X-Git-Url: http://developer.intra2net.com/git/?a=blobdiff_plain;f=src%2Fftdi.c;h=41496ee1312e5337f25adeaaabc7510908458dd6;hb=ce3940810901906eb00d67fe259d5540a9008630;hp=b22a55b755a35da96227ed431d98797bf2c709f0;hpb=249888c8bdc8907bb664f8e3af674a630533eff8;p=libftdi diff --git a/src/ftdi.c b/src/ftdi.c index b22a55b..41496ee 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -93,10 +93,7 @@ int ftdi_init(struct ftdi_context *ftdi) ftdi->writebuffer_chunksize = 4096; ftdi->max_packet_size = 0; - ftdi->interface = 0; - ftdi->index = 0; - ftdi->in_ep = 0x02; - ftdi->out_ep = 0x81; + ftdi_set_interface(ftdi, INTERFACE_ANY); ftdi->bitbang_mode = 1; /* when bitbang is enabled this holds the number of the mode */ ftdi->error_str = NULL; @@ -149,7 +146,10 @@ int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface) { case INTERFACE_ANY: case INTERFACE_A: - /* ftdi_usb_open_desc cares to set the right index, depending on the found chip */ + ftdi->interface = 0; + ftdi->index = INTERFACE_A; + ftdi->in_ep = 0x02; + ftdi->out_ep = 0x81; break; case INTERFACE_B: ftdi->interface = 1; @@ -531,19 +531,6 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, libusb_device *dev) else if (desc.bcdDevice == 0x800) ftdi->type = TYPE_4232H; - // Set default interface on dual/quad type chips - switch(ftdi->type) - { - case TYPE_2232C: - case TYPE_2232H: - case TYPE_4232H: - if (!ftdi->index) - ftdi->index = INTERFACE_A; - break; - default: - break; - } - // Determine maximum packet size ftdi->max_packet_size = _ftdi_determine_max_packet_size(ftdi, dev); @@ -630,12 +617,12 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, char string[256]; int i = 0; - if (libusb_init(&ftdi->usb_ctx) < 0) - ftdi_error_return(-11, "libusb_init() failed"); - if (ftdi == NULL) ftdi_error_return(-11, "ftdi context invalid"); + if (libusb_init(&ftdi->usb_ctx) < 0) + ftdi_error_return(-11, "libusb_init() failed"); + if (libusb_get_device_list(ftdi->usb_ctx, &devs) < 0) ftdi_error_return(-12, "libusb_get_device_list() failed"); @@ -656,12 +643,12 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, { if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iProduct, (unsigned char *)string, sizeof(string)) < 0) { - libusb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); ftdi_error_return_free_device_list(-8, "unable to fetch product description", devs); } if (strncmp(string, description, sizeof(string)) != 0) { - libusb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); continue; } } @@ -1322,9 +1309,9 @@ static void 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; - - tc->offset = transfer->actual_length; - + + tc->offset += transfer->actual_length; + if (tc->offset == tc->size) { tc->completed = 1; @@ -1388,7 +1375,9 @@ struct ftdi_transfer_control *ftdi_write_data_submit(struct ftdi_context *ftdi, else write_size = ftdi->writebuffer_chunksize; - libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->in_ep, buf, write_size, ftdi_write_data_cb, tc, ftdi->usb_write_timeout); + libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->in_ep, buf, + write_size, ftdi_write_data_cb, tc, + ftdi->usb_write_timeout); transfer->type = LIBUSB_TRANSFER_TYPE_BULK; ret = libusb_submit_transfer(transfer); @@ -1514,17 +1503,21 @@ int ftdi_transfer_data_done(struct ftdi_transfer_control *tc) break; libusb_free_transfer(tc->transfer); free (tc); - tc = NULL; return ret; } } - if (tc->transfer->status == LIBUSB_TRANSFER_COMPLETED) - ret = tc->offset; - else - ret = -1; - - libusb_free_transfer(tc->transfer); + ret = tc->offset; + /** + * tc->transfer could be NULL if "(size <= ftdi->readbuffer_remaining)" + * at ftdi_read_data_submit(). Therefore, we need to check it here. + **/ + if (tc->transfer) + { + if (tc->transfer->status != LIBUSB_TRANSFER_COMPLETED) + ret = -1; + libusb_free_transfer(tc->transfer); + } free(tc); return ret; } @@ -1963,7 +1956,7 @@ int ftdi_poll_modem_status(struct ftdi_context *ftdi, unsigned short *status) if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_POLL_MODEM_STATUS_REQUEST, 0, ftdi->index, (unsigned char *)usb_val, 2, ftdi->usb_read_timeout) != 2) ftdi_error_return(-1, "getting modem status failed"); - *status = (usb_val[1] << 8) | usb_val[0]; + *status = (usb_val[1] << 8) | (usb_val[0] & 0xFF); return 0; } @@ -2170,6 +2163,8 @@ void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom *eeprom, */ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) { + int i; + if (eeprom == NULL) return; @@ -2178,7 +2173,7 @@ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) eeprom->self_powered = 1; eeprom->remote_wakeup = 1; - eeprom->BM_type_chip = 1; + eeprom->chip_type = TYPE_BM; eeprom->in_is_isochronous = 0; eeprom->out_is_isochronous = 0; @@ -2192,6 +2187,12 @@ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) eeprom->manufacturer = NULL; eeprom->product = NULL; eeprom->serial = NULL; + for (i=0; i < 5; i++) + { + eeprom->cbus_function[i] = 0; + } + eeprom->high_current = 0; + eeprom->invert = 0; eeprom->size = FTDI_DEFAULT_EEPROM_SIZE; } @@ -2221,12 +2222,16 @@ void ftdi_eeprom_free(struct ftdi_eeprom *eeprom) Build binary output from ftdi_eeprom structure. Output is suitable for ftdi_write_eeprom(). + \note This function doesn't handle FT2232x devices. Only FT232x. \param eeprom Pointer to ftdi_eeprom \param output Buffer of 128 bytes to store eeprom image to - \retval >0: used eeprom size + \retval >0: free eeprom size \retval -1: eeprom size (128 bytes) exceeded by custom strings \retval -2: Invalid eeprom pointer + \retval -3: Invalid cbus function setting + \retval -4: Chip doesn't support invert + \retval -5: Chip doesn't support high current drive */ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) { @@ -2234,6 +2239,7 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, 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}; if (eeprom == NULL) return -2; @@ -2245,6 +2251,18 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, 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] && eeprom->chip_type != TYPE_R)) return -3; + } + if (eeprom->chip_type != TYPE_R) + { + if (eeprom->invert) return -4; + if (eeprom->high_current) return -5; + } + size_check = eeprom->size; size_check -= 28; // 28 are always in use (fixed) @@ -2252,7 +2270,7 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) // 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; + if (eeprom->size>=256) size_check = 120; size_check -= manufacturer_size*2; size_check -= product_size*2; size_check -= serial_size*2; @@ -2264,7 +2282,12 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) // empty eeprom memset (output, 0, eeprom->size); - // Addr 00: Stay 00 00 + // Addr 00: High current IO + output[0x00] = eeprom->high_current ? HIGH_CURRENT_DRIVE : 0; + // Addr 01: IN endpoint size (for R type devices, different for FT2232) + if (eeprom->chip_type == TYPE_R) { + output[0x01] = 0x40; + } // Addr 02: Vendor ID output[0x02] = eeprom->vendor_id; output[0x03] = eeprom->vendor_id >> 8; @@ -2275,11 +2298,22 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) // Addr 06: Device release number (0400h for BM features) output[0x06] = 0x00; - - if (eeprom->BM_type_chip == 1) - output[0x07] = 0x04; - else - output[0x07] = 0x02; + switch (eeprom->chip_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; + default: + output[0x07] = 0x00; + } // Addr 08: Config descriptor // Bit 7: always 1 @@ -2319,8 +2353,8 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) j = j | 16; output[0x0A] = j; - // Addr 0B: reserved - output[0x0B] = 0x00; + // 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 @@ -2343,9 +2377,23 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) // Addr 13: Length of serial string output[0x13] = serial_size*2 + 2; + // Addr 14: CBUS function: CBUS0, CBUS1 + // Addr 15: CBUS function: CBUS2, CBUS3 + // Addr 16: CBUS function: CBUS5 + output[0x14] = eeprom->cbus_function[0] | (eeprom->cbus_function[1] << 4); + output[0x15] = eeprom->cbus_function[2] | (eeprom->cbus_function[3] << 4); + output[0x16] = eeprom->cbus_function[4]; + // Addr 17: Unknown + // Dynamic content - i=0x14; - if (eeprom->size>=256) i = 0x80; + // In images produced by FTDI's FT_Prog for FT232R strings start at 0x18 + // Space till 0x18 should be considered as reserved. + if (eeprom->chip_type >= TYPE_R) { + i = 0x18; + } else { + i = 0x14; + } + if (eeprom->size >= 256) i = 0x80; // Output manufacturer @@ -2439,7 +2487,8 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) // empty eeprom struct memset(eeprom, 0, sizeof(struct ftdi_eeprom)); - // Addr 00: Stay 00 00 + // Addr 00: High current IO + eeprom->high_current = (buf[0x02] & HIGH_CURRENT_DRIVE); // Addr 02: Vendor ID eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8); @@ -2450,14 +2499,17 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) value = buf[0x06] + (buf[0x07]<<8); switch (value) { + case 0x0600: + eeprom->chip_type = TYPE_R; + break; case 0x0400: - eeprom->BM_type_chip = 1; + eeprom->chip_type = TYPE_BM; break; case 0x0200: - eeprom->BM_type_chip = 0; + eeprom->chip_type = TYPE_AM; break; default: // Unknown device - eeprom->BM_type_chip = 0; + eeprom->chip_type = 0; break; } @@ -2490,7 +2542,8 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) if (j&0x08) eeprom->use_serial = 1; if (j&0x10) eeprom->change_usb_version = 1; - // Addr 0B: reserved + // Addr 0B: Invert data lines + eeprom->invert = buf[0x0B]; // Addr 0C: USB version low byte when 0x0A bit 4 is set // Addr 0D: USB version high byte when 0x0A bit 4 is set @@ -2517,6 +2570,19 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) if (serial_size > 0) eeprom->serial = malloc(serial_size); else eeprom->serial = NULL; + // Addr 14: CBUS function: CBUS0, CBUS1 + // Addr 15: CBUS function: CBUS2, CBUS3 + // Addr 16: CBUS function: CBUS5 + if (eeprom->chip_type == TYPE_R) { + eeprom->cbus_function[0] = buf[0x14] & 0x0f; + eeprom->cbus_function[1] = (buf[0x14] >> 4) & 0x0f; + eeprom->cbus_function[2] = buf[0x15] & 0x0f; + eeprom->cbus_function[3] = (buf[0x15] >> 4) & 0x0f; + eeprom->cbus_function[4] = buf[0x16] & 0x0f; + } else { + for (j=0; j<5; j++) eeprom->cbus_function[j] = 0; + } + // Decode manufacturer i = buf[0x0E] & 0x7f; // offset for (j=0;jusb_dev == NULL) ftdi_error_return(-2, "USB device unavailable"); - if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, eeprom_addr, (char *)eeprom_val, 2, ftdi->usb_read_timeout) != 2) + if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, eeprom_addr, (unsigned char *)eeprom_val, 2, ftdi->usb_read_timeout) != 2) ftdi_error_return(-1, "reading eeprom failed"); return 0;