Author: Rodrigo Balerdi
Contact: lanchon at hotmail dot com
Initial Post: 17-JUN-2004
Last Update: 26-JUL-2004
This page summarizes my findings concerning the Dakota Digital Camera. This work builds on reverse engineering efforts done by many people, most prominently John Maushammer (see his Dakota page) who was the first to download pictures from the camera among other things. None of this could have been done without John's invaluable help. Tim Gipson (also has a Dakota page) has also helped a lot with debugging and testing.
[UPDATE: Until now, the only other firmware version I know of is 184.108.40.206 (MD5 hash: E9AD9806 BC54C35F A92B9751 D165BE51). If you happen to have one that is not any of these two, please contact me.]
Dakota USB Driver:
A portable driver to access the Dakota camera via USB.
The driver permits development of software for the Dakota that does not depend on a particular implementation
of the USB stack.
The implementation is based on libusb,
a library ported to many operating systems including various Unix and Windows platforms,
so the driver implementation should be portable to these platforms.
If libusb is not available for a certain platform, a native driver implementation should be easily done.
The only other non-portable API is encapsulated in file
timingutils.cpp which declares
a couple of functions that handle timing, and should be easily ported to any platform.
Dakota Memory API: An API that provides read/write access to the camera's external memory space, the firmware flash, and the DRAM. There is a method that permits bytewise programming of the firmware flash, with the limitation that bits can only be cleared, not set, in the firmware byte. You could use this to perform some modifications to the firmware flash, but I strongly recommend using the bulk firmware updater instead (see below). A picture flash read/erase/program API could be built on top of this (a read-only non-ECC API was implemented by John), but it would be terribly slow. I'd rather try to find the bulk APIs I guess the camera must have. Meanwhile, I've analyzed the ECC (error checking and correction) method of the picture flash and written a Java API to take care of it.
[UPDATE: I've added bulk access to the DRAM running at about 8 MBit/s. Also, now I know how to access the picture flash in bulk, but I'm being lazy and not coding it. One problem remains concerning picture flash access, though. The bulk access method I mention completely bypasses the firmware and directly uses hardware I call "data pump" (for lack of a better name) that transfers data between any two camera peripherals such as the picture flash and the USB controller. The problem is this: using whatever low-level method you choose to access the flash that bypasses firmware, although you can write to the flash, you are not invalidating the cached structures that the firmware may maintain to speed up its access. In particular, the firmware has a flash transaction layer that caches the physical address of all logical blocks in the flash. It may also cache higher level structures, such as parts of the FAT (but I'm inclined to think this does not present a real problem in this case). So if after low-level writes to the flash and before rebooting the camera the firmware tries reading the flash it may read invalid data, and if it writes to it it may cause data corruption at the FTL level and above. Hence the importance of accessing the flash via the firmware's FTL implementation if you are going to write to it. How to do this or even whether it is possible is not known to me, and I'm not investigating this either.]
Dakota Firmware Update Tool: Firmware update is done in cooperation with the currently installed firmware, so an update failure will ruin your camera. There are two update types, erasing and non-erasing. An erasing update lets you program any firmware image, but because it erases the flash memory before programming, an interrupted update will leave you with a partially clear firmware and an almost sure ruined camera. A non-erasing update is less risky as it skips the erasing operation, but it can only clear firmware bits, not set them, an thus can only be used for hacks. When performing a non-erasing update, the tool will check whether the named firmware image can be programmed only by clearing bits, and will abort if not possible without touching the camera. The tool can also download the current firmware, query the firmware version, etc.
WARNING: USE AT YOUR OWN RISK !!! AN INTERRUPTED OR OTHERWISE FAILED FIRMWARE UPDATE WILL RUIN YOUR CAMERA, AS YOU PROBABLY WILL NOT BE ABLE TO UPDATE AGAIN. THE SAME APPLIES TO A SUCCESSFUL UPDATE WITH A BUGGY FIRMWARE FILE. USE AN UNINTERRUPTABLE POWER SUPPLY IF POSSIBLE. INSTALL FRESH BATTERIES. (NOT KNOWN IF BATTERIES CAN POWER THE CAMERA THROUGH THE CRITICAL PART OF AN UPDATE IN THE EVENT OF A USB POWER FAILURE, PROBABLY NOT.) DO NOT MULTITASK WHILE UPDATING. DO NOT TOUCH ANY WIRES. UNPLUG AND REPLUG THE CAMERA BEFORE UPDATING. BY USING THIS SOFTWARE YOU ACCEPT FULL RESPONSIBILITY FOR WHATEVER HAPPENS. THE AUTHOR IS NOT LIABLE IN ANY WAY IF THIS SOFTWARE RUINS YOUR CAMERA.
There are two other factory-programmed areas that accompany the firmware. These are the static configuration and the sunplus configuration areas, and I know how to read and reprogram both. Maybe this functionality should be included with the firmware tool, but it is not clear if data in these areas must match the firmware or some other component of the camera (specially the sunplus area). The static area was not observed to change between cameras, and it makes sense that it remains mostly stable.
Dakota Configuration Tool: A tool that lets you alter the dynamic non-volatile configuration of your camera. For now, this tool only lets you modify the maximum number of pictures the camera will take and the camera lock status. The camera is factory-limited to 25 pictures. However, that only uses a small portion of the 16MB picture flash memory. With this tool you can configure a higher picture count limit and use all the available memory. The number of pictures that will fit in the memory depends on the size of the pictures, which varies with image complexity. In practice, I was able to shoot around 90 to 100 pictures, sometimes over 110. I'd recomend using a limit of 199 pictures. The display will show 99 and decrement with each shot. In case more than 100 pictures fit in the memory, the display will rollover from 00 to 99 again and keep shooting. When no more pictures fit, the camera will keep shooting and firing the flash, but the display will not decrement. If you don't like the rollover you can configure a limit of 99. The camera lock status is a flag that can be set or cleared at will. When set the camera will not shoot nor delete pictures. I think this functionality was built to help employees handle the camera and avoid accidental shots to occur on cameras partially used by customers. I know the workings of a number of other configuration commands that permit setting the serial number, setting the tagging dword (a tag returned by request 0x2D, index 4), enabling or disabling the "thirties interface" (requests 0x33, 0x36 and 0x37 which are disabled by default), and managing the bad pixel list. For now I haven't included these capabilities in the tool.
Dakota Info Tool: A tool that displays information about your camera, including firmware version, MD5 hash of the firmware, and dumps of the static and dynamic non-volatile configuration areas.
Dakota Code Loader API and Tool: A tool that lets you execute custom code from RAM in your camera. The camera can be switched into a special mode where the lowest 4 of the 6 KB of extrernal memory are also mapped into code memory space. This tool lets you upload images for the code, external and DRAM memories and then transfers execution to your program. The properties of the images that this tool can upload are as follows:
|Image||Load Address||Maximum Image Size||Corresponding Memory Size|
|Code||000x0000||000x0FF0 (4 KB - 16 bytes)||000x1000 (4 KB)|
|External||000x1000||000x0800 (2 KB)||000x0800 (2 KB)|
|DRAM||0x000000||0x7FE800 (8 MB - 6 KB)||0x800000 (8 MB)|
Code execution begins at address 0x0000 (the reset vector) with this state: registers A, B, DPTR, PSW, IE, IP and PCON cleared, internal memory cleared (and thus Rn registers of all banks cleared), interrupt-in-progress flip-flops cleared, and the stack pointer set to 0x07. All other hardware state is undefined. There are two related methods to transfer execution to the uploaded program, fast and safe. Fast takes a fraction of a second but may not work with all firmware versions. Safe takes around 10 seconds and should work with all versions. The fast method works fine with the two firmwares known to me until now: versions 220.127.116.11 and 18.104.22.168. The tool includes an option to test whether the fast method is appropriate for your camera.
The code loader works like this. First a composed image of the code, external and DRAM images is uploaded bulk to the DRAM. Then a bootstrap loader is transfered into external memory, to an address known to be within a 0x210 byte buffer used by the firmware to read and write the picture flash memory. The buffer is at the same address in both known firmware versions, and even if it moved it would be expected that it would not move much. The firmware will not overwrite any part of this buffer while it is doing its idle chores, so the bootstrapper is safe. Replacement reset and interrupt vectors are then built in external memory that point to the loader. Also, if safe mode was requested, the rest of the external memory is filled with jmp 0x0000 instructions (0x0000 is the address of the reset vector). These instructions are encoded as a non-zero opcode followed by a zero operand. Zero is also the opcode for nop (the no operation instruction), so if after switching external memory into code space execution happens to fall in the middle of a jump instruction, the CPU will execute nops until reaching and executing the next jump thus staring the loader anyway. Execution should not fall in the middle of the loader, as its address was chosen not only to be within said buffer in external memory, but also to be within the addresses occupied by firmware routines in code memory used to update the firmware, which are obviously not in use at the time of the transfer of control. These firmware routines are not expected to move much either, since there are good reasons to make them the first routines in the firmware (and they are in both known firmwares). Finally external memory is switched into code space in readying for the execution of the loader, which typically happens when a periodic interrupt is triggered.
Then the bootstrap loader kicks in. First it relocates itself towards the end of the mapped-in memory. Then it copies the code and external images from DRAM to their final destinations, but leaving untouched a hole in code memory which is occupied by the relocated loader itself. The data corresponding to this hole is copied to internal memory instead. Finally the hole is mostly filled from internal memory, internal memory is cleared, registers are initialized, and control is transfered to the reset vector of the uploaded program. After these steps, only the last 16 bytes of code memory are not initialized to user code, and this number includes a small margin for updating the loader if needed. While the loader does these things, it also checks for two conditions to hold. One is that the checksum of itself must be valid. The other is that execution must have started from the begining of the loader. If these conditions do not hold, bootstrapping is aborted and the camera hangs while rapidly flashing the LED to signal the error, so it would be very unlikely that control ended up being transfered to user code by a damaged loader. I have never seen the loading process fail, either blinking or just by not working, and I would appreciate that you contact me if you ever do.
Included with the tools is a Dakota executable file named
ledpwm.dkx. It is a very simple example program that pulse-width
modulates the LED of the camera. It is written in C and compiled using SDCC.
You can use it to test the code loader tool. Sources of the bootstrap loader, the fast/safe upload method test,
and the test executable are all included of course.
You can download the whole thing from here. It is provided under the GNU GPL license, see the included LICENSE file for details. The package contains the portable sources and compiled Windows binaries. The binaries were compiled using BCC32 5.5.1, Borland's free C++ compiler for Windows. It also includes version 0.1.8.0 binaries of libusb-win32, a Windows port of libusb, and libmd5-rfc, an MD5 hash library by Peter Deutsch.
Please drop me a line if you use this software, tell me if it worked with your camera, or what you are doing, or whatever. I'd appreciate a copy of the output of the Dakota Info tool ran against your camera.
To analyze the camera firmware I'm using a modified version of Mark Hopkins' 8051 disassembler. The disassembler is hacked to produce better cross referencing and to handle some stack-funny routines in the version of the firmware I'm working on, so don't use it as it is for anything else. You can download it from here.
NOTE FOR WINDOWS USERS: Some people experience a "more than one camera found" error when running any of these tools under Windows. This seems to be some kind of libusb problem. I am able to reproduce it by installing a SnoopyPro snoop on the camera, and even after removing it the problem persists. I've made a hack I dislike to my USB driver to cope with this problem in some situations. However, to cope with all situations I'd have to cripple the driver too much and I don't want to. The solution that works for me is to reinstall the libusb drivers. Here is how (for Windows XP, steps for other versions should be similar): Open the device manager (open the "System" control panel application, click the "Hardware" tab, and click "Device Manager"). Select "View/Devices by connection". Find the two Dakota entries ("ISO" and "Bulk"), they should be within your host controller. This two entries should be directly contained by an "USB Composite Device". Right-click on this device and choose "Uninstall". The drivers are gone. Now choose "Action/Scan for hardware chagnes" or unplug and replug the camera, and the "Found New Hardware Wizard" should come up twice, once for the ISO interface and once for the bulk interface. For each interface do the exactly the same: Select "Install from a list or specific location" and click "Next". Select "Don't search, I will choose the driver to install" and click "Next". Now a list should come up where you should choose the "Dakota Digital Camera, ISO/Bulk Interface, version 02/15/2004 0.1.8.0" entry. (If it's not there click "Have Disk..." and browse to the "dakota-driver-win32-0.1.8.0" directory that's included in the distribution of these tools, and the entry should be added to the list.) Click "Next". If Windows complains about the driver not being digitally signed or not having passed Windows Logo testing or the like, just ignore it and click "Continue Anyway". After you've done this twice (once for each interface) your "more than one camera found" problem should be solved. Please tell me if this workaround helped you.
|Instruction||Byte Count||Cycle Count|
|mov A, Rn
mov Rn, A
|mov A, #xx
mov Rn, #xx
|mov DPTR, #xxxx||3||3|
|djnz Rn, label
(whether jump is taken or not)
The CPU core is probably based on some freely available synthesizable 8032 core, and this table could help identify which.
[To be updated.]
The low level format of the Dakota flash is very similar to that of standard SmartMedias, except that the first 8 blocks of the flash are reserved for camera configuration purposes. Although not a requirement of SmartMedia, the particular Samsung chip used by the Dakota guarantees that block 0 will be defect-free. Any other particular block may be defective, but there is a limit on how many are.
There are 4 configuration areas stored in the first 8 blocks of the flash. All of them are stored at fixed addresses. All but one are stored two times to cope with the possibility of a certain block being defective (the one that is not is stored at block 0 which is guaranteed to be defect-free). This strategy is ill-conceived for two reasons: there is no wear leveling algorithm, and if by chance the two blocks corresponding to a particular configuration area are defective the camera will fail.
Here is a map of the picture flash contents:
|0||8||0x1000||Bad pixel list for defect concealment
Four bytes per pixel (x,y coords. LSB first).
|1||0||0x4000||Static configuration area
Template to regenerate dynamic configuration.
|2||0 - 15||0x8000||Sunplus configuration area
Tables, matrices, etc. loaded at DRAM address
0x2B8000 (0x15C000 * 2).
|3||0||0xC000||Static configuration area
|4||0 - 15||0x10000||Sunplus configuration area
|5||0||0x14000||Dynamic configuration area
Configuration and non-volatile variable area.
|6||0||0x18000||Dynamic configuration area
|Start of SmartMedia Area|
|8||0 - 1||0x20000||SmartMedia CIS
(four copies, 256 bytes each,
relocated forward if block is defective)
|(NOTE: All used pages up to here have zero block addresses.)|
|Start of SmartMedia FTL Storage Area|
|9 - 1023||Used, free or defective blocks of the FTL|
[To be updated.]
[To be updated.]
[To be updated.]
(will reinitialize data if not there,
see firmware 22.214.171.124, 0xA27D and 0x5B17)
(will default data if not there,
see firmware 126.96.36.199, 0x59FB)
|0x105||1||Number that will be assigned to next shot|
|0x106||1||Delete available status
(1: yes, 0: no)
|0x10F||1||"Thirties interface" enable status
(0x00: enabled, 0xFF: disabled)
|0x110||1||Picture count limit|
|0x180||1||Camera lock status
(0x5A: locked, 0xFF: unlocked)
(camera seems to treat tag as obscure data)
|0x1F0||12||Camera extended serial number
(should start with "BA")
[To be updated.]
[To be updated.]
[To be updated.]
[To be updated.]
[To be updated.]
[To be updated.]
But I decided I won't do it. Tag reading is a startup activity and if I mess up somehow the camera could hang on startup. I wouldn't be able to flash a corrected firmware and the camera would be ruined. And I just got one, and I live in Argentina so getting another would be difficult for me. It's not worth the risk.
I've posted a patched firmware that always stores pictures starting at number 1 and does not wrap around, so more than 254 can be taken safely. Deletions decrement the counter (never any holes). It survives configuration data losses as well as the original firmware (and does not get confused). With the patch, the numbering for the next shot comes from the number of pictures in the camera. Being the case that only the last taken shot can be erased, this will never cause duplicate filenames. The old "next picture" configuration variable (which is 8 bit wide and wraps back at 254) is still maintained (incremented) but is completely ignored. A different solution would have been to extend the "next picture" variable to 16 bits, but I liked the back to 1 policy better.
[UPDATE: I was wrong! A brave man updated his version 188.8.131.52 firmware with version 184.108.40.206 and it didn't work. The display showed "Er" and the camera would do nothing. Apparently a dependency on configuration data. Fortunately, all it took to fix it was to flash the old firmware back and the camera fully recovered. Lucky guy!]
THIS FIRMWARE PATCHES ARE DISTRIBUTED FREELY WITHOUT ANY GUARANTEE. USE THEM AT YOUR OWN RISK !!!