Talk:DPF with AppoTech AX206

From ST2205u wiki

I renamed page (since there are other devices rather than only this from DX with AX206). Also, since a user said that the Firmware is loaded by a bootloader from the SPI memory, I think this device can be hacked as well --Socram8888 11:07, 12 August 2010 (CEST)

New DPF Variant

Moved from DPF with AppoTech AX203 --Socram8888 11:11, 12 August 2010 (CEST)

I'm receive digital frame with different construction. In frame placed MCD AX206 (may be AX208, hieroglyphically). Placed flash marked as M80A80CG (Excel Semiconductor ES25M80A by JEDEC ID). LCD have 20 pins on flat cable. On Appotech i read, than MCU AX206 have:

  • 4K bytes Mask-ROM Program Memory
  • 3K bytes SRAM which can be used as Xdata and Program Memory(IRAM)

Linux detect this DPF as:

 [259667.688984] usb 5-3.3: New USB device found, idVendor=1908, idProduct=0102
 [259667.688984] usb 5-3.3: New USB device strings: Mfr=2, Product=3, SerialNumber=1
 [259667.688984] usb 5-3.3: Product: Digital Photo Frame
 [259667.688984] usb 5-3.3: Manufacturer: BUILDWIN
 [259667.688984] usb 5-3.3: SerialNumber: 200807101900000000

I read CD image from frame (dd if=/dev/sr0 of=dpf-ax206.img), later, on home, i try read flash. Also make photos.


Concerning AX206, I received the following answers from Appotech:
1) Does the AX206 contain a bootstrap loader via UART interface?

AX206 is a mask ROM version with boot loader program on-chip. Customer program is stored at external SPI Flash via SPI interface.

2) Is it possible to program the AX206 OTP codememory in-application? How many pins are needed?

Yes, it is possible to modify the external SPI code memory in-application.

It can modify through the SPI interface.

3) Is AX206 only available with OTP memory or also with flash memory?

AX206 is only provided in MASK ROM.

So maybe there should be 8051 code somewhere in your flash image.

Where did you buy this photoframe using an AX206?

cu, Mic

I bought this [1] device on DealExtreme, which is also an AppoTech chipset. I disassembled a bit of DPFMate.exe (found the SetTime etc. routine) and I also found that when you hold the 'Up' button while pressing the 'Reset' button, the device enters some kind of 'special' state but unfortunately not accessible through USB (the backlight goes on but nothing is showed on the LCD).

A dump utility for Linux (+ some extra stuff):

/* Written by Maurus Cuelenaere */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>

typedef struct
    char            typeName[32];
    unsigned char   memsize[4];
    unsigned char   devID[4];
    unsigned char   eraseCMD;
    unsigned char   writeCMD;
    unsigned char   readCMD;
    char            data;
    unsigned char   iWriteByByte[4];

unsigned char* scsi_read(int fd, unsigned char *cmd_buffer, size_t cmd_size, size_t read_size)
    sg_io_hdr_t io_hdr;
    unsigned char sense_buffer[32];
    unsigned char* read_data = malloc(read_size * sizeof(unsigned char));

    if(read_data == NULL)
        return NULL;

    memset(read_data, 0, read_size * sizeof(unsigned char));
    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
    io_hdr.interface_id = 'S';
    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
    io_hdr.dxfer_len = read_size;
    io_hdr.dxferp = read_data;
    io_hdr.cmdp = cmd_buffer;
    io_hdr.cmd_len = cmd_size;
    io_hdr.sbp = sense_buffer;
    io_hdr.mx_sb_len = sizeof(sense_buffer);
    io_hdr.timeout = 200;

    if(ioctl(fd, SG_IO, &io_hdr) < 0)
        printf("%d %s\n", io_hdr.status, strerror(errno));
        return NULL;
        return read_data;

unsigned char* flash_read(int fd, int addr, int size)
    unsigned char cmd_buffer[16];

    memset(cmd_buffer, 0, sizeof(cmd_buffer));
    cmd_buffer[0] = 0xCD;
    cmd_buffer[6] = 0x04;
    cmd_buffer[7] = (size >> 16) & 0xFF;
    cmd_buffer[8] = (size >>  8) & 0xFF;
    cmd_buffer[9] = (size >>  0) & 0xFF;
    cmd_buffer[10] = 0x03;
    cmd_buffer[11] = (addr >> 16) & 0xFF;
    cmd_buffer[12] = (addr >>  8) & 0xFF;
    cmd_buffer[13] = (addr >>  0) & 0xFF;

    return scsi_read(fd, cmd_buffer, 16, size);

