From b56d5a64309e1d705d34f42a28c2371a7bf7f9fe Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 19 Feb 2009 17:33:53 +0100 Subject: [PATCH] Added ftdi_eeprom_decode() --- .gitignore | 9 ++++ src/ftdi.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ftdi.h | 1 + 3 files changed, 158 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index f7ac5b5..66068d7 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,12 @@ doc/html # libftdi specific libftdi-config libftdi.spec + +# CMake +CMakeCache.txt +cmake_install.cmake +CMakeFiles + +# Misc. binaries +*.dylib +opt \ No newline at end of file diff --git a/src/ftdi.c b/src/ftdi.c index 3feb9b6..a8a67fb 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "ftdi.h" @@ -1806,6 +1807,153 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) return size_check; } +void ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf) +{ + unsigned char i, j; + unsigned short checksum, eeprom_checksum, value; + unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; + int size_check; + int eeprom_size = 128; +#if 0 + size_check = eeprom->size; + size_check -= 28; // 28 are always in use (fixed) + + // Top half of a 256byte eeprom is used just for strings and checksum + // it seems that the FTDI chip will not read these strings from the lower half + // Each string starts with two bytes; offset and type (0x03 for string) + // the checksum needs two bytes, so without the string data that 8 bytes from the top half + if(eeprom->size>=256)size_check = 120; + size_check -= manufacturer_size*2; + size_check -= product_size*2; + size_check -= serial_size*2; + + // eeprom size exceeded? + if (size_check < 0) + return (-1); +#endif + + // empty eeprom struct + memset (eeprom, 0, sizeof(struct ftdi_eeprom)); + + // Addr 00: Stay 00 00 + + // Addr 02: Vendor ID + eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8); + + // Addr 04: Product ID + eeprom->product_id = buf[0x04] + (buf[0x05] << 8); + +/* // Addr 06: Device release number (0400h for BM features) */ +/* output[0x06] = 0x00; */ + + if (buf[0x07] == 0x04) eeprom->BM_type_chip = 1; + + // Addr 08: Config descriptor + // Bit 7: always 1 + // Bit 6: 1 if this device is self powered, 0 if bus powered + // Bit 5: 1 if this device uses remote wakeup + // Bit 4: 1 if this device is battery powered + j = buf[0x08]; + + if (j&0x40) eeprom->self_powered = 1; + if (j&0x20) eeprom->remote_wakeup = 1; + + // Addr 09: Max power consumption: max power = value * 2 mA + eeprom->max_power = buf[0x09]; + + // Addr 0A: Chip configuration + // Bit 7: 0 - reserved + // Bit 6: 0 - reserved + // Bit 5: 0 - reserved + // Bit 4: 1 - Change USB version + // Bit 3: 1 - Use the serial number string + // Bit 2: 1 - Enable suspend pull downs for lower power + // Bit 1: 1 - Out EndPoint is Isochronous + // Bit 0: 1 - In EndPoint is Isochronous + // + j = buf[0x0A]; + if (j&1) eeprom->in_is_isochronous = 1; + if (j&2) eeprom->out_is_isochronous = 1; + if (j&4) eeprom->suspend_pull_downs = 1; + if (j&8) eeprom->use_serial = 1; + if (j&16) eeprom->change_usb_version = 1; + +/* // Addr 0B: reserved */ +/* output[0x0B] = 0x00; */ + + // Addr 0C: USB version low byte when 0x0A bit 4 is set + // Addr 0D: USB version high byte when 0x0A bit 4 is set + if (eeprom->change_usb_version == 1) { + eeprom->usb_version = buf[0x0C] + (buf[0x0D] << 8); + } + + // Addr 0E: Offset of the manufacturer string + 0x80, calculated later + // Addr 0F: Length of manufacturer string + manufacturer_size = buf[0x0F]/2; + if (manufacturer_size > 0) eeprom->manufacturer = malloc(manufacturer_size); + else eeprom->manufacturer = NULL; + + // Addr 10: Offset of the product string + 0x80, calculated later + // Addr 11: Length of product string + product_size = buf[0x11]/2; + if (product_size > 0) eeprom->product = malloc(product_size); + else eeprom->product = NULL; + + // Addr 12: Offset of the serial string + 0x80, calculated later + // Addr 13: Length of serial string + serial_size = buf[0x13]/2; + if (serial_size > 0) eeprom->serial = malloc(serial_size); + else eeprom->serial = NULL; + + // Dynamic content + // if(eeprom->size>=256) i = 0x80; + + // Decode manufacturer + i = buf[0x0E] & 0x7f; // offset +/* printf("debug size: %d, %d\n", buf[i]/2, manufacturer_size); // length */ +/* printf("debug 0x03: %02x\n", buf[i+1]); // type: string */ + for (j=0;jmanufacturer[j] = buf[2*j+i+2]; + } + eeprom->manufacturer[j] = '\0'; + + // Decode product name + i = buf[0x10] & 0x7f; // offset +/* printf("debug size: %d, %d\n", buf[i]/2, product_size); // length */ +/* printf("debug 0x03: %02x\n", buf[i+1]); // type: string */ + for (j=0;jproduct[j] = buf[2*j+i+2]; + } + eeprom->product[j] = '\0'; + + // Decode serial + i = buf[0x12] & 0x7f; // offset +/* printf("debug size: %d, %d\n", buf[i]/2, serial_size); // length */ +/* printf("debug 0x03: %02x\n", buf[i+1]); // type: string */ + for (j=0;jserial[j] = buf[2*j+i+2]; + } + eeprom->serial[j] = '\0'; + + // verify checksum + checksum = 0xAAAA; + + for (i = 0; i < eeprom_size/2-1; i++) { + value = buf[i*2]; + value += buf[(i*2)+1] << 8; + + checksum = value^checksum; + checksum = (checksum << 1) | (checksum >> 15); + } + + eeprom_checksum = buf[eeprom_size-2] + (buf[eeprom_size-1] << 8); + + if (eeprom_checksum != checksum) + fprintf(stderr, "Checksum Error: %04x %04x\n", checksum, eeprom_checksum); + + return; +} + /** Read eeprom diff --git a/src/ftdi.h b/src/ftdi.h index ec3d431..ab785d9 100644 --- a/src/ftdi.h +++ b/src/ftdi.h @@ -322,6 +322,7 @@ extern "C" { /* init and build eeprom from ftdi_eeprom structure */ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom); int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output); + void ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *output); /* "eeprom" needs to be valid 128 byte eeprom (generated by the eeprom generator) the checksum of the eeprom is valided */ -- 1.7.1