X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=e2c4009c83f71b4932167a9d314cbe0df0146974;hp=1f45e95cd481c9965b8801e1e768eef4449663e7;hb=2f80efc24176c903d82cea1f084453fd3df9b992;hpb=2d790e377ad5f1c61b38436aa3d5a201c9184028 diff --git a/src/ftdi.c b/src/ftdi.c index 1f45e95..e2c4009 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -2,7 +2,7 @@ ftdi.c - description ------------------- begin : Fri Apr 4 2003 - copyright : (C) 2003-2011 by Intra2net AG and the libftdi developers + copyright : (C) 2003-2013 by Intra2net AG and the libftdi developers email : opensource@intra2net.com ***************************************************************************/ @@ -39,7 +39,10 @@ #include "ftdi_version_i.h" #define ftdi_error_return(code, str) do { \ - ftdi->error_str = str; \ + if ( ftdi ) \ + ftdi->error_str = str; \ + else \ + fprintf(stderr, str); \ return code; \ } while(0); @@ -149,12 +152,23 @@ struct ftdi_context *ftdi_new(void) \retval 0: all fine \retval -1: unknown interface \retval -2: USB device unavailable + \retval -3: Device already open, interface can't be set in that state */ int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface) { if (ftdi == NULL) ftdi_error_return(-2, "USB device unavailable"); + if (ftdi->usb_dev != NULL) + { + int check_interface = interface; + if (check_interface == INTERFACE_ANY) + check_interface = INTERFACE_A; + + if (ftdi->index != check_interface) + ftdi_error_return(-3, "Interface can not be changed on an already open device"); + } + switch (interface) { case INTERFACE_ANY: @@ -456,7 +470,7 @@ static unsigned int _ftdi_determine_max_packet_size(struct ftdi_context *ftdi, l // Determine maximum packet size. Init with default value. // New hi-speed devices from FTDI use a packet size of 512 bytes // but could be connected to a normal speed USB hub -> 64 bytes packet size. - if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H ) + if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H || ftdi->type == TYPE_230X) packet_size = 512; else packet_size = 64; @@ -594,6 +608,8 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, libusb_device *dev) ftdi->type = TYPE_4232H; else if (desc.bcdDevice == 0x900) ftdi->type = TYPE_232H; + else if (desc.bcdDevice == 0x1000) + ftdi->type = TYPE_230X; // Determine maximum packet size ftdi->max_packet_size = _ftdi_determine_max_packet_size(ftdi, dev); @@ -1159,7 +1175,7 @@ static int ftdi_convert_baudrate(int baudrate, struct ftdi_context *ftdi, #define H_CLK 120000000 #define C_CLK 48000000 - if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H) || (ftdi->type == TYPE_232H )) + if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H) || (ftdi->type == TYPE_232H) || (ftdi->type == TYPE_230X)) { if(baudrate*10 > H_CLK /0x3fff) { @@ -1184,8 +1200,7 @@ static int ftdi_convert_baudrate(int baudrate, struct ftdi_context *ftdi, } // Split into "value" and "index" values *value = (unsigned short)(encoded_divisor & 0xFFFF); - if (ftdi->type == TYPE_2232H || - ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H ) + if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H || ftdi->type == TYPE_230X) { *index = (unsigned short)(encoded_divisor >> 8); *index &= 0xFF00; @@ -1528,7 +1543,7 @@ struct ftdi_transfer_control *ftdi_write_data_submit(struct ftdi_context *ftdi, tc->size = size; tc->offset = 0; - if (size < ftdi->writebuffer_chunksize) + if (size < (int)ftdi->writebuffer_chunksize) write_size = size; else write_size = ftdi->writebuffer_chunksize; @@ -1581,7 +1596,7 @@ struct ftdi_transfer_control *ftdi_read_data_submit(struct ftdi_context *ftdi, u tc->buf = buf; tc->size = size; - if (size <= ftdi->readbuffer_remaining) + if (size <= (int)ftdi->readbuffer_remaining) { memcpy (buf, ftdi->readbuffer+ftdi->readbuffer_offset, size); @@ -1745,7 +1760,7 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) ftdi_error_return(-1, "max_packet_size is bogus (zero)"); // everything we want is still in the readbuffer? - if (size <= ftdi->readbuffer_remaining) + if (size <= (int)ftdi->readbuffer_remaining) { memcpy (buf, ftdi->readbuffer+ftdi->readbuffer_offset, size); @@ -2301,8 +2316,11 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, eeprom->product_id = 0x6011; else if (ftdi->type == TYPE_232H) eeprom->product_id = 0x6014; + else if (ftdi->type == TYPE_230X) + eeprom->product_id = 0x6015; else eeprom->product_id = 0x6010; + if (ftdi->type == TYPE_AM) eeprom->usb_version = 0x0101; else @@ -2340,6 +2358,7 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, case TYPE_2232H: default_product = "Dual RS232-HS"; break; case TYPE_4232H: default_product = "FT4232H"; break; case TYPE_232H: default_product = "Single-RS232-HS"; break; + case TYPE_230X: default_product = "FT230X Basic UART"; break; default: ftdi_error_return(-3, "Unknown chip type"); } @@ -2358,7 +2377,6 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, strcpy(eeprom->serial, serial); } - if (ftdi->type == TYPE_R) { eeprom->max_power = 90; @@ -2369,6 +2387,15 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, eeprom->cbus_function[3] = CBUS_PWREN; eeprom->cbus_function[4] = CBUS_SLEEP; } + else if (ftdi->type == TYPE_230X) + { + eeprom->max_power = 90; + eeprom->size = 0x100; + eeprom->cbus_function[0] = CBUSH_TXDEN; + eeprom->cbus_function[1] = CBUSH_RXLED; + eeprom->cbus_function[2] = CBUSH_TXLED; + eeprom->cbus_function[3] = CBUSH_SLEEP; + } else { if(ftdi->type == TYPE_232H) @@ -2379,9 +2406,83 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, } eeprom->size = -1; } - eeprom->initialized_for_connected_device = 1; + switch (ftdi->type) + { + case TYPE_AM: + eeprom->release_number = 0x0200; + break; + case TYPE_BM: + eeprom->release_number = 0x0400; + break; + case TYPE_2232C: + eeprom->release_number = 0x0500; + break; + case TYPE_R: + eeprom->release_number = 0x0600; + break; + case TYPE_2232H: + eeprom->release_number = 0x0700; + break; + case TYPE_4232H: + eeprom->release_number = 0x0800; + break; + case TYPE_232H: + eeprom->release_number = 0x0900; + break; + case TYPE_230X: + eeprom->release_number = 0x1000; + break; + default: + eeprom->release_number = 0x00; + } return 0; } + +int ftdi_eeprom_set_strings(struct ftdi_context *ftdi, char * manufacturer, + char * product, char * serial) +{ + struct ftdi_eeprom *eeprom; + + if (ftdi == NULL) + ftdi_error_return(-1, "No struct ftdi_context"); + + if (ftdi->eeprom == NULL) + ftdi_error_return(-2,"No struct ftdi_eeprom"); + + eeprom = ftdi->eeprom; + + if (ftdi->usb_dev == NULL) + ftdi_error_return(-3, "No connected device or device not yet opened"); + + if (manufacturer) { + if (eeprom->manufacturer) + free (eeprom->manufacturer); + eeprom->manufacturer = malloc(strlen(manufacturer)+1); + if (eeprom->manufacturer) + strcpy(eeprom->manufacturer, manufacturer); + } + + if(product) { + if (eeprom->product) + free (eeprom->product); + eeprom->product = malloc(strlen(product)+1); + if (eeprom->product) + strcpy(eeprom->product, product); + } + + if (serial) { + if (eeprom->serial) + free (eeprom->serial); + eeprom->serial = malloc(strlen(serial)+1); + if (eeprom->serial) { + strcpy(eeprom->serial, serial); + eeprom->use_serial = 1; + } + } + return 0; +} + + /*FTD2XX doesn't check for values not fitting in the ACBUS Signal oprtions*/ void set_ft232h_cbus(struct ftdi_eeprom *eeprom, unsigned char * output) { @@ -2396,9 +2497,9 @@ void set_ft232h_cbus(struct ftdi_eeprom *eeprom, unsigned char * output) if (eeprom->cbus_function[2*i+1]> CBUSH_CLK7_5) mode_high = CBUSH_TRISTATE; else - mode_high = eeprom->cbus_function[2*i]; + mode_high = eeprom->cbus_function[2*i+1]; - output[0x18+i] = mode_high <<4 | mode_low; + output[0x18+i] = (mode_high <<4) | mode_low; } } /* Return the bits for the encoded EEPROM Structure of a requested Mode @@ -2432,6 +2533,7 @@ static unsigned char type2bit(unsigned char type, enum ftdi_chip_type chip) default: return 0; } } + case TYPE_230X: /* FT230X is only UART */ default: return 0; } return 0; @@ -2471,10 +2573,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) if (eeprom->chip == -1) ftdi_error_return(-6,"No connected EEPROM or EEPROM type unknown"); - if ((eeprom->chip == 0x56) || (eeprom->chip == 0x66)) - eeprom->size = 0x100; - else - eeprom->size = 0x80; + if (eeprom->size == -1) { + if ((eeprom->chip == 0x56) || (eeprom->chip == 0x66)) + eeprom->size = 0x100; + else + eeprom->size = 0x80; + } if (eeprom->manufacturer != NULL) manufacturer_size = strlen(eeprom->manufacturer); @@ -2494,6 +2598,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) user_area_size = 90; // two extra config bytes and 4 bytes PnP stuff break; case TYPE_R: + case TYPE_230X: user_area_size = 88; // four extra config bytes + 4 bytes PnP stuff break; case TYPE_2232H: // six extra config bytes + 4 bytes PnP stuff @@ -2513,7 +2618,14 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) ftdi_error_return(-1,"eeprom size exceeded"); // empty eeprom - memset (ftdi->eeprom->buf, 0, FTDI_MAX_EEPROM_SIZE); + if (ftdi->type == TYPE_230X) { + /* FT230X have a reserved section in the middle of the MTP, + which cannot be written to, but must be included in the checksum */ + memset(ftdi->eeprom->buf, 0, 0x80); + memset((ftdi->eeprom->buf + 0xa0), 0, (FTDI_MAX_EEPROM_SIZE - 0xa0)); + } else { + memset(ftdi->eeprom->buf, 0, FTDI_MAX_EEPROM_SIZE); + } // Bytes and Bits set for all Types @@ -2526,33 +2638,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x05] = eeprom->product_id >> 8; // Addr 06: Device release number (0400h for BM features) - output[0x06] = 0x00; - switch (ftdi->type) - { - case TYPE_AM: - output[0x07] = 0x02; - break; - case TYPE_BM: - output[0x07] = 0x04; - break; - case TYPE_2232C: - output[0x07] = 0x05; - break; - case TYPE_R: - output[0x07] = 0x06; - break; - case TYPE_2232H: - output[0x07] = 0x07; - break; - case TYPE_4232H: - output[0x07] = 0x08; - break; - case TYPE_232H: - output[0x07] = 0x09; - break; - default: - output[0x07] = 0x00; - } + output[0x06] = eeprom->release_number; + output[0x07] = eeprom->release_number >> 8; // Addr 08: Config descriptor // Bit 7: always 1 @@ -2560,16 +2647,16 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) // Bit 5: 1 if this device uses remote wakeup // Bit 4-0: reserved - 0 j = 0x80; - if (eeprom->self_powered == 1) + if (eeprom->self_powered) j |= 0x40; - if (eeprom->remote_wakeup == 1) + if (eeprom->remote_wakeup) j |= 0x20; output[0x08] = j; // Addr 09: Max power consumption: max power = value * 2 mA - output[0x09] = eeprom->max_power>>1; + output[0x09] = eeprom->max_power / MAX_POWER_MILLIAMP_PER_UNIT; - if (ftdi->type != TYPE_AM) + if ((ftdi->type != TYPE_AM) && (ftdi->type != TYPE_230X)) { // Addr 0A: Chip configuration // Bit 7: 0 - reserved @@ -2582,9 +2669,9 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) // Bit 0: 1 - In EndPoint is Isochronous // j = 0; - if (eeprom->in_is_isochronous == 1) + if (eeprom->in_is_isochronous) j = j | 1; - if (eeprom->out_is_isochronous == 1) + if (eeprom->out_is_isochronous) j = j | 2; output[0x0A] = j; } @@ -2608,6 +2695,10 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) case TYPE_AM: case TYPE_BM: i += 0x94; + break; + case TYPE_230X: + i = 0xa0; + break; } /* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */ eeprom_size_mask = eeprom->size -1; @@ -2708,15 +2799,15 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) else output[0x01] &= ~HIGH_CURRENT_DRIVE; - if (eeprom->in_is_isochronous == 1) + if (eeprom->in_is_isochronous) output[0x0A] |= 0x1; else output[0x0A] &= ~0x1; - if (eeprom->out_is_isochronous == 1) + if (eeprom->out_is_isochronous) output[0x0A] |= 0x2; else output[0x0A] &= ~0x2; - if (eeprom->suspend_pull_downs == 1) + if (eeprom->suspend_pull_downs) output[0x0A] |= 0x4; else output[0x0A] &= ~0x4; @@ -2734,7 +2825,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x00] |= HIGH_CURRENT_DRIVE_R; output[0x01] = 0x40; /* Hard coded Endpoint Size*/ - if (eeprom->suspend_pull_downs == 1) + if (eeprom->suspend_pull_downs) output[0x0A] |= 0x4; else output[0x0A] &= ~0x4; @@ -2784,7 +2875,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) else output[0x01] &= ~SUSPEND_DBUS7_BIT; - if (eeprom->suspend_pull_downs == 1) + if (eeprom->suspend_pull_downs) output[0x0A] |= 0x4; else output[0x0A] &= ~0x4; @@ -2829,8 +2920,83 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) break; case TYPE_4232H: + if (eeprom->channel_a_driver == DRIVER_VCP) + output[0x00] |= DRIVER_VCP; + else + output[0x00] &= ~DRIVER_VCP; + if (eeprom->channel_b_driver == DRIVER_VCP) + output[0x01] |= DRIVER_VCP; + else + output[0x01] &= ~DRIVER_VCP; + if (eeprom->channel_c_driver == DRIVER_VCP) + output[0x00] |= (DRIVER_VCP << 4); + else + output[0x00] &= ~(DRIVER_VCP << 4); + if (eeprom->channel_d_driver == DRIVER_VCP) + output[0x01] |= (DRIVER_VCP << 4); + else + output[0x01] &= ~(DRIVER_VCP << 4); + + if (eeprom->suspend_pull_downs) + output[0x0a] |= 0x4; + else + output[0x0a] &= ~0x4; + + if (eeprom->channel_a_rs485enable) + output[0x0b] |= CHANNEL_IS_RS485 << 0; + else + output[0x0b] &= ~(CHANNEL_IS_RS485 << 0); + if (eeprom->channel_b_rs485enable) + output[0x0b] |= CHANNEL_IS_RS485 << 1; + else + output[0x0b] &= ~(CHANNEL_IS_RS485 << 1); + if (eeprom->channel_c_rs485enable) + output[0x0b] |= CHANNEL_IS_RS485 << 2; + else + output[0x0b] &= ~(CHANNEL_IS_RS485 << 2); + if (eeprom->channel_d_rs485enable) + output[0x0b] |= CHANNEL_IS_RS485 << 3; + else + output[0x0b] &= ~(CHANNEL_IS_RS485 << 3); + + if (eeprom->group0_drive > DRIVE_16MA) + output[0x0c] |= DRIVE_16MA; + else + output[0x0c] |= eeprom->group0_drive; + if (eeprom->group0_schmitt == IS_SCHMITT) + output[0x0c] |= IS_SCHMITT; + if (eeprom->group0_slew == SLOW_SLEW) + output[0x0c] |= SLOW_SLEW; + + if (eeprom->group1_drive > DRIVE_16MA) + output[0x0c] |= DRIVE_16MA<<4; + else + output[0x0c] |= eeprom->group1_drive<<4; + if (eeprom->group1_schmitt == IS_SCHMITT) + output[0x0c] |= IS_SCHMITT<<4; + if (eeprom->group1_slew == SLOW_SLEW) + output[0x0c] |= SLOW_SLEW<<4; + + if (eeprom->group2_drive > DRIVE_16MA) + output[0x0d] |= DRIVE_16MA; + else + output[0x0d] |= eeprom->group2_drive; + if (eeprom->group2_schmitt == IS_SCHMITT) + output[0x0d] |= IS_SCHMITT; + if (eeprom->group2_slew == SLOW_SLEW) + output[0x0d] |= SLOW_SLEW; + + if (eeprom->group3_drive > DRIVE_16MA) + output[0x0d] |= DRIVE_16MA<<4; + else + output[0x0d] |= eeprom->group3_drive<<4; + if (eeprom->group3_schmitt == IS_SCHMITT) + output[0x0d] |= IS_SCHMITT<<4; + if (eeprom->group3_slew == SLOW_SLEW) + output[0x0d] |= SLOW_SLEW<<4; + output[0x18] = eeprom->chip; - fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n"); + break; case TYPE_232H: output[0x00] = type2bit(eeprom->channel_a_type, TYPE_232H); @@ -2877,7 +3043,14 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x1e] = eeprom->chip; fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n"); break; - + case TYPE_230X: + output[0x00] = 0x80; /* Actually, leave the default value */ + output[0x0a] = 0x08; /* Enable USB Serial Number */ + output[0x0c] = (0x01) | (0x3 << 4); /* DBUS drive 4mA, CBUS drive 16mA */ + for (j = 0; j <= 6; j++) { + output[0x1a + j] = eeprom->cbus_function[j]; + } + break; } // calculate checksum @@ -2885,6 +3058,10 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) for (i = 0; i < eeprom->size/2-1; i++) { + if ((ftdi->type == TYPE_230X) && (i == 0x12)) { + /* FT230X has a user section in the MTP which is not part of the checksum */ + i = 0x40; + } value = output[i*2]; value += output[(i*2)+1] << 8; @@ -2895,6 +3072,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[eeprom->size-2] = checksum; output[eeprom->size-1] = checksum >> 8; + eeprom->initialized_for_connected_device = 1; return user_area_size; } /* Decode the encoded EEPROM field for the FTDI Mode into a value for the abstracted @@ -2936,8 +3114,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; int eeprom_size; struct ftdi_eeprom *eeprom; - unsigned char *buf = ftdi->eeprom->buf; - int release; + unsigned char *buf = NULL; if (ftdi == NULL) ftdi_error_return(-1,"No context"); @@ -2946,6 +3123,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom = ftdi->eeprom; eeprom_size = eeprom->size; + buf = ftdi->eeprom->buf; // Addr 02: Vendor ID eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8); @@ -2953,7 +3131,8 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) // Addr 04: Product ID eeprom->product_id = buf[0x04] + (buf[0x05] << 8); - release = buf[0x06] + (buf[0x07]<<8); + // Addr 06: Device release number + eeprom->release_number = buf[0x06] + (buf[0x07]<<8); // Addr 08: Config descriptor // Bit 7: always 1 @@ -2963,7 +3142,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom->remote_wakeup = buf[0x08] & 0x20; // Addr 09: Max power consumption: max power = value * 2 mA - eeprom->max_power = buf[0x09]; + eeprom->max_power = MAX_POWER_MILLIAMP_PER_UNIT * buf[0x09]; // Addr 0A: Chip configuration // Bit 7: 0 - reserved @@ -3053,6 +3232,10 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) for (i = 0; i < eeprom_size/2-1; i++) { + if ((ftdi->type == TYPE_230X) && (i == 0x12)) { + /* FT230X has a user section in the MTP which is not part of the checksum */ + i = 0x40; + } value = buf[i*2]; value += buf[(i*2)+1] << 8; @@ -3086,7 +3269,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) else if (ftdi->type == TYPE_R) { /* TYPE_R flags D2XX, not VCP as all others*/ - eeprom->channel_a_driver = (~buf[0x00]) & DRIVER_VCP; + eeprom->channel_a_driver = ~buf[0x00] & DRIVER_VCP; eeprom->high_current = buf[0x00] & HIGH_CURRENT_DRIVE_R; if ( (buf[0x01]&0x40) != 0x40) fprintf(stderr, @@ -3108,15 +3291,26 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom->cbus_function[3] = (buf[0x15] >> 4) & 0x0f; eeprom->cbus_function[4] = buf[0x16] & 0x0f; } - else if ((ftdi->type == TYPE_2232H) ||(ftdi->type == TYPE_4232H)) + else if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H)) { - eeprom->channel_a_type = bit2type(buf[0x00] & 0x7); eeprom->channel_a_driver = buf[0x00] & DRIVER_VCP; - eeprom->channel_b_type = bit2type(buf[0x01] & 0x7); eeprom->channel_b_driver = buf[0x01] & DRIVER_VCP; if (ftdi->type == TYPE_2232H) + { + eeprom->channel_a_type = bit2type(buf[0x00] & 0x7); + eeprom->channel_b_type = bit2type(buf[0x01] & 0x7); eeprom->suspend_dbus7 = buf[0x01] & SUSPEND_DBUS7_BIT; + } + else + { + eeprom->channel_c_driver = (buf[0x00] >> 4) & DRIVER_VCP; + eeprom->channel_d_driver = (buf[0x01] >> 4) & DRIVER_VCP; + eeprom->channel_a_rs485enable = buf[0x0b] & (CHANNEL_IS_RS485 << 0); + eeprom->channel_b_rs485enable = buf[0x0b] & (CHANNEL_IS_RS485 << 1); + eeprom->channel_c_rs485enable = buf[0x0b] & (CHANNEL_IS_RS485 << 2); + eeprom->channel_d_rs485enable = buf[0x0b] & (CHANNEL_IS_RS485 << 3); + } eeprom->chip = buf[0x18]; eeprom->group0_drive = buf[0x0c] & DRIVE_16MA; @@ -3157,18 +3351,30 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom->chip = buf[0x1e]; /*FIXME: Decipher more values*/ } + else if (ftdi->type == TYPE_230X) + { + for(i=0; i<4; i++) { + eeprom->cbus_function[i] = buf[0x1a + i] & 0xFF; + } + eeprom->group0_drive = buf[0x0c] & 0x03; + eeprom->group0_schmitt = buf[0x0c] & IS_SCHMITT; + eeprom->group0_slew = buf[0x0c] & SLOW_SLEW; + eeprom->group1_drive = (buf[0x0c] >> 4) & 0x03; + eeprom->group1_schmitt = (buf[0x0c] >> 4) & IS_SCHMITT; + eeprom->group1_slew = (buf[0x0c] >> 4) & SLOW_SLEW; + } if (verbose) { char *channel_mode[] = {"UART", "FIFO", "CPU", "OPTO", "FT1284"}; fprintf(stdout, "VID: 0x%04x\n",eeprom->vendor_id); fprintf(stdout, "PID: 0x%04x\n",eeprom->product_id); - fprintf(stdout, "Release: 0x%04x\n",release); + fprintf(stdout, "Release: 0x%04x\n",eeprom->release_number); if (eeprom->self_powered) fprintf(stdout, "Self-Powered%s", (eeprom->remote_wakeup)?", USB Remote Wake Up\n":"\n"); else - fprintf(stdout, "Bus Powered: %3d mA%s", eeprom->max_power * 2, + fprintf(stdout, "Bus Powered: %3d mA%s", eeprom->max_power, (eeprom->remote_wakeup)?" USB Remote Wake Up\n":"\n"); if (eeprom->manufacturer) fprintf(stdout, "Manufacturer: %s\n",eeprom->manufacturer); @@ -3258,7 +3464,29 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) fprintf(stdout,"C%d Function: %s\n", i, cbush_mux[eeprom->cbus_function[i]]); } - + } + else if (ftdi->type == TYPE_230X) + { + int i; + char *cbush_mux[] = {"TRISTATE","RXLED","TXLED", "TXRXLED","PWREN", + "SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN", + "CLK24","CLK12","CLK6","BAT_DETECT","BAT_DETECT#", + "I2C_TXE#", "I2C_RXF#", "VBUS_SENSE", "BB_WR#", + "BBRD#", "TIME_STAMP", "AWAKE#", + }; + fprintf(stdout,"IOBUS has %d mA drive%s%s\n", + (eeprom->group0_drive+1) *4, + (eeprom->group0_schmitt)?" Schmitt Input":"", + (eeprom->group0_slew)?" Slow Slew":""); + fprintf(stdout,"CBUS has %d mA drive%s%s\n", + (eeprom->group1_drive+1) *4, + (eeprom->group1_schmitt)?" Schmitt Input":"", + (eeprom->group1_slew)?" Slow Slew":""); + for (i=0; i<4; i++) + { + if (eeprom->cbus_function[i]<= CBUSH_AWAKE) + fprintf(stdout,"CBUS%d Function: %s\n", i, cbush_mux[eeprom->cbus_function[i]]); + } } if (ftdi->type == TYPE_R) @@ -3319,6 +3547,9 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case PRODUCT_ID: *value = ftdi->eeprom->product_id; break; + case RELEASE_NUMBER: + *value = ftdi->eeprom->release_number; + break; case SELF_POWERED: *value = ftdi->eeprom->self_powered; break; @@ -3364,6 +3595,24 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case CHANNEL_B_DRIVER: *value = ftdi->eeprom->channel_b_driver; break; + case CHANNEL_C_DRIVER: + *value = ftdi->eeprom->channel_c_driver; + break; + case CHANNEL_D_DRIVER: + *value = ftdi->eeprom->channel_d_driver; + break; + case CHANNEL_A_RS485: + *value = ftdi->eeprom->channel_a_rs485enable; + break; + case CHANNEL_B_RS485: + *value = ftdi->eeprom->channel_b_rs485enable; + break; + case CHANNEL_C_RS485: + *value = ftdi->eeprom->channel_c_rs485enable; + break; + case CHANNEL_D_RS485: + *value = ftdi->eeprom->channel_d_rs485enable; + break; case CBUS_FUNCTION_0: *value = ftdi->eeprom->cbus_function[0]; break; @@ -3488,6 +3737,9 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case PRODUCT_ID: ftdi->eeprom->product_id = value; break; + case RELEASE_NUMBER: + ftdi->eeprom->release_number = value; + break; case SELF_POWERED: ftdi->eeprom->self_powered = value; break; @@ -3533,6 +3785,24 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case CHANNEL_B_DRIVER: ftdi->eeprom->channel_b_driver = value; break; + case CHANNEL_C_DRIVER: + ftdi->eeprom->channel_c_driver = value; + break; + case CHANNEL_D_DRIVER: + ftdi->eeprom->channel_d_driver = value; + break; + case CHANNEL_A_RS485: + ftdi->eeprom->channel_a_rs485enable = value; + break; + case CHANNEL_B_RS485: + ftdi->eeprom->channel_b_rs485enable = value; + break; + case CHANNEL_C_RS485: + ftdi->eeprom->channel_c_rs485enable = value; + break; + case CHANNEL_D_RS485: + ftdi->eeprom->channel_d_rs485enable = value; + break; case CBUS_FUNCTION_0: ftdi->eeprom->cbus_function[0] = value; break; @@ -3631,6 +3901,7 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu default : ftdi_error_return(-1, "Request to unknown EEPROM value"); } + ftdi->eeprom->initialized_for_connected_device = 0; return 0; } @@ -3892,6 +4163,10 @@ int ftdi_write_eeprom(struct ftdi_context *ftdi) for (i = 0; i < ftdi->eeprom->size/2; i++) { + /* Do not try to write to reserved area */ + if ((ftdi->type == TYPE_230X) && (i == 0x40)) { + i = 0x50; + } usb_val = eeprom[i*2]; usb_val += eeprom[(i*2)+1] << 8; if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,