unsigned char* get_flash_id(int fd)
    unsigned char cmd_buffer[16];

    memset(cmd_buffer, 0, sizeof(cmd_buffer));
    cmd_buffer[0] = 0xCD;
    cmd_buffer[6] = 0x01;
    cmd_buffer[9] = 0x40;
    cmd_buffer[10] = 0x9F;

    return scsi_read(fd, cmd_buffer, 16, 0x40);

void get_lcd_param(int fd, short *x, short *y)
    unsigned char cmd_buffer[16], *ret;

    memset(cmd_buffer, 0, sizeof(cmd_buffer));
    cmd_buffer[0] = 0xCD;
    cmd_buffer[5] = 0x02;
    cmd_buffer[6] = 0x01;
    cmd_buffer[10] = 0x02;

    ret = scsi_read(fd, cmd_buffer, 16, 0x40);

    *x = ret[0] | (ret[1] << 8);
    *y = ret[2] | (ret[3] << 8);

unsigned char* get_version(int fd)
    unsigned char cmd_buffer[16];

    memset(cmd_buffer, 0, sizeof(cmd_buffer));
    cmd_buffer[0] = 0xCD;
    cmd_buffer[5] = 0x01;
    cmd_buffer[6] = 0x01;
    cmd_buffer[10] = 0x01;

    return scsi_read(fd, cmd_buffer, 16, 0x40);

long filesize(FILE* fd)
    long cur = ftell(fd);
    fseek(fd, 0, SEEK_END);
    long size = ftell(fd);
    fseek(fd, cur, SEEK_SET);
    return size;

static FLASH_TYPE_STRUCT* flashlib;
static int flashlib_count;
int load_flashlib(void)
    FILE* fd = fopen("flashlib.dat", "r");
    if(fd < 0)
        return -1;

    flashlib_count = filesize(fd) / sizeof(FLASH_TYPE_STRUCT);
    flashlib = malloc(sizeof(FLASH_TYPE_STRUCT) * flashlib_count);
    if(flashlib == NULL)
        return -2;

    fread(flashlib, sizeof(FLASH_TYPE_STRUCT) * flashlib_count, 1, fd);
    return 0;

int main(int argc, char* argv[])
    int fd;
    FILE* out;

    if(load_flashlib() < 0)
        printf("Cannot load flashlib!\n");

    int j;
    for(j=0; j<flashlib_count; j++)
        FLASH_TYPE_STRUCT* flash = &flashlib[j];
        printf("%s: %x%x%x%x [%d]\n", flash->typeName, flash->devID[0], flash->devID[1], flash->devID[2], flash->devID[3],
                                      flash->memsize[2] | (flash->memsize[1] << 8) | (flash->memsize[3] << 16) | (flash->memsize[0] << 24));

    fd = open(argv[1], O_RDONLY);
    if(fd < 0)
        printf("Cannot open %s: %s\n", argv[1], strerror(errno));

#if 1
    unsigned char* flash_id = get_flash_id(fd);
    printf("%x%x%x%x\n", flash_id[0], flash_id[1], flash_id[2], flash_id[3]);

    short x, y;
    get_lcd_param(fd, &x, &y);
    printf("%dx%d\n", x, y);

    unsigned char* d = get_version(fd);
    int i;
    for(i=0; i<0x40; i+=4)
        printf("%02x %02x %02x %02x %c %c %c %c\n",
               d[i], d[i+1], d[i+2], d[i+3],
               d[i], d[i+1], d[i+2], d[i+3]);
    int i;
    unsigned char* d = get_version(fd);
    for(i=0; i<0x40; i+=4)
        printf("%02x %02x %02x %02x %c %c %c %c\n",
               d[i], d[i+1], d[i+2], d[i+3],
               d[i], d[i+1], d[i+2], d[i+3]);
    printf("%s", d);

    out = fopen("dump2.bin", "w");

    int i;
    unsigned char* data;
    for(i = 0; i<(2*1024*1024); i += 0x1000)
        if((data = flash_read(fd, i, 0x1000)) == NULL)

        fwrite(data, 1, 0x1000, out);


