diff options
author | root <root@filebitch> | 2011-08-28 18:28:51 +0200 |
---|---|---|
committer | root <root@filebitch> | 2011-08-28 18:28:51 +0200 |
commit | c8c27e3af96a84ccf8ecdfd7610e49dba0598e7d (patch) | |
tree | 3cb1a59b301f91b6a1524b48fb9d828a78a43dac /oncology/dpfhack_display/dpflib | |
parent | 99bdbc04f2be1f0d27c4a4dde692e8a5b6eb8a7e (diff) | |
parent | 7a97f9d4baff89bbcfa4bef93ab4d4246b2b82e6 (diff) |
Merge branch 'master' of https://github.com/krebscode/painload
Diffstat (limited to 'oncology/dpfhack_display/dpflib')
-rw-r--r-- | oncology/dpfhack_display/dpflib/Makefile | 24 | ||||
-rw-r--r-- | oncology/dpfhack_display/dpflib/dpf.h | 143 | ||||
-rw-r--r-- | oncology/dpfhack_display/dpflib/dpflib.c | 707 | ||||
-rw-r--r-- | oncology/dpfhack_display/dpflib/fwload.c | 140 | ||||
-rw-r--r-- | oncology/dpfhack_display/dpflib/rawusb.c | 177 | ||||
-rw-r--r-- | oncology/dpfhack_display/dpflib/sglib.h | 19 |
6 files changed, 1210 insertions, 0 deletions
diff --git a/oncology/dpfhack_display/dpflib/Makefile b/oncology/dpfhack_display/dpflib/Makefile new file mode 100644 index 00000000..79010b6d --- /dev/null +++ b/oncology/dpfhack_display/dpflib/Makefile @@ -0,0 +1,24 @@ +OBJS = dpflib.o rawusb.o + +CFLAGS = -Wall -fPIC -I../include -g + +ifndef DESTDIR + DESTDIR = .. +endif + +all: libdpf.a fwload + +fwload: fwload.o libdpf.a + $(CC) -o $@ fwload.o -L. -ldpf -lusb + +testusb: testusb.o libdpf.a + $(CC) -o $@ testusb.o -L. -ldpf -lusb + +libdpf.a: $(OBJS) + ar ruv $@ $(OBJS) + +clean: + rm -f fwload libdpf.a *.o + +install: all + cp fwload libdpf.a $(DESTDIR) diff --git a/oncology/dpfhack_display/dpflib/dpf.h b/oncology/dpfhack_display/dpflib/dpf.h new file mode 100644 index 00000000..ba6c05d8 --- /dev/null +++ b/oncology/dpfhack_display/dpflib/dpf.h @@ -0,0 +1,143 @@ +/** libdpf header file + * + * (c) 2010, 2011 <hackfin@section5.ch> + * + */ + +#include <usb.h> +#include "usbuser.h" + +#define ADDR unsigned int + +#define MODE_SG 0x00 ///< generic device mode (original) +#define MODE_USB 0x01 ///< libusb operation mode (hacked) +#define FLAG_CAN_LOCK 0x80 ///< Has the locking feature (new firmware) + +enum { + DEVERR_FILE = -16, + DEVERR_OPEN, + DEVERR_HEX, + DEVERR_CHK, + DEVERR_IO, + DEVERR_MALLOC, + DEVERR_TIMEOUT, +}; + +/** The DPF context structure */ + +typedef +struct dpf_context { + unsigned char mode; + unsigned char flags; + union { + usb_dev_handle *udev; + int fd; + } dev; + unsigned int width; + unsigned int height; + int bpp; + int proto; + char* buff; + unsigned char* oldpix; + int offx; + int offy; +} DPFContext; + +/** A value proxy for the property API */ +typedef struct dpf_proxy { + union { + short integer; + char *sequence; + } value; + char type; +} DPFValue; + +enum { + TYPE_INTEGER, + TYPE_STRING, +}; + +#define DPFHANDLE struct dpf_context * + +/** + Opens the DPF device. if dev is not NULL, open device, otherwise, look for + USB device. + */ +int dpf_open(const char *dev, DPFHANDLE *h); + +/** Close DPF device */ +void dpf_close(DPFHANDLE h); + +/* + */ +void dpf_writefb(DPFHANDLE h, unsigned char *fb); + +int dpf_screen_blit(DPFHANDLE h, const unsigned char *buf, short rect[4]); + +/** Set property on DPF + * \param token Property token + * \param value Pointer to value + */ +int dpf_setproperty(DPFHANDLE h, int token, const DPFValue *value); + +/* USB raw */ + +int emulate_scsi(usb_dev_handle *d, unsigned char *cmd, int cmdlen, char out, + unsigned char *data, unsigned long block_len); + +const char *dev_errstr(int err); + +// Private stuff: +usb_dev_handle *dpf_usb_open(int index); +int sgdev_open(const char *portname, int *fd); + +//////////////////////////////////////////////////////////////////////////// +// FLASH stuff + +// Maximum size for flash_read +#define MAX_CHUNKSIZE 0x10000 + +int read_mem(DPFHANDLE h, unsigned char *buf, ADDR offset, int len); +int write_mem(DPFHANDLE h, const char *hexfile); +int code_go(DPFHANDLE h, ADDR start); + +int dpf_bootstrap(DPFHANDLE h, + ADDR dst, unsigned char *src, unsigned short n, ADDR start); + +int flash_cmd(DPFHANDLE h, int command, int cmdlen, ADDR addr); +int flash_probe(DPFContext *h, unsigned char *id); +int flash_erase(DPFHANDLE h, ADDR offset); +int flash_write(DPFHANDLE h, const unsigned char *buf, ADDR offset, int len); +int flash_read(DPFHANDLE h, unsigned char *buf, ADDR offset, int len); + +int load_ihx(const char *fname, unsigned char *data, + unsigned int *buflen, unsigned int reloc); + +int patch_sector(DPFHANDLE h, + ADDR reloc, unsigned long addr, const char *hexfile); + +//////////////////////////////////////////////////////////////////////////// +/* DPF specific stuff: */ + +#define RGB565_0(r, g, b) \ + (( ((r) & 0xf8) ) | (((g) & 0xe0) >> 5)) +#define RGB565_1(r, g, b) \ + (( ((g) & 0x1c) << 3 ) | (((b) & 0xf8) >> 3)) + +#define RGB565(r, g, b) { RGB565_0(r, g, b), RGB565_1(r, g, b) } + +int dpf_copy(ADDR dst, unsigned char *src, unsigned short n); + +// int clr_screen(DPFHANDLE h, const unsigned char *col); +int write_screen(DPFHANDLE h, const unsigned char *buf, unsigned int len); + + +// Some internal address offsets. They may change, but so far all types +// seem to have the same +// +// w: word, <n>: length, [LE, BE] +// +// FIXME: Use packed struct later. + +// FIXME: Should be 0x0020, once we have the firmware replaced +#define OFFSET_PROPS 0x3f0020 ///< w[2]:LE : Resolution X, Y diff --git a/oncology/dpfhack_display/dpflib/dpflib.c b/oncology/dpfhack_display/dpflib/dpflib.c new file mode 100644 index 00000000..e248eb09 --- /dev/null +++ b/oncology/dpfhack_display/dpflib/dpflib.c @@ -0,0 +1,707 @@ +/** DPF access library for AX206 based HW + * + * 12/2010 <hackfin@section5.ch> + * + * This is an ugly hack, because we use existing SCSI vendor specific + * extensions to pass on our requests to the DPF. + * + * One day we might use a proper protocol like netpp. + * + */ + +// FIXME: Put all those SCSI commands in one (wrapped) place. + +#include "dpf.h" +#include "sglib.h" + +#include "flash.h" +#include <fcntl.h> +#include "usbuser.h" // our user defined flash commands +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <scsi/scsi.h> +#include <scsi/sg.h> +#include <sys/ioctl.h> + +#ifdef DEBUG +#define DEB(x) x +#else +#define DEB(x) +#endif + +/** Vendor command for our hacks */ +static +unsigned char g_excmd[16] = { + 0xcd, 0, 0, 0, + 0, 6, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; + +int do_scsi(int fd, unsigned char *cmd, int cmdlen, char out, + unsigned char *data, unsigned long block_len) +{ + int error; + unsigned char sensebuf[32]; + sg_io_hdr_t io_hdr; + memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); + + io_hdr.interface_id = 'S'; + io_hdr.sbp = sensebuf; + io_hdr.mx_sb_len = sizeof(sensebuf); + if (data == 0) { + io_hdr.dxfer_direction = SG_DXFER_NONE; + } else { + if (out) { + io_hdr.dxfer_direction = SG_DXFER_TO_DEV; + } else { + io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; + } + } + io_hdr.dxferp = data; + io_hdr.dxfer_len = block_len; + io_hdr.cmdp = cmd; + io_hdr.cmd_len = cmdlen; + io_hdr.timeout = 5000; // in ms + error = ioctl(fd, SG_IO, &io_hdr); + if (error < 0) perror("calling SCSI ioctl()"); + return error; +} + +int wrap_scsi(DPFContext *h, unsigned char *cmd, int cmdlen, char out, + unsigned char *data, unsigned long block_len) +{ + int error; + if (h->mode == MODE_USB) { + error = emulate_scsi(h->dev.udev, cmd, cmdlen, out, data, block_len); + } else { + error = do_scsi(h->dev.fd, cmd, cmdlen, out, data, block_len); + } + return error; +} + +/* device wrapper */ + +const char idstring[] = "buildwin Photo Frame 1.01"; + +#define INQ_REPLY_LEN 96 + +int sgdev_open(const char *portname, int *fd) +{ + int error; + + static + unsigned char inquiry[] = { + INQUIRY, 0, 0, 0, + INQ_REPLY_LEN, 0 + }; + + static unsigned char inqbuf[INQ_REPLY_LEN + 2]; + + *fd = open(portname, O_RDONLY | O_NONBLOCK ); + error = do_scsi(*fd, inquiry, sizeof(inquiry), DIR_IN, inqbuf, + INQ_REPLY_LEN); + + if (error < 0) { + fprintf(stderr, "SCSI inquiry failed\n"); + close(*fd); error = DEVERR_OPEN; + } else + if (memcmp(idstring, &inqbuf[8], sizeof(idstring) - 1) != 0) { + close(*fd); error = DEVERR_OPEN; + fprintf(stderr, "Not a photo frame. Refuse to open device.\n"); + } + return error; +} + +static +int probe(DPFHANDLE h) +{ + int ret; + + // We abuse a command that just responds with a '0' status in the + // original firmware. + static unsigned char buf[5]; + + + static + unsigned char cmd[16] = { + 0xcd, 0, 0, 0, + 0, 3, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + cmd[5] = 3; + ret = wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, 0, 0); + + switch (ret) { + case 0: + // The original protocol. + fprintf(stderr, + "Warning: This firmware can not lock the flash\n"); + break; + case 1: + // The improved hack + h->flags |= FLAG_CAN_LOCK; + break; + } + + cmd[5] = 2; // get LCD parameters + ret = wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, 5); + h->width = (buf[0]) | (buf[1] << 8); + h->height = (buf[2]) | (buf[3] << 8); + h->bpp = 2; + + return ret; +} + +/* +static +int dpf_query(DPFHANDLE h) +{ + int ret; + unsigned char buf[64]; // Do not change size + + static + unsigned char cmd[16] = { + 0xcd, 0, 0, 0, + 0, 3, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + return wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, sizeof(buf)); +} +*/ + + + +int dpf_open(const char *dev, DPFHANDLE *h) +{ + int error = 0; + DPFContext *dpf; + int i; + usb_dev_handle *u; + + int fd; + + if (!dev) { + fprintf(stderr, "Please specify a string like 'usb0' or a sg device\n"); + return DEVERR_OPEN; + } + + if (strncmp(dev, "usb", 3) == 0) { + i = dev[3] - '0'; + u = dpf_usb_open(i); + if (!u) return DEVERR_OPEN; + i = MODE_USB; + } else { + fprintf(stderr, "Opening generic SCSI device '%s'\n", dev); + if (sgdev_open(dev, &fd) < 0) return DEVERR_OPEN; + i = MODE_SG; + } + + dpf = (DPFHANDLE) malloc(sizeof(DPFContext)); + if (!dpf) return DEVERR_MALLOC; + + dpf->flags = 0; + dpf->mode = i; + + if (dpf->mode == MODE_USB) { + dpf->dev.udev = u; + error = probe(dpf); + fprintf(stderr, "Got LCD dimensions: %dx%d\n", dpf->width, dpf->height); + } else { + dpf->dev.fd = fd; + } + + *h = dpf; + return error; +} + +void dpf_close(DPFContext *h) +{ + switch (h->mode) { + case MODE_SG: + close(h->dev.fd); + break; + case MODE_USB: + usb_release_interface(h->dev.udev, 0); + usb_close(h->dev.udev); + break; + } + free(h); +} + +const char *dev_errstr(int err) +{ + switch (err) { + case DEVERR_FILE: return "File I/O error"; + case DEVERR_OPEN: return "File open error"; + case DEVERR_HEX: return "Hex file error"; + case DEVERR_CHK: return "Checksum error"; + case DEVERR_IO: return "Common I/O error"; + default: return "Unknown error"; + } +} + +/* Flash stuff */ + +int flash_cmd(DPFContext *h, int command, int cmdlen, ADDR addr) +{ + static + unsigned char cmd[16] = { + 0xcb, 0, 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0 + }; + + cmd[10] = command; + cmd[6] = cmdlen; + + // Sector number or addr: + cmd[13] = addr; + cmd[12] = addr >> 8; + cmd[11] = addr >> 16; + + return wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, 0, 0); +} + + +int flash_read(DPFContext *h, unsigned char *buf, ADDR offset, int len) +{ + static + unsigned char cmd[16] = { + 0xcd, 0, 0, 0, 0, 0, + 0x04, /* num of bytes: */ 0, 0, 0, + SPM_READ, /* SPI offset: */ 0, 0, 0, + 0, 0 + }; + + cmd[9] = len >> 0; + cmd[8] = len >> 8; + cmd[7] = len >> 16; + + cmd[13] = offset >> 0; + cmd[12] = offset >> 8; + cmd[11] = offset >> 16; + + return wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, len); +} + +static +int flash_writechunk(DPFContext *h, const unsigned char *buf, ADDR offset, int len) +{ + static + unsigned char cmd[16] = { + 0xcb, 0, 0, 0, 0, 0, + 4, /* num of bytes: */ 0, 0, 0, + SPM_PP, /* SPI offset: */ 0, 0, 0, + 0, 0 + }; + + cmd[9] = len >> 0; + cmd[8] = len >> 8; + cmd[7] = len >> 16; + + cmd[13] = offset >> 0; + cmd[12] = offset >> 8; + cmd[11] = offset >> 16; + + return wrap_scsi(h, cmd, sizeof(cmd), DIR_OUT, + (unsigned char*) buf, len); +} + +int flash_write(DPFContext *h, const unsigned char *buf, ADDR offset, int len) +{ + int i; + int error = 0; + + for (i = 0; i < len; i += 0x1000) { + error = flash_cmd(h, SPM_WREN, 1, 0); + DEB(printf("Write pages at %06x\n", offset)); + error = flash_writechunk(h, buf, offset, 0x1000); + if (error < 0) break; + buf += 0x1000; offset += 0x1000; + } + return error; +} + + +int load_ihx(const char *fname, unsigned char *data, + unsigned int *buflen, unsigned int reloc) +{ + unsigned char csum_is, csum_need; + int ret; + FILE *f; + + static char line[512]; + static unsigned char buf[0x100]; + int count; + unsigned int addr, len, type; + unsigned short b; + unsigned int total = 0; + + DEB(printf("Opening %s...\n", fname)); + f = fopen(fname, "r"); + if (f == NULL) { + return DEVERR_OPEN; + } + + while(1) { + fgets(line, sizeof(line), f); + + if (feof(f) || ferror(f)) break; + + if ((line[0] != ':') || (strlen(line) < 9)) { + fprintf(stderr, "invalid line in ihx\n"); + break; + } + + ret = sscanf(&line[1], "%02x", &len); + if (ret != 1) { ret = DEVERR_HEX; break; } + + ret = sscanf(&line[3], "%04x", &addr); + if (ret != 1) { ret = DEVERR_HEX; break; } + + ret = sscanf(&line[7], "%02x", &type); + if (ret != 1) { ret = DEVERR_HEX; break; } + +#ifdef DEBUG + printf("len %u addr %04x type %u\n", len, addr, type); +#endif + + if (type == 1) break; + + if (type != 0) { + fprintf(stderr, "ihx: unknown type %u\n", type); + continue; + } + + csum_need = len + (addr & 0xff) + (addr >> 8) + type; + + total += len; + if (total > *buflen) { + fprintf(stderr, "Buffer length exceeded. IHX file too big.\n"); + ret = DEVERR_HEX; + break; + } + + if (len > sizeof(buf)) { + fprintf(stderr, "Buffer length exceeded. Too long lines.\n"); + ret = DEVERR_HEX; + break; + } + + for(count = 0; count < len; count++) { + ret = sscanf(&line[9 + count * 2], "%02hx", &b); + if (ret != 1) { + fprintf(stderr, "hex file: could not parse data!\n"); + break; + } + + buf[count] = b; + csum_need += buf[count]; + } + + if (ret != 1) { ret = DEVERR_HEX; break; } + + ret = sscanf(&line[9 + len * 2], "%02hx", &b); + if (ret != 1) { ret = DEVERR_HEX; break; } + + csum_is = b; + if (((csum_need+csum_is) & 0xff) != 0x00) { + fprintf(stderr, "ihx: checksum failure! is: %02x should be:%02x\n", + csum_is, csum_need); + ret = DEVERR_CHK; + break; + } + + if (addr < reloc) { + fprintf(stderr, "Bad relocation value\n"); + ret = DEVERR_HEX; + break; + } + // Copy to data buffer at relocated address + if (data) { + DEB(printf("Patching at offset %08x, chunk size %d\n", + addr - reloc, len)); + memcpy(&data[addr - reloc], buf, len); + } else { + DEB(printf("Writing to %04x (CODE: %04x), chunk size %d\n", + addr - reloc, addr, len)); + dpf_copy(addr - reloc, buf, len); + } + } + *buflen = total; + fclose(f); + return ret; +} + + +int flash_probe(DPFContext *h, unsigned char *id) +{ + int error; + static + unsigned char buf[64]; + static + unsigned char cmd[16] = { + 0xcd, 0, 0, 0, 0, 0, + 1, sizeof(buf) >> 16, sizeof(buf) >> 8, sizeof(buf) >> 0, + // flash command sequence: + SPM_RDID, 0, 0, 0, + 0, 0 + }; + + error = wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, sizeof(buf)); + id[0] = buf[0]; id[1] = buf[1]; id[2] = buf[2]; + return error; +} + +int flash_erase(DPFContext *h, ADDR addr) +{ + int error; + error = flash_cmd(h, SPM_RES, 1, 0); + error = flash_cmd(h, SPM_WREN, 1, 0); + error = flash_cmd(h, SPM_WRSR, 2, 0); // clr status + + // now erase flash sector: + error = flash_cmd(h, SPM_WREN, 1, 0); + error = flash_cmd(h, SPM_FLASH_SE, 4, addr); + return error; +} + +void dpf_flash_lock(DPFContext *h, char enable) +{ + unsigned char *cmd = g_excmd; + + if (!(h->flags & FLAG_CAN_LOCK)) return; + + printf("Lock flash %d\n", enable); + cmd[6] = USBCMD_FLASHLOCK; // flash lock + cmd[7] = enable; + + wrap_scsi(h, cmd, sizeof(g_excmd), DIR_IN, 0, 0); +} + + +int patch_sector(DPFContext *h, + ADDR reloc, unsigned long addr, const char *hexfile) +{ + int error; + unsigned short offset; + static + unsigned char readbuf[0x10000]; + unsigned int len = sizeof(readbuf); + + offset = addr & 0xffff; + addr -= offset; + + error = flash_read(h, readbuf, addr, 0x10000); + if (error < 0) { + perror("Reading flash"); + return error; + } + + error = load_ihx(hexfile, &readbuf[offset], &len, reloc); + if (error < 0) { + fprintf(stderr, "Failed to load HEX file\n"); + return error; + } + // Lock DPF handler so nothing can interfere with the flashing (in case + // we flash ourselves) + dpf_flash_lock(h, 1); + error = flash_cmd(h, SPM_WREN, 1, 0); + error = flash_cmd(h, SPM_WRSR, 2, 0); // clr status + + error = flash_erase(h, addr); + if (error < 0) return error; + + error = flash_write(h, readbuf, addr, 0x10000); // clr status + dpf_flash_lock(h, 0); + + return error; +} + +//////////////////////////////////////////////////////////////////////////// +// High level functions, generic +// These require a hacked command handler with extended command set. + + +static DPFHANDLE g_dpf; + +int write_mem(DPFContext *h, const char *hexfile) +{ + unsigned int len = 0xc000; + int error; + + g_dpf = h; + error = load_ihx(hexfile, 0, &len, 0x800); + return error; +} + +int read_blk(DPFContext *h, unsigned char *buf, ADDR offset, int len) +{ + unsigned char *cmd = g_excmd; + + cmd[6] = USBCMD_MEMREAD; // memory_read + cmd[7] = offset; + cmd[8] = offset >> 8; + cmd[9] = len; + cmd[10] = len >> 8; + + return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_IN, buf, len); +} + +#define CHUNK_SIZE 1024 + +int read_mem(DPFContext *h, unsigned char *buf, ADDR offset, int len) +{ + int error = 0; + while (len > CHUNK_SIZE && error >= 0) { + error = read_blk(h, buf, offset, CHUNK_SIZE); + offset += CHUNK_SIZE; len -= CHUNK_SIZE; buf += CHUNK_SIZE; + } + error = read_blk(h, buf, offset, len); + + return error; +} + + +int code_go(DPFContext *h, ADDR start) +{ + unsigned char *cmd = g_excmd; + printf("Executing applet..\n"); + cmd[6] = 0x02; // execute + cmd[7] = start; + cmd[8] = start >> 8; + + return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_IN, 0, 0); +} + + + +//////////////////////////////////////////////////////////////////////////// +// High level functions, DPF specific + +/* Bootstrap mode: Expects contiguous memory block to download, then jumps + * into start address + */ +int dpf_bootstrap(DPFContext *h, + ADDR dest, unsigned char *src, unsigned short n, ADDR start) +{ + unsigned char *cmd = g_excmd; + cmd[6] = USBCMD_APPLOAD; // Enter bootstrap mode + cmd[7] = dest; + cmd[8] = dest >> 8; + cmd[9] = n; + cmd[10] = n >> 8; + cmd[11] = start; + cmd[12] = start >> 8; + + return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, src, n); +} + +int dpf_copy(ADDR dst, unsigned char *src, unsigned short n) +{ + unsigned char *cmd = g_excmd; + + cmd[6] = 0x01; // memory_write + cmd[7] = dst; + cmd[8] = dst >> 8; + cmd[9] = n; + cmd[10] = n >> 8; + + return wrap_scsi(g_dpf, cmd, sizeof(g_excmd), DIR_OUT, src, n); +} + +/* Currently unused. +int clr_screen(DPFContext *h, const unsigned char *col) +{ + unsigned char *cmd = g_excmd; + + cmd[6] = USBCMD_PROBE; + cmd[7] = col[0]; + cmd[8] = col[1]; + + return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_IN, 0, 0); +} +*/ + +/* This function is deprecated and may not be implemented on newer hacks + */ +int write_screen(DPFContext *h, const unsigned char *buf, unsigned int len) +{ + unsigned char *cmd = g_excmd; + unsigned int l; + unsigned char factor; + + if (len > 0xffff) { + factor = 2; l = len >> 1; + } else { + factor = 1; l = len; + } + + cmd[6] = USBCMD_WRITEFB; + cmd[7] = factor; + cmd[8] = 0; + cmd[9] = l; + cmd[10] = l >> 8; + + return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, + (unsigned char*) buf, len); +} + +int dpf_screen_blit(DPFContext *h, + const unsigned char *buf, short rect[4]) +{ + unsigned long len = (rect[2] - rect[0]) * (rect[3] - rect[1]); + len <<= 1; + unsigned char *cmd = g_excmd; + + cmd[6] = USBCMD_BLIT; + cmd[7] = rect[0]; + cmd[8] = rect[0] >> 8; + cmd[9] = rect[1]; + cmd[10] = rect[1] >> 8; + cmd[11] = rect[2] - 1; + cmd[12] = (rect[2] - 1) >> 8; + cmd[13] = rect[3] - 1; + cmd[14] = (rect[3] - 1) >> 8; + cmd[15] = 0; + + return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, + (unsigned char*) buf, len); +} + +void dpf_writefb(DPFContext *h, unsigned char *buffer) +{ + int len; + + len = h->width * h->height * h->bpp; + write_screen(h, buffer, len); +} + +int dpf_setproperty(DPFContext *h, int token, const DPFValue *value) +{ + unsigned char *cmd = g_excmd; + + cmd[6] = USBCMD_SETPROPERTY; + cmd[7] = token; + cmd[8] = token >> 8; + + switch (value->type) { + case TYPE_INTEGER: + cmd[9] = value->value.integer; + cmd[10] = value->value.integer >> 8; + break; + default: + break; + } + + return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, NULL, 0); +} + diff --git a/oncology/dpfhack_display/dpflib/fwload.c b/oncology/dpfhack_display/dpflib/fwload.c new file mode 100644 index 00000000..72e37f4a --- /dev/null +++ b/oncology/dpfhack_display/dpflib/fwload.c @@ -0,0 +1,140 @@ +/** DPF firmware loader + * + * 12/2010 <hackfin@section5.ch> + * + * Based on the FX2 ihx loader + * + */ + +#include "dpf.h" +#include <stdio.h> + +//////////////////////////////////////////////////////////////////////////// + +// Demo stuff: + +void memory_dump(unsigned char *buf, unsigned int n) +{ + int i = 0; + int c = 0; + + while (i < n) { + printf("%02x ", buf[i]); + c++; + if (c == 16) { c = 0; printf("\n"); } + i++; + } + if (c) + printf("\n"); +} + +int demo0(DPFHANDLE h) +{ + static unsigned char image[2 * 128 * 128]; + int x, y; + int i; + for (i = 0; i < 127; i++) { + unsigned char *b = image; + for (y = 0; y < 128; y++) { + for (x = 0; x < 128; x++) { + *b++ = RGB565_0(x * 2 + i, y * 2 + i, i); + *b++ = RGB565_1(x * 2 + i, y * 2 + i, i); + } + } + write_screen(h, image, sizeof(image)); + } + return 0; +} + + +//////////////////////////////////////////////////////////////////////////// + + +#if EXPERIMENTAL + +int xmain(int argc, char **argv) +{ + int ret; + int i; + struct banktable *bt; + + // flash offset, offset after jump table + unsigned int offset = 0x80000 + 0x200; + + + static unsigned char buf[0x10000]; + unsigned int len = sizeof(buf); + ret = load_ihx(argv[1], buf, &len, 0x127c, g_banktab); + if (ret < 0) { + fprintf(stderr, "Failed to load HEX file\n"); + return ret; + } else { + printf("Read %d banks\n", ret); + for (i = 0; i < ret; i++) { + bt = &g_banktab[i]; + printf(" { XADDR(0x%04x), XADDR(0x%04x), FOFFS(0x%06x) },\n", + bt->reloc, bt->reloc + bt->len, offset + bt->offset); + + } + } + return 0; +} + +#endif + +int main(int argc, char **argv) +{ + int ret; + DPFHANDLE h; + + int i = 2; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage:\n" + "%s <generic scsi dev> <.ihx file>\n" + "or in USB mode:\n" + "%s <.ihx file>\n", + argv[0], argv[0]); + return -1; + } + + if (argc == 2) { + ret = dpf_open(NULL, &h); + i--; + } else + if (argc == 3) { + ret = dpf_open(argv[1], &h); + } + + if (ret < 0) { + perror("opening DPF device:"); + return ret; + } + +// This patches a module to init the relocated jump table on a certain +// menu action: +// ret = patch_sector(h, 0x1330, 0x4af7a, "hack2.ihx"); + + +// patch_sector(h, 0x0, 0x100000, "jumptbl.ihx"); + + if (0) { + patch_sector(h, 0x0, 0x100000, "jumptbl.ihx"); + ret = patch_sector(h, 0x1330, 0x110000, "hack.ihx"); + ret = patch_sector(h, 0x132a, 0x120000, "main.ihx"); + if (ret < 0) printf("Failed.\n"); + } else { + // demo0(h); + + } + ret = write_mem(h, argv[i]); + code_go(h, 0x18a0); + if (ret < 0) printf("Failed.\n"); + + // unsigned char buf[256]; + // ret = read_mem(h, buf, 0x18a0, 64); + // memory_dump(buf, 64); + + dpf_close(h); + return ret; +} diff --git a/oncology/dpfhack_display/dpflib/rawusb.c b/oncology/dpfhack_display/dpflib/rawusb.c new file mode 100644 index 00000000..a3c568b7 --- /dev/null +++ b/oncology/dpfhack_display/dpflib/rawusb.c @@ -0,0 +1,177 @@ +/* Low level USB code to access DPF. + * + * (c) 2010, 2011 <hackfin@section5.ch> + * + * This currently uses the SCSI command set + * + * The reason for this is that we want to access the hacked frame + * non-root and without having to wait for the SCSI interface to + * intialize. + * + * Later, we'll replace the SCSI command stuff. + */ + +#include "dpf.h" +#include "sglib.h" + +#include <string.h> +#include <stdio.h> + +#define ENDPT_OUT 1 +#define ENDPT_IN 0x81 + +struct known_device { + char *desc; + unsigned short vid; + unsigned short pid; +} g_known_devices[] = { + { "AX206 DPF", 0x1908, 0x0102 }, + { 0 , 0, 0 } /* NEVER REMOVE THIS */ +}; + +int handle_error(char *txt) +{ + fprintf(stderr, "Error: %s\n", txt); + return -1; +} + +void usb_flush(usb_dev_handle *dev) +{ + char buf[20]; + usb_bulk_read(dev, ENDPT_IN, buf, 3, 1000); +} + +int check_known_device(struct usb_device *d) +{ + struct known_device *dev = g_known_devices; + + while (dev->desc) { + if ((d->descriptor.idVendor == dev->vid) && + (d->descriptor.idProduct == dev->pid)) { + fprintf(stderr, "Found %s\n", dev->desc); + return 1; + } + dev++; + } + return 0; +} + +static struct usb_device *find_dev(int index) +{ + struct usb_bus *b; + struct usb_device *d; + int enumeration = 0; + + b = usb_get_busses(); + + while (b) { + d = b->devices; + while (d) { + if (check_known_device(d)) { + if (enumeration == index) return d; + else enumeration++; + } + +#ifdef DEBUG + printf("%04x %04x\n", + d->descriptor.idVendor, + d->descriptor.idProduct); +#endif + d = d->next; + } + b = b->next; + } + return NULL; +} + +char g_buf[] = { + 0x55, 0x53, 0x42, 0x43, // dCBWSignature + 0xde, 0xad, 0xbe, 0xef, // dCBWTag + 0x00, 0x80, 0x00, 0x00, // dCBWLength + 0x00, // bmCBWFlags: 0x80: data in (dev to host), 0x00: Data out + 0x00, // bCBWLUN + 0x10, // bCBWCBLength + + // SCSI cmd: + 0xcd, 0x00, 0x00, 0x00, + 0x00, 0x06, 0x11, 0xf8, + 0x70, 0x00, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +int emulate_scsi(usb_dev_handle *dev, unsigned char *cmd, int cmdlen, char out, + unsigned char *data, unsigned long block_len) +{ + int len; + int ret; + static unsigned char ansbuf[13]; // Do not change size. + + g_buf[14] = cmdlen; + memcpy(&g_buf[15], cmd, cmdlen); + + g_buf[8] = block_len; + g_buf[9] = block_len >> 8; + g_buf[10] = block_len >> 16; + g_buf[11] = block_len >> 24; + + ret = usb_bulk_write(dev, ENDPT_OUT, g_buf, sizeof(g_buf), 1000); + if (ret < 0) return ret; + + if (out == DIR_OUT) { + if (data) { + ret = usb_bulk_write(dev, ENDPT_OUT, (const char* )data, + block_len, 3000); + if (ret != block_len) { + perror("bulk write"); + return ret; + } + } + } else if (data) { + ret = usb_bulk_read(dev, ENDPT_IN, (char *) data, block_len, 4000); + if (ret != block_len) { + perror("bulk data read"); + } + } + // get ACK: + len = sizeof(ansbuf); + int retry = 0; + do { + ret = usb_bulk_read(dev, ENDPT_IN, (char *) ansbuf, len, 5000); + if (ret != len) { + perror("bulk ACK read"); + ret = DEVERR_TIMEOUT; + } + retry++; + } while (ret == DEVERR_TIMEOUT && retry < 5); + if (strncmp((char *) ansbuf, "USBS", 4)) { + return handle_error("Got invalid reply\n"); + } + // pass back return code set by peer: + return ansbuf[12]; +} + +usb_dev_handle *dpf_usb_open(int index) +{ + struct usb_device *d; + usb_dev_handle *usb_dev; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + d = find_dev(index); + if (!d) { + handle_error("No matching USB device found!"); + return NULL; + } + + usb_dev = usb_open(d); + if (usb_dev == NULL) { + handle_error("Failed to open usb device!"); + return NULL; + } + usb_claim_interface(usb_dev, 0); + return usb_dev; +} + + diff --git a/oncology/dpfhack_display/dpflib/sglib.h b/oncology/dpfhack_display/dpflib/sglib.h new file mode 100644 index 00000000..a2bc232e --- /dev/null +++ b/oncology/dpfhack_display/dpflib/sglib.h @@ -0,0 +1,19 @@ +#include <stdint.h> + + +/* generic device wrapper: */ + +const char* dev_errstr(int error); + + +/* generic SCSI device stuff: */ + +#define DIR_IN 0 +#define DIR_OUT 1 + + +/* Special functions */ + + + + |