X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=aa4b4ecf160fe7280d71fab7c37c6fa7a5a84dc2;hp=90dfae50e18e693b9271cb97e2fd0a137e367543;hb=6e962b9a0991bf28571c7a143a532d83237c05af;hpb=a7e053532fb66aabe0d232cb335be4746cc052b3 diff --git a/src/ftdi.c b/src/ftdi.c index 90dfae5..aa4b4ec 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -2,7 +2,7 @@ ftdi.c - description ------------------- begin : Fri Apr 4 2003 - copyright : (C) 2003-2013 by Intra2net AG and the libftdi developers + copyright : (C) 2003-2014 by Intra2net AG and the libftdi developers email : opensource@intra2net.com ***************************************************************************/ @@ -278,7 +278,7 @@ void ftdi_set_usbdev (struct ftdi_context *ftdi, libusb_device_handle *usb) * * @return ftdi_version_info Library version information **/ -struct ftdi_version_info ftdi_get_library_version() +struct ftdi_version_info ftdi_get_library_version(void) { struct ftdi_version_info ver; @@ -295,7 +295,7 @@ struct ftdi_version_info ftdi_get_library_version() Finds all ftdi devices with given VID:PID on the usb bus. Creates a new ftdi_device_list which needs to be deallocated by ftdi_list_free() after use. With VID:PID 0:0, search for the default devices - (0x403:0x6001, 0x403:0x6010, 0x403:0x6011, 0x403:0x6014) + (0x403:0x6001, 0x403:0x6010, 0x403:0x6011, 0x403:0x6014, 0x403:0x6015) \param ftdi pointer to ftdi_context \param devlist Pointer where to store list of found devices @@ -328,11 +328,12 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli if (libusb_get_device_descriptor(dev, &desc) < 0) ftdi_error_return_free_device_list(-6, "libusb_get_device_descriptor() failed", devs); - if (((vendor != 0 && product != 0) && + if (((vendor || product) && desc.idVendor == vendor && desc.idProduct == product) || - ((vendor == 0 && product == 0) && + (!(vendor || product) && (desc.idVendor == 0x403) && (desc.idProduct == 0x6001 || desc.idProduct == 0x6010 - || desc.idProduct == 0x6011 || desc.idProduct == 0x6014))) + || desc.idProduct == 0x6011 || desc.idProduct == 0x6014 + || desc.idProduct == 0x6015))) { *curdev = (struct ftdi_device_list*)malloc(sizeof(struct ftdi_device_list)); if (!*curdev) @@ -413,8 +414,8 @@ int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct libusb_device * dev, if ((ftdi==NULL) || (dev==NULL)) return -1; - if (libusb_open(dev, &ftdi->usb_dev) < 0) - ftdi_error_return(-4, "libusb_open() failed"); + if (ftdi->usb_dev == NULL && libusb_open(dev, &ftdi->usb_dev) < 0) + ftdi_error_return(-4, "libusb_open() failed"); if (libusb_get_device_descriptor(dev, &desc) < 0) ftdi_error_return(-11, "libusb_get_device_descriptor() failed"); @@ -470,7 +471,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 || ftdi->type == TYPE_230X) + if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H) packet_size = 512; else packet_size = 64; @@ -1018,8 +1019,8 @@ static int ftdi_to_clkbits_AM(int baudrate, unsigned long *encoded_divisor) static const char am_adjust_up[8] = {0, 0, 0, 1, 0, 3, 2, 1}; static const char am_adjust_dn[8] = {0, 0, 0, 1, 0, 1, 2, 3}; int divisor, best_divisor, best_baud, best_baud_diff; - divisor = 24000000 / baudrate; int i; + divisor = 24000000 / baudrate; // Round down to supported fraction (AM only) divisor -= am_adjust_dn[divisor & 7]; @@ -1175,7 +1176,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) || (ftdi->type == TYPE_230X)) + if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H) || (ftdi->type == TYPE_232H)) { if(baudrate*10 > H_CLK /0x3fff) { @@ -1200,7 +1201,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 || ftdi->type == TYPE_230X) + if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H) { *index = (unsigned short)(encoded_divisor >> 8); *index &= 0xFF00; @@ -1393,7 +1394,7 @@ int ftdi_write_data(struct ftdi_context *ftdi, const unsigned char *buf, int siz return offset; } -static void ftdi_read_data_cb(struct libusb_transfer *transfer) +static void LIBUSB_CALL ftdi_read_data_cb(struct libusb_transfer *transfer) { struct ftdi_transfer_control *tc = (struct ftdi_transfer_control *) transfer->user_data; struct ftdi_context *ftdi = tc->ftdi; @@ -1475,7 +1476,7 @@ static void ftdi_read_data_cb(struct libusb_transfer *transfer) } -static void ftdi_write_data_cb(struct libusb_transfer *transfer) +static void LIBUSB_CALL ftdi_write_data_cb(struct libusb_transfer *transfer) { struct ftdi_transfer_control *tc = (struct ftdi_transfer_control *) transfer->user_data; struct ftdi_context *ftdi = tc->ftdi; @@ -2391,10 +2392,10 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, { 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; + eeprom->cbus_function[0] = CBUSX_TXDEN; + eeprom->cbus_function[1] = CBUSX_RXLED; + eeprom->cbus_function[2] = CBUSX_TXLED; + eeprom->cbus_function[3] = CBUSX_SLEEP; } else { @@ -2487,7 +2488,7 @@ int ftdi_eeprom_set_strings(struct ftdi_context *ftdi, char * manufacturer, } -/*FTD2XX doesn't check for values not fitting in the ACBUS Signal oprtions*/ +/*FTD2XX doesn't check for values not fitting in the ACBUS Signal options*/ void set_ft232h_cbus(struct ftdi_eeprom *eeprom, unsigned char * output) { int i; @@ -2562,7 +2563,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) unsigned char i, j, eeprom_size_mask; unsigned short checksum, value; unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; - int user_area_size; + int user_area_size, free_start, free_end; struct ftdi_eeprom *eeprom; unsigned char * output; @@ -2597,12 +2598,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) { case TYPE_AM: case TYPE_BM: + case TYPE_R: user_area_size = 96; // base size for strings (total of 48 characters) break; case TYPE_2232C: 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; @@ -2709,6 +2710,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) } /* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */ eeprom_size_mask = eeprom->size -1; + free_end = i & eeprom_size_mask; // Addr 0E: Offset of the manufacturer string + 0x80, calculated later // Addr 0F: Length of manufacturer string @@ -2776,7 +2778,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) case TYPE_BM: output[0x0C] = eeprom->usb_version & 0xff; output[0x0D] = (eeprom->usb_version>>8) & 0xff; - if (eeprom->use_usb_version == USE_USB_VERSION_BIT) + if (eeprom->use_usb_version) output[0x0A] |= USE_USB_VERSION_BIT; else output[0x0A] &= ~USE_USB_VERSION_BIT; @@ -2818,7 +2820,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x0A] |= 0x4; else output[0x0A] &= ~0x4; - if (eeprom->use_usb_version == USE_USB_VERSION_BIT) + if (eeprom->use_usb_version) output[0x0A] |= USE_USB_VERSION_BIT; else output[0x0A] &= ~USE_USB_VERSION_BIT; @@ -2830,6 +2832,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) case TYPE_R: if (eeprom->high_current == HIGH_CURRENT_DRIVE_R) output[0x00] |= HIGH_CURRENT_DRIVE_R; + if (eeprom->external_oscillator) + output[0x00] |= 0x02; output[0x01] = 0x40; /* Hard coded Endpoint Size*/ if (eeprom->suspend_pull_downs) @@ -2840,22 +2844,22 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x0C] = eeprom->usb_version & 0xff; output[0x0D] = (eeprom->usb_version>>8) & 0xff; - if (eeprom->cbus_function[0] > CBUS_BB) + if (eeprom->cbus_function[0] > CBUS_BB_RD) output[0x14] = CBUS_TXLED; else output[0x14] = eeprom->cbus_function[0]; - if (eeprom->cbus_function[1] > CBUS_BB) + if (eeprom->cbus_function[1] > CBUS_BB_RD) output[0x14] |= CBUS_RXLED<<4; else output[0x14] |= eeprom->cbus_function[1]<<4; - if (eeprom->cbus_function[2] > CBUS_BB) + if (eeprom->cbus_function[2] > CBUS_BB_RD) output[0x15] = CBUS_TXDEN; else output[0x15] = eeprom->cbus_function[2]; - if (eeprom->cbus_function[3] > CBUS_BB) + if (eeprom->cbus_function[3] > CBUS_BB_RD) output[0x15] |= CBUS_PWREN<<4; else output[0x15] |= eeprom->cbus_function[3]<<4; @@ -3059,14 +3063,48 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) 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 */ + /*FIXME: Make DBUS & CBUS Control configurable*/ + output[0x0c] = 0; /* DBUS drive 4mA, CBUS drive 4 mA like factory default */ for (j = 0; j <= 6; j++) { output[0x1a + j] = eeprom->cbus_function[j]; } + output[0x0b] = eeprom->invert; break; } + /* First address without use */ + free_start = 0; + switch (ftdi->type) + { + case TYPE_230X: + free_start += 2; + case TYPE_232H: + free_start += 6; + case TYPE_2232H: + case TYPE_4232H: + free_start += 2; + case TYPE_R: + free_start += 2; + case TYPE_2232C: + free_start++; + case TYPE_AM: + case TYPE_BM: + free_start += 0x14; + } + + /* Arbitrary user data */ + if (eeprom->user_data && eeprom->user_data_size >= 0) + { + if (eeprom->user_data_addr < free_start) + fprintf(stderr,"Warning, user data starts inside the generated data!\n"); + if (eeprom->user_data_addr + eeprom->user_data_size >= free_end) + fprintf(stderr,"Warning, user data overlaps the strings area!\n"); + if (eeprom->user_data_addr + eeprom->user_data_size > eeprom->size) + ftdi_error_return(-1,"eeprom size exceeded"); + memcpy(output + eeprom->user_data_addr, eeprom->user_data, eeprom->user_data_size); + } + // calculate checksum checksum = 0xAAAA; @@ -3077,9 +3115,18 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) /* 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; - + if ((ftdi->type == TYPE_230X) && (i >= 0x40) && (i < 0x50)) { + uint16_t data; + if (ftdi_read_eeprom_location(ftdi, i, &data)) { + fprintf(stderr, "Reading Factory Configuration Data failed\n"); + i = 0x50; + } + value = data; + } + else { + value = output[i*2]; + value += output[(i*2)+1] << 8; + } checksum = value^checksum; checksum = (checksum << 1) | (checksum >> 15); } @@ -3110,9 +3157,26 @@ static unsigned char bit2type(unsigned char bits) } return 0; } +/* Decode 230X / 232R type chips invert bits + * Prints directly to stdout. +*/ +static void print_inverted_bits(int invert) +{ + char *r_bits[] = {"TXD","RXD","RTS","CTS","DTR","DSR","DCD","RI"}; + int i; + + fprintf(stdout,"Inverted bits:"); + for (i=0; i<8; i++) + if ((invert & (1<in_is_isochronous = buf[0x0A]&0x01; eeprom->out_is_isochronous = buf[0x0A]&0x02; eeprom->suspend_pull_downs = buf[0x0A]&0x04; - eeprom->use_serial = (buf[0x0A] & USE_SERIAL_NUM)?1:0; - eeprom->use_usb_version = buf[0x0A] & USE_USB_VERSION_BIT; + eeprom->use_serial = !!(buf[0x0A] & USE_SERIAL_NUM); + eeprom->use_usb_version = !!(buf[0x0A] & USE_USB_VERSION_BIT); // Addr 0C: USB version low byte when 0x0A // Addr 0D: USB version high byte when 0x0A @@ -3287,6 +3351,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) /* TYPE_R flags D2XX, not VCP as all others*/ eeprom->channel_a_driver = ~buf[0x00] & DRIVER_VCP; eeprom->high_current = buf[0x00] & HIGH_CURRENT_DRIVE_R; + eeprom->external_oscillator = buf[0x00] & 0x02; if ( (buf[0x01]&0x40) != 0x40) fprintf(stderr, "TYPE_R EEPROM byte[0x01] Bit 6 unexpected Endpoint size." @@ -3344,8 +3409,6 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) } else if (ftdi->type == TYPE_232H) { - int i; - eeprom->channel_a_type = buf[0x00] & 0xf; eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0; eeprom->clock_polarity = buf[0x01] & FT1284_CLK_IDLE_STATE; @@ -3379,6 +3442,8 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom->group1_drive = (buf[0x0c] >> 4) & 0x03; eeprom->group1_schmitt = (buf[0x0c] >> 4) & IS_SCHMITT; eeprom->group1_slew = (buf[0x0c] >> 4) & SLOW_SLEW; + + eeprom->invert = buf[0xb]; } if (verbose) @@ -3400,8 +3465,10 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) if (eeprom->serial) fprintf(stdout, "Serial: %s\n",eeprom->serial); fprintf(stdout, "Checksum : %04x\n", checksum); - if (ftdi->type == TYPE_R) + if (ftdi->type == TYPE_R) { fprintf(stdout, "Internal EEPROM\n"); + fprintf(stdout,"Oscillator: %s\n", eeprom->external_oscillator?"External":"Internal"); + } else if (eeprom->chip >= 0x46) fprintf(stdout, "Attached EEPROM: 93x%02x\n", eeprom->chip); if (eeprom->suspend_dbus7) @@ -3421,20 +3488,20 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) channel_mode[eeprom->channel_a_type], (eeprom->channel_a_driver)?" VCP":"", (eeprom->high_current_a)?" High Current IO":""); - if (ftdi->type >= TYPE_232H) + if (ftdi->type == TYPE_232H) { fprintf(stdout,"FT1284 Mode Clock is idle %s, %s first, %sFlow Control\n", (eeprom->clock_polarity)?"HIGH":"LOW", (eeprom->data_order)?"LSB":"MSB", (eeprom->flow_control)?"":"No "); } - if ((ftdi->type >= TYPE_2232C) && (ftdi->type != TYPE_R) && (ftdi->type != TYPE_232H)) + if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H)) fprintf(stdout,"Channel B has Mode %s%s%s\n", channel_mode[eeprom->channel_b_type], (eeprom->channel_b_driver)?" VCP":"", (eeprom->high_current_b)?" High Current IO":""); if (((ftdi->type == TYPE_BM) || (ftdi->type == TYPE_2232C)) && - eeprom->use_usb_version == USE_USB_VERSION_BIT) + eeprom->use_usb_version) fprintf(stdout,"Use explicit USB Version %04x\n",eeprom->usb_version); if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H)) @@ -3462,8 +3529,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) } else if (ftdi->type == TYPE_232H) { - int i; - char *cbush_mux[] = {"TRISTATE","RXLED","TXLED", "TXRXLED","PWREN", + char *cbush_mux[] = {"TRISTATE","TXLED","RXLED", "TXRXLED","PWREN", "SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN", "CLK30","CLK15","CLK7_5" }; @@ -3484,14 +3550,13 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) } else if (ftdi->type == TYPE_230X) { - int i; - char *cbush_mux[] = {"TRISTATE","RXLED","TXLED", "TXRXLED","PWREN", + char *cbusx_mux[] = {"TRISTATE","TXLED","RXLED", "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", + fprintf(stdout,"DBUS has %d mA drive%s%s\n", (eeprom->group0_drive+1) *4, (eeprom->group0_schmitt)?" Schmitt Input":"", (eeprom->group0_slew)?" Slow Slew":""); @@ -3501,9 +3566,12 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) (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 (eeprom->cbus_function[i]<= CBUSX_AWAKE) + fprintf(stdout,"CBUS%d Function: %s\n", i, cbusx_mux[eeprom->cbus_function[i]]); } + + if (eeprom->invert) + print_inverted_bits(eeprom->invert); } if (ftdi->type == TYPE_R) @@ -3515,17 +3583,11 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) char *cbus_BB[] = {"RXF","TXE","RD", "WR"}; if (eeprom->invert) - { - char *r_bits[] = {"TXD","RXD","RTS", "CTS","DTR","DSR","DCD","RI"}; - fprintf(stdout,"Inverted bits:"); - for (i=0; i<8; i++) - if ((eeprom->invert & (1<invert); + for (i=0; i<5; i++) { - if (eeprom->cbus_function[i]cbus_function[i]<=CBUS_BB_RD) fprintf(stdout,"C%d Function: %s\n", i, cbus_mux[eeprom->cbus_function[i]]); else @@ -3658,7 +3720,7 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu *value = ftdi->eeprom->cbus_function[8]; break; case CBUS_FUNCTION_9: - *value = ftdi->eeprom->cbus_function[8]; + *value = ftdi->eeprom->cbus_function[9]; break; case HIGH_CURRENT: *value = ftdi->eeprom->high_current; @@ -3726,6 +3788,9 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case CHIP_SIZE: *value = ftdi->eeprom->size; break; + case EXTERNAL_OSCILLATOR: + *value = ftdi->eeprom->external_oscillator; + break; default: ftdi_error_return(-1, "Request for unknown EEPROM value"); } @@ -3915,6 +3980,14 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu break; case CHIP_SIZE: ftdi_error_return(-2, "EEPROM Value can't be changed"); + break; + case EXTERNAL_OSCILLATOR: + ftdi->eeprom->external_oscillator = value; + break; + case USER_DATA_ADDR: + ftdi->eeprom->user_data_addr = value; + break; + default : ftdi_error_return(-1, "Request to unknown EEPROM value"); } @@ -3956,7 +4029,7 @@ int ftdi_get_eeprom_buf(struct ftdi_context *ftdi, unsigned char * buf, int size \param size Size of buffer \retval 0: All fine - \retval -1: struct ftdi_contxt or ftdi_eeprom of buf missing + \retval -1: struct ftdi_context or ftdi_eeprom or buf missing */ int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, int size) { @@ -3972,6 +4045,25 @@ int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, in return 0; } +/** Set the EEPROM user data content from the user-supplied prefilled buffer + + \param ftdi pointer to ftdi_context + \param buf buffer to read EEPROM user data content + \param size Size of buffer + + \retval 0: All fine + \retval -1: struct ftdi_context or ftdi_eeprom or buf missing +*/ +int ftdi_set_eeprom_user_data(struct ftdi_context *ftdi, const char * buf, int size) +{ + if (!ftdi || !(ftdi->eeprom) || !buf) + ftdi_error_return(-1, "No appropriate structure"); + + ftdi->eeprom->user_data_size = size; + ftdi->eeprom->user_data = buf; + return 0; +} + /** Read eeprom location @@ -4217,7 +4309,7 @@ int ftdi_erase_eeprom(struct ftdi_context *ftdi) if (ftdi == NULL || ftdi->usb_dev == NULL) ftdi_error_return(-2, "USB device unavailable"); - if (ftdi->type == TYPE_R) + if ((ftdi->type == TYPE_R) || (ftdi->type == TYPE_230X)) { ftdi->eeprom->chip = 0; return 0;