CD 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 seems to give the string 'USBS' + some garbage

CB 00 00 00 00 00 01 00 00 00 06 00 00 00 00 00 is CProcessFlash::FlashWREN (write enable?)

Maurus Cuelenaere

OK I've just bough 2 of these 1.5 inch picture frames and they're using the AX203 for sure. I found the DPFMate program and when using the about it gives the same message as posted here before: About I'm sure that AX203 is actually the same as CPF5102. Therefore I'm pretty sure all the code is in the OTP memory and there isn't any in the SPI attached flash chip. The only way to actually run some code on these frames according to the CPF5102 would be to attach an external memory and make the AX203 use only that ( pull some pin to low I think ). However this would prove too difficult I think given the fact that these pins aren't easily accessible. I do have another question , does anyone have any info about the LCD used. This seems to be the only thing that can be used, this and the battery. Where is the LCD controller for one ? Is it on the LCD glass somewhere because I couldn't see it on the PCB. Can the LCD be used for other projects ? Someone mentioned a 20 pin cable being used but I even saw some code posted online but I don't really understand why 20 pins are needed and how they are connected.


Marius, I've found a site that took the DPF and used it's LCD for a project, maybe you can get your info there LINK BinAm

I have a request , could anyone post a newer, Vista compatible, version of dpfmate.exe on or some other site. @BinAm , thanks for the info. I'll look into it if I have some time. Marius

@Marius: Where does the flashlib.dat come from? Alex

Mine is the same, but with a glob-top IC. It has 1MB FLASH instead of 2MB. I found many things in my device:

Offset: 0x23 - Size: 16 bit - Description: LCD size (height?)

Offset: 0x25 - Size: 16 bit - Description: LCD size (width?)

Offset: 0x2F - Size: 16 bit - Description: FLASH size (in KB)

Offset: 0x40 - Size: 16 bytes (empty space filled with 0xFF) - Description: DPF Version (mine is "DPFv1.0")

Offset: 0x50 - Size: 16 bytes (empty space filled with 0xFF) - Description: Firmware Build date? (YYYYMMDD. mine is 20090113)

Offset: 0x60 - Size: 16 bytes (empty space filled with 0xFF) - Description: Manufacturing date? (mine is Jul 22 2010)

Offset: 0x70 - Size: 8 bytes - Description: Manufacturing time? (mine is 19:03:33)

Offset: in mine is 0x52A3, I think this can vary - Size: variable 0x00 terminated - Description: Firmware version (this what you can see on DPFMate About Window - mine is DPF_V3.5.0)

The last value (that "DPF_V3.5.0" at offset 0x52A3) indicates that the block from 0x000000 to 0x008000 must be some sorta of code, since there are no pointer to "DPF_V3.5.0" anywhere in the header nor in the entire firmware dump, but that DPFMate can show it anyway :)

The Dump can be found right here: [2]

--Socram8888 19:42, 11 August 2010 (CEST)

Code analysis

Using the d52 disassembler from, the dump can be analyzed somewhat better using a control file. This is found in See also Makefile. If you are a windows user, you will have to use Cygwin or minGW and install the tools manually.

A few remarks:

  • Have a look at the ProcTable entries, labeled 'jumptbl_start'. This describes the offsets of different "programs" inside the SPI,

plus where they should be relocated.

  • Note that the AX206 is an enhanced CFP5102 architecture. There are a few unknown and undocumented SFRs.

Update: I've decoded the jump table and split up the code into 49 modules. Since the on chip RAM is limited, there are functions that dynamically load code from flash and execute.

Further identified is:

  • The SCSI command emulation (incl. vendor commands CA, CB, CD)
  • SPI access functions (distributed all over the modules)


  • Loading own code into the box. Note: Before we have not figured out the "bootloader" mode (hold menu and reset), we must be absolutely careful not to overwrite the flash access essentials.
  • Getting at the memory map secrets, gather interrupt handler and "system library" code segments
  • Analyze boot loader code (possible?)

If someone is interested about the details (as this might no more be up to date), send me a note.

-- Hackfin