X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=ac0a65127aef1a84e806f4150836286a757d6916;hp=78ae76e392f5e2b20ca6f9121b3855c84416fba6;hb=ca41c8ee8dcc93a431fbc0b6746b5ea246d511f9;hpb=6cd4f92217aa33f3b8c6c304ceeb893ec913c71c diff --git a/src/ftdi.c b/src/ftdi.c index 78ae76e..ac0a651 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -2206,8 +2206,11 @@ void ftdi_eeprom_initdefaults(struct ftdi_context *ftdi) default: eeprom->release = 0; } - eeprom->usb_version = 0x0200; - eeprom->max_power = 100; + if (ftdi->type == TYPE_AM) + eeprom->usb_version = 0x0101; + else + eeprom->usb_version = 0x0200; + eeprom->max_power = 50; eeprom->manufacturer = NULL; eeprom->product = NULL; @@ -2261,6 +2264,7 @@ void ftdi_eeprom_free(struct ftdi_context *ftdi) \retval -3: Invalid cbus function setting \retval -4: Chip doesn't support invert \retval -5: Chip doesn't support high current drive + \retval -6: No connected EEPROM or EEPROM Type unknown */ int ftdi_eeprom_build(struct ftdi_context *ftdi, unsigned char *output) { @@ -2268,7 +2272,6 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi, unsigned char *output) unsigned short checksum, value; unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; int size_check; - const int cbus_max[5] = {13, 13, 13, 13, 9}; struct ftdi_eeprom *eeprom; if (ftdi == NULL) @@ -2278,6 +2281,9 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi, unsigned char *output) eeprom= ftdi->eeprom; + if(eeprom->chip == -1) + ftdi_error_return(-5,"No connected EEPROM or EEPROM Type unknown"); + if (eeprom->manufacturer != NULL) manufacturer_size = strlen(eeprom->manufacturer); if (eeprom->product != NULL) @@ -2285,18 +2291,6 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi, unsigned char *output) if (eeprom->serial != NULL) serial_size = strlen(eeprom->serial); - // highest allowed cbus value - for (i = 0; i < 5; i++) - { - if ((eeprom->cbus_function[i] > cbus_max[i]) || - (eeprom->cbus_function[i] && ftdi->type != TYPE_R)) return -3; - } - if (ftdi->type != TYPE_R) - { - if (eeprom->invert) return -4; - if (eeprom->high_current_a) return -5; - } - size_check = 0x80; switch(ftdi->type) { @@ -2378,7 +2372,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi, unsigned char *output) // Bit 7: 0 - reserved // Bit 6: 0 - reserved // Bit 5: 0 - reserved - // Bit 4: 1 - Change USB version + // Bit 4: 1 - Change USB version + // not seen on FT2232C) // 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 @@ -2393,20 +2388,15 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi, unsigned char *output) j = j | 4; if (eeprom->use_serial == 1) j = j | 8; - if (eeprom->change_usb_version == 1) - j = j | 16; output[0x0A] = j; // Addr 0B: Invert data lines output[0x0B] = eeprom->invert & 0xff; - // 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) - { - output[0x0C] = eeprom->usb_version; - output[0x0D] = eeprom->usb_version >> 8; - } + // Addr 0C: USB version low byte + // Addr 0D: USB version high byte + output[0x0C] = eeprom->usb_version; + output[0x0D] = eeprom->usb_version >> 8; // Addr 0E: Offset of the manufacturer string + 0x80, calculated later @@ -2522,17 +2512,23 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, unsigned char *buf, int size, // Addr 00: Channel A setting eeprom->channel_a_type = buf[0x00] & 0x7; - eeprom->channel_a_driver = buf[0x00] & DRIVER_VCP; + eeprom->high_current = buf[0x00] & HIGH_CURRENT_DRIVE_R; + eeprom->channel_a_driver = buf[0x00] & DRIVER_D2XX; eeprom->high_current_a = buf[0x00] & HIGH_CURRENT_DRIVE; // Addr 01: Channel B setting eeprom->channel_b_type = buf[0x01] & 0x7; - eeprom->channel_b_driver = buf[0x01] & DRIVER_VCP; + eeprom->channel_b_driver = buf[0x01] & DRIVER_D2XX; eeprom->high_current_b = buf[0x01] & HIGH_CURRENT_DRIVE; eeprom->suspend_dbus7 = buf[0x01] & SUSPEND_DBUS7; + if((ftdi->type == TYPE_R) && ((buf[0x01]&0x40) != 0x40)) + fprintf(stderr, + "TYPE_R EEPROM byte[0x01] Bit 6 unexpected Endpoint size. If this happened with the\n" + " EEPROM programmed by FTDI tools, please report to libftdi@developer.intra2net.com\n"); + // Addr 02: Vendor ID eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8); @@ -2567,15 +2563,15 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, unsigned char *buf, int size, eeprom->out_is_isochronous = buf[0x0A]&0x02; eeprom->suspend_pull_downs = buf[0x0A]&0x04; eeprom->use_serial = buf[0x0A] & USE_SERIAL_NUM; - eeprom->change_usb_version = buf[0x0A]&0x10; + if(buf[0x0A]&0x10) + fprintf(stderr, + "EEPROM byte[0x0a] Bit 4 unexpected set. If this happened with the EEPROM\n" + "programmed by FTDI tools, please report to libftdi@developer.intra2net.com\n"); - // 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) || ftdi->type == TYPE_2232C) - { - eeprom->usb_version = buf[0x0C] + (buf[0x0D] << 8); - } + // Addr 0C: USB version low byte when 0x0A + // Addr 0D: USB version high byte when 0x0A + eeprom->usb_version = buf[0x0C] + (buf[0x0D] << 8); // Addr 0E: Offset of the manufacturer string + 0x80, calculated later // Addr 0F: Length of manufacturer string @@ -2726,12 +2722,12 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, unsigned char *buf, int size, if (ftdi->type >= TYPE_2232C) fprintf(stdout,"Channel A has Mode %s%s%s\n", channel_mode[eeprom->channel_a_type], - (eeprom->channel_a_driver)?" VCP":"", + (eeprom->channel_a_driver)?" D2XX":"", (eeprom->high_current_a)?" High Currenr IO":""); if (ftdi->type >= TYPE_2232C) fprintf(stdout,"Channel B has Mode %s%s%s\n", channel_mode[eeprom->channel_b_type], - (eeprom->channel_b_driver)?" VCP":"", + (eeprom->channel_b_driver)?" D2XX":"", (eeprom->high_current_b)?" High Currenr IO":""); if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H)) { @@ -2946,15 +2942,61 @@ int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) \retval 0: all fine \retval -1: erase failed \retval -2: USB device unavailable + \retval -3: Writing magic failed + \retval -4: Read EEPROM failed + \retval -5: Unexpected EEPROM value */ +#define MAGIC 0x55aa int ftdi_erase_eeprom(struct ftdi_context *ftdi) { + unsigned short eeprom_value; if (ftdi == NULL || ftdi->usb_dev == NULL) ftdi_error_return(-2, "USB device unavailable"); - if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_ERASE_EEPROM_REQUEST, 0, 0, NULL, 0, ftdi->usb_write_timeout) < 0) + if(ftdi->type == TYPE_R) + { + ftdi->eeprom->chip = 0; + return 0; + } + + if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_ERASE_EEPROM_REQUEST, + 0, 0, NULL, 0, ftdi->usb_write_timeout) < 0) ftdi_error_return(-1, "unable to erase eeprom"); + + /* detect chip type by writing 0x55AA as magic at word position 0xc0 + Chip is 93x46 if magic is read at word position 0x00, as wraparound happens around 0x40 + Chip is 93x56 if magic is read at word position 0x40, as wraparound happens around 0x80 + Chip is 93x66 if magic is only read at word position 0xc0*/ + if( ftdi_write_eeprom_location(ftdi, 0xc0, MAGIC)) + ftdi_error_return(-3, "Writing magic failed"); + if (ftdi_read_eeprom_location( ftdi, 0x00, &eeprom_value)) + ftdi_error_return(-4, "Reading failed failed"); + if(eeprom_value == MAGIC) + { + ftdi->eeprom->chip = 0x46; + } + else + { + if (ftdi_read_eeprom_location( ftdi, 0x40, &eeprom_value)) + ftdi_error_return(-4, "Reading failed failed"); + if(eeprom_value == MAGIC) + ftdi->eeprom->chip = 0x56; + else + { + if (ftdi_read_eeprom_location( ftdi, 0xc0, &eeprom_value)) + ftdi_error_return(-4, "Reading failed failed"); + if(eeprom_value == MAGIC) + ftdi->eeprom->chip = 0x66; + else + { + ftdi->eeprom->chip = -1; + } + } + } + if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, SIO_ERASE_EEPROM_REQUEST, + 0, 0, NULL, 0, ftdi->usb_write_timeout) < 0) + ftdi_error_return(-1, "unable to erase eeprom"); return 0; }