Dakota Digital Camera

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.

Software

These tools are mostly written in portable C++, unless noted. Except for the basic read/write access to the external memory space and read access to the firmware flash, these tools provide all-new functionality not available elsewhere, and are the result of my ongoing analysis of the firmware. They were developed against firmware version 1.42.6.0 (MD5 hash: F613FD39 45B6EFD3 8BE64ECD 517828E3), but should work on all versions. Some of my findings are reported in the next sections.

[UPDATE: Until now, the only other firmware version I know of is 1.38.3.0 (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 1.38.3.0 and 1.42.6.0. 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.

Download Software

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.

Camera Information

[NOTE: There's a lot to write in these sections and I don't have much time, and I don't think a lot of people are interested in this information anyway. So I don't know when, if ever, I'm going to write it down. Email me if you could use this info.]

CPU Timing

The CPU core in the Sunplus chip is not cycle-compatible with the original Intel 8052 series controllers. Instruction cycles run at a rate of 6.0 MHz (167 ns period). In this core the instruction byte count has a stronger weight in determining the cycle count than in the original controllers, hinting a lower clock to instruction cycle rate. Also, jumps take a hit compared to other instructions, hinting the existance of some pipelining. Here is the data for some instructions:

Instruction Byte Count Cycle Count
nop 1 1
mov A, Rn
mov Rn, A
1 1
mov A, #xx
mov Rn, #xx
2 2
mov DPTR, #xxxx 3 3
djnz Rn, label
(whether jump is taken or not)
2 3
sjmp label 2 3
ljmp label 3 4

The CPU core is probably based on some freely available synthesizable 8032 core, and this table could help identify which.

The Data Pump

The data pump is a peripheral that transfers data between any two of a certaing group of camera peripherals. Source and destination peripherals are identified by a number: CPU (a register based interface actually) is 0, USB (bulk) is 1, picture flash is 2, and DRAM is 3. (Source and destination may both be the same peripheral, as well as it is not USB and the pump is set to manual mode.) There are two operational modes. In manual mode, a configurable ammount of data in the range of 1 to 0x400 bytes is inputted from the source peripheral to a FIFO during the input phase. Then, when the output phase is separately triggered, the data is outputted from the FIFO to the destination. (This is all supposing that the source and destination are correctly configured and willing to deal with that ammount of data.) In automatic mode, data is transfered continuously and the transfer ends when either the source or the destination has had enough (the definition of this is peripheral dependant). Some peripherals impose additional restrictions regarding the transfer size. For example, since DRAM is 16 bits wide it prefers even sizes, and USB likes multiples of 0x80. To see how to program the data pump, take a look at DRAM bulk access in dakotamemory.cpp.

The DRAM Controller

The DRAM controller provides access to the 16 bit wide DRAM. It provides two interfaces, one for the CPU (register based) and one for the data pump. It appears that both can operate simultaneously. All addresses are word addresses (two consecutive addresses delimit two bytes, not one, on account of the 16 bit data width). To see how to use both interfaces, take a look at dakotamemory.cpp.

Updating the Firmware Flash

Request 0x10, index 0. A signature must be set in the uploaded firmware or the update will fail ruining the camera. The signature is invalidated by the firmware in the camera before it is written to the firmware flash. See dakotafirmware.cpp.

[To be updated.]

Accessing the Picture Flash

[To be updated.]

The Picture Flash Memory Map

The 16 MB picture flash memory is composed of 1024 blocks. Each block is made up of 32 pages. Each page has 512 bytes of main data and 16 bytes of out-of-band spare data used for page and block status, error correction, etc. The erase unit is the block. The read/program unit is the page.

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:

Block Page Address Contents
0 8 0x1000 Bad pixel list for defect concealment
(single copy)
Four bytes per pixel (x,y coords. LSB first).
1 0 0x4000 Static configuration area
(first copy)
Template to regenerate dynamic configuration.
2 0 - 15 0x8000 Sunplus configuration area
(first copy)
Tables, matrices, etc. loaded at DRAM address
0x2B8000 (0x15C000 * 2).
3 0 0xC000 Static configuration area
(second copy)
4 0 - 15 0x10000 Sunplus configuration area
(second copy)
5 0 0x14000 Dynamic configuration area
(first copy)
Configuration and non-volatile variable area.
6 0 0x18000 Dynamic configuration area
(second copy)
7 Empty block
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

Updating the Bad Pixel List

Request 0x11, any index.

[To be updated.]

Reading the Configuration Areas

Static configuration: request 0x13, any index.
Dynamic configuration: request 0x12, any index.

[To be updated.]

Updating the Static and Sunplus Configuration Areas

Static configuration: request 0x10, index 1.
Sunplus configuration: request 0x10, index 2.

[To be updated.]

The Dynamic Configuration Area

Here is a map of the dynamic area contents:

Address Length Contents
0x100 1 Signature: 0xAA
(will reinitialize data if not there,
see firmware 1.38.3.0, 0xA27D and 0x5B17)
0x101 1 Signature: 0x55
(will default data if not there,
see firmware 1.38.3.0, 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)
0x1E0 4 Camera tag
(camera seems to treat tag as obscure data)
0x1F0 12 Camera extended serial number
(should start with "BA")

[To be updated.]

Configuring the Dynamic Area

Picture Count Limit

Request 0x55, index 2.

[To be updated.]

Camera Lock Status

Request 0x55, indexes 0 and 1.

[To be updated.]

Camera Extended Serial Number

Request 0x58, index 0.

[To be updated.]

Camera Tag

Request 0x58, any index but 0.

[To be updated.]

"Thirties Interface" Enable Status

Request 0x38, index 0 and any index but 0.

[To be updated.]

Firmware Hacks

Faster Camera Startup

The format of the picture flash memory of the Dakota is based on the SmartMedia standard. In SmartMedias all data is affected by a level of indirection to tolerate defective blocks and to provide wear leveling. The logical blocks of data are physically all scrambled inside the SmartMedia. Each physical block has a tag that informs a piece of software called the flash translation layer (FTL) what the logical address of the block is. When the Dakota powers up, it scans the entire picture flash to read all the tags. This takes most of the startup time. SmartMedias have a specific command to read tags, however the Dakota does not use it and reads the whole contents of the flash (tags + data) to do this scan. This is unnecessarily slow and could be improved.

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.

Pictures Taken Count Display

I've posted a patched firmware that displays the number of pictures taken instead of the number of remaining pictures. The "remaining" display text in the LCD will normally be off, but it will turn on in case there are more than 99 pictures taken, indicating overflow. For example, a display number of "07" with the "remaining" display text on indicates that there are 107 pictures taken (or 207, but it is mostly useless to program a picture limit of more than 199).

Fixing the Picture Numbering Bug

The camera remembers the number of the last taken shot (outside of the FAT, in the dynamic configuration area) and increments it to number the next shot. Deleting a shot does not decrement the counter. Unfortunately the picture number wraps back from 254 to 1. Also, when you turn off the camera and then turn it back on, there is a bolted on check that does this: if the current picture number is less than the number of stored pictures, it is set to be equal. This is a cheap attempt to survive a configuration data loss without corrupting the filesystem with duplicate filenames. It explains the common disorder found in the picture numbers. Furthermore, the camera can take two or more shots and assign them the same number. (Just think of the simple case of repeatedly shooting and deleting.) That makes all affected shots but the first impossible to download (all shots are listed in the TOC but only the first one can be downloaded) and the shots are lost (unless you dump the whole flash and fish the file from the filesystem yourself). This has sometimes happen unintendedly to others and me.

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.

Compatibility With a Comercial Camera ???

[To be updated... soon?]

Firmware Patches

WARNING: These are firmware patches done by me on firmware version 1.42.6.0 (MD5 hash: F613FD39 45B6EFD3 8BE64ECD 517828E3). You MUST have an original firmware file of this version of the firmware in order to use this patches, as they are distributed as an xor file of the original (a kind of difference file) in order to avoid copyright issues. In addition, your camera SHOULD have this firmware version (or a patch based on this version) installed. If not you'd be upgrading the firmware version, and that could cause incompatibilities in the format of the configuration areas which are NOT changed by the firmware update tool (though I don't think this is likely to happen).

[UPDATE: I was wrong! A brave man updated his version 1.38.3.0 firmware with version 1.42.6.0 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 !!!

22-JUN-2004

In this update: Instructions:


Copyright 2004, Rodrigo Balerdi
http://www.balerdi.com.ar/dakota
USE AT YOUR OWN RISK !!!