I was working on getting the DCS-930L camera support working several years back on the old forum, but eventually gave up due to USB issues that prevented the camera to work. Having a bunch of these cameras and with D-Link not having released a firmware for the last 5 years I decided to give this another shot, and after a ton of issues finally managed to get it working without requiring soldering a serial console to it. I know this is a 4/32 device and that support for these in general is going away, but hopefully there's still an opportunity to keep these working.
The Wiki page is quite outdated (I can see if I can update it later on), but as stated in the forum thread above one of the biggest challenges with this device is the stock firmware layout. In the stock firmware there is only one partition listed as "Kernel" or "Firmware" depending on version, in addition to the bootloader, config and factory settings partitions:
Creating 4 MTD partitions on "Ralink SoC physically mapped flash":
0x00000000-0x00030000 : "Bootloader"
0x00030000-0x00040000 : "Config"
0x00040000-0x00050000 : "Factory"
0x00050000-0x00400000 : "Kernel"
Problem here though is that while not showing up in the bootlog above this partition is actually split into two, and the kernel one is only 1MB in size. So any attempt to flash this device with a kernel bigger than that will fail as long as you do it through the emergency web interface, which without soldering is the only practical way of doing it. I spent a lot of time trying to slim down the current kernel in 19.07 to get below this limit, and finally managed to build one that was just a few KB below the limit. Sadly I despite much testing could not get this one to properly read the partitions after flashing it through the emergency web interface, where I got this on the serial console:
VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
Please append a correct "root=" boot option; here are the available partitions:
1f00 192 mtdblock0
(driver?)
1f01 64 mtdblock1
(driver?)
1f02 64 mtdblock2
(driver?)
1f03 3776 mtdblock3
(driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
Rebooting in 1 seconds..
I initially thought I had just slimmed it down too much, but oddly enough booting with the current official initramfs kernel over TFTP gives the same error. Having worked on this device years back I did have an old firmware though that I knew booted. Flashing that one through the emergency web interface worked. Turns out that ssh wasn't working in that image without a root password set, but luckily telnet did, allowing me to not have to have serial access. Through telnet I logged into the device and could then scp a more proper firmware to the device and flash it through sysupgrade. The initial 1MB kernel limitation is only an issue when using the emergency web interface, so now I could re-flash again with a more proper firmware:
killall: telnetd: no process killed
Sending TERM to remaining processes ... ntpd ubusd urngd logd rpcd netifd
Sending KILL to remaining processes ...
Performing system upgrade...
Unlocking firmware ...
Writing from <stdin> to firmware ...
Upgrade completed
Rebooting system...
umount: can't unmount /dev: Resource busy
umount: can't unmount /tmp: Resource busy
umount: can't unmount /: Ireboot: Restarting system
þ
U-Boot 1.1.3
Board: Ralink APSoC DRAM: 32 MB
relocate_code Pointer at: 81fac000
config usb..
******************************
Software System Reset Occurred
******************************
flash_protect ON: from 0xBF000000 to 0xBF021767
flash_protect ON: from 0xBF030000 to 0xBF030FFF
============================================
Ralink UBoot Version: 3.5.2.0
--------------------------------------------
ASIC 3052_MP2 (Port5<->None)
DRAM component: 256 Mbits SDR
DRAM bus: 16 bit
Total memory: 32 MBytes
Flash component: NOR Flash
============================================
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:128, ways:4, linesz:32 ,total:16384
##### The CPU freq = 320 MHZ ####
estimate memory size =32 Mbytes
Signature: DCS-930 Release 1.11 (2011-05-31)
Please choose the operation:
1: Load system code to SDRAM via TFTP.
2: Load system code then write to Flash via TFTP.
3: Boot system code via Flash (default).
4: Entr boot command line interface.
7: Load Boot Loader code then write to Flash via Serial.
9: Load Boot Loader code then write to Flash via TFTP.
0
3: System Boot system code via Flash.
## Booting image at bf050000 ...
Image Name: MIPS OpenWrt Linux-4.14.215
Created: 2021-01-19 13:10:02 UTC
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 1256560 Bytes = 1.2 MB
Load Address: 80000000
Entry Point: 80000000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80000000) ...
## Giving linux memsize in MB, 32
Starting kernel ...
Linux version 4.14.215 (builder@buildhost) (gcc version 7.5.0 (OpenWrt GCC 7.5.0 r11278-8055e38794)) #0 Tue Jan 19 13:10:02 2021
SoC Type: Ralink RT3350 id:1 rev:2
bootconsole [early0] enabled
CPU0 revision is: 0001964c (MIPS 24KEc)
MIPS: machine is D-Link DCS-930
Determined physical RAM map:
memory: 02000000 @ 00000000 (usable)
Initrd not found or empty - disabling initrd
Primary instruction cache 32kB, VIPT, 4-way, linesize 32 bytes.
Primary data cache 16kB, 4-way, VIPT, no aliases, linesize 32 bytes
Zone ranges:
Normal [mem 0x0000000000000000-0x0000000001ffffff]
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x0000000000000000-0x0000000001ffffff]
Initmem setup node 0 [mem 0x0000000000000000-0x0000000001ffffff]
random: get_random_bytes called from 0x803926ec with crng_init=0
Built 1 zonelists, mobility grouping on. Total pages: 8128
Kernel command line: console=ttyS0,57600 rootfstype=squashfs,jffs2
PID hash table entries: 128 (order: -3, 512 bytes)
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Writing ErrCtl register=0002f9d0
Readback ErrCtl register=0002f9d0
Memory: 27348K/32768K available (3070K kernel code, 167K rwdata, 412K rodata, 1208K init, 196K bss, 5420K reserved, 0K cma-reserv)
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS: 256
CPU Clock: 320MHz
timer_probe: no matching timers found
clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 11945377789 ns
sched_clock: 32 bits at 160MHz, resolution 6ns, wraps every 13421772796ns
Calibrating delay loop... 212.58 BogoMIPS (lpj=1062912)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: -1, 3072 bytes)
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
rt2880_gpio 10000600.gpio: registering 24 gpios
rt2880_gpio 10000600.gpio: registering 24 irq handlers
clocksource: Switched to clocksource MIPS
NET: Registered protocol family 2
TCP established hash table entries: 1024 (order: 0, 4096 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
rt-timer 10000100.timer: maximum frequency is 3255Hz
workingset: timestamp_bits=30 max_order=13 bucket_order=0
squashfs: version 4.0 (2009/01/31) Phillip Lougher
jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
io scheduler noop registered
io scheduler deadline registered (default)
Serial: 8250/16550 driver, 16 ports, IRQ sharing enabled
console [ttyS0] disabled
10000c00.uartlite: ttyS0 at MMIO 0x10000c00 (irq = 20, base_baud = 6666666) is a Palmchip BK-3103
console [ttyS0] enabled
console [ttyS0] enabled
bootconsole [early0] disabled
bootconsole [early0] disabled
1f000000.cfi: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x0000c2 Chip ID 0x0022a8
Amd/Fujitsu Extended Query Table at 0x0040
Amd/Fujitsu Extended Query version 1.1.
number of CFI chips: 1
4 fixed-partitions partitions found on MTD device 1f000000.cfi
Creating 4 MTD partitions on "1f000000.cfi":
0x000000000000-0x000000030000 : "u-boot"
0x000000030000-0x000000040000 : "u-boot-env"
0x000000040000-0x000000050000 : "factory"
0x000000050000-0x000000400000 : "firmware"
2 uimage-fw partitions found on MTD device firmware
Creating 2 MTD partitions on "firmware":
0x000000000000-0x000000132cb0 : "kernel"
0x000000132cb0-0x0000003b0000 : "rootfs"
mtd: device 5 (rootfs) set to be root filesystem
1 squashfs-split partitions found on MTD device rootfs
0x000000340000-0x0000003b0000 : "rootfs_data"
libphy: Fixed MDIO Bus: probed
rt3050-esw 10110000.esw: link changed 0x01
mtk_soc_eth 10100000.ethernet eth0: mediatek frame engine at 0xb0100000, irq 5
rt2880_wdt 10000120.watchdog: Initialized
NET: Registered protocol family 17
bridge: filtering via arp/ip/ip6tables is no longer available by default. Update your scripts to load br_netfilter if you need th.
8021q: 802.1Q VLAN Support v1.8
VFS: Mounted root (squashfs filesystem) readonly on device 31:5.
Freeing unused kernel memory: 1208K
This architecture does not have kernel memory protection.
random: fast init done
init: Console is alive
init: - watchdog -
kmodloader: loading kernel modules from /etc/modules-boot.d/*
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
dwc2 101c0000.otg: Configuration mismatch. dr_mode forced to host
dwc2 101c0000.otg: DWC OTG Controller
dwc2 101c0000.otg: new USB bus registered, assigned bus number 1
dwc2 101c0000.otg: irq 26, io mem 0x101c0000
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
kmodloader: done loading kernel modules from /etc/modules-boot.d/*
init: - preinit -
usb 1-1: new full-speed USB device number 2 using dwc2
8021q: adding VLAN 0 to HW filter on device eth0
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
random: procd: uninitialized urandom read (4 bytes read)
mount_root: jffs2 not ready yet, using temporary tmpfs overlay
urandom-seed: Seed file not found (/etc/urandom.seed)
procd: - early -
procd: - watchdog -
open: No such file or directory
random: jshn: uninitialized urandom read (4 bytes read)
random: ubusd: uninitialized urandom read (4 bytes read)
random: ubus: uninitialized urandom read (4 bytes read)
Command failed: Not found
procd: - init -
Please press Enter to activate this console.
kmodloader: loading kernel modules from /etc/modules.d/*
i2c /dev entries driver
Linux video capture interface: v2.00
Loading modules backported from Linux version v4.19.161-0-gdaefdc9eb24b
Backport generated by backports.git v4.19.161-1-0-g4bb568fe
nf_conntrack version 0.5.0 (1024 buckets, 4096 max)
xt_time: kernel timezone is -0000
ip_tables: (C) 2000-2006 Netfilter Core Team
usbcore: registered new interface driver snd-usb-audio
urngd: v1.0.2 started.
uvcvideo: Found UVC 1.00 device <unnamed> (1b3b:2970)
uvcvideo: UVC non compliance - GET_DEF(PROBE) not supported. Enabling workaround.
input: UVC Camera (1b3b:2970) as /devices/platform/101c0000.otg/usb1/1-1/1-1:1.0/input/input0
usbcore: registered new interface driver uvcvideo
USB Video Class driver (1.1.1)
rt2800_wmac 10180000.wmac: loaded eeprom from mtd device "factory"
ieee80211 phy0: rt2x00_set_rt: Info - RT chipset 2872, rev 0200 detected
ieee80211 phy0: rt2x00_set_rf: Info - RF chipset 0005 detected
kmodloader: done loading kernel modules from /etc/modules.d/*
random: crng init done
random: 6 urandom warning(s) missed due to ratelimiting
jffs2_scan_eraseblock(): End of filesystem marker found at 0x0
jffs2_build_filesystem(): unlocking the mtd device...
done.
jffs2_build_filesystem(): erasing all blocks after the end marker...
8021q: adding VLAN 0 to HW filter on device eth0
br-lan: port 1(eth0) entered blocking state
br-lan: port 1(eth0) entered disabled state
device eth0 entered promiscuous mode
br-lan: port 1(eth0) entered blocking state
br-lan: port 1(eth0) entered forwarding state
done.
jffs2: notice: (986) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of.
overlayfs: upper fs does not support tmpfile.
To fit the new firmware onto the small flash I had to slim it down considerably, but not having the 1MB kernel limit anymore it was not any issues building a firmware that is fully functional for it's intended use case. With networking + wireless, ssh and mjpg-streamer built in I still have about 500KB left for the JFFS2 partition. I have removed anything not strictly needed to run the camera part, like LUCI and also took out IPv6 support. I did the steps above on a second DCS-930 A1 device lacking serial console, and it worked fine there too.
mjpg-streamer requires a bit of configuration changes to work, I will try to work that into the firmware itself to not waste JFFS2 space changing it. Here's the config I have for it now:
root@OpenWrt:~# cat /etc/config/mjpg-streamer
config mjpg-streamer 'core'
option enabled '1'
option input 'uvc'
option output 'http'
option device '/dev/video0'
option resolution '640x480'
option fps '5'
option led 'auto'
option www '/www/webcam'
option port '8080'
Streaming works really well, it consumes 10-20% CPU only, doing a continuous stream over HTTP. I will stream to Zoneminder so I can do the motion detection there, but in the past I know people have successfully run motion on the camera as well. Oddly enough mjpg_streamer seems to do some sort of motion detection on it's own too:
user.notice root: webcam motion event
For anyone interested I'll make my old firmware available for initial flashing, and the config for the new one too. I will give it another shot getting a version based on 19.07 compiled as well, but it will be so slimmed down that it will probably still be hard to provide it as an official factory image. Since it is only needed once maybe that isn't a big issue though. Creating a working official sysupgrade image should be doable though I think.