X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=f5d263cc1983ceabe08158f9eb24e61fe3fb7dd7;hp=aa4b4ecf160fe7280d71fab7c37c6fa7a5a84dc2;hb=6f9f969dc7e359296e562ee9731081cefaf06b20;hpb=6e962b9a0991bf28571c7a143a532d83237c05af diff --git a/src/ftdi.c b/src/ftdi.c index aa4b4ec..f5d263c 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -406,16 +406,76 @@ void ftdi_list_free2(struct ftdi_device_list *devlist) \retval -9: get serial number failed \retval -11: libusb_get_device_descriptor() failed */ -int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct libusb_device * dev, - char * manufacturer, int mnf_len, char * description, int desc_len, char * serial, int serial_len) +int ftdi_usb_get_strings(struct ftdi_context *ftdi, + struct libusb_device *dev, + char *manufacturer, int mnf_len, + char *description, int desc_len, + char *serial, int serial_len) { - struct libusb_device_descriptor desc; + int ret; if ((ftdi==NULL) || (dev==NULL)) return -1; if (ftdi->usb_dev == NULL && libusb_open(dev, &ftdi->usb_dev) < 0) - ftdi_error_return(-4, "libusb_open() failed"); + ftdi_error_return(-4, "libusb_open() failed"); + + // ftdi->usb_dev will not be NULL when entering ftdi_usb_get_strings2(), so + // it won't be closed either. This allows us to close it whether we actually + // called libusb_open() up above or not. This matches the expected behavior + // (and note) for ftdi_usb_get_strings(). + ret = ftdi_usb_get_strings2(ftdi, dev, + manufacturer, mnf_len, + description, desc_len, + serial, serial_len); + + // only close it if it was successful, as all other return codes close + // before returning already. + if (ret == 0) + ftdi_usb_close_internal(ftdi); + + return ret; +} + +/** + Return device ID strings from the usb device. + + The parameters manufacturer, description and serial may be NULL + or pointer to buffers to store the fetched strings. + + \note The old function ftdi_usb_get_strings() always closes the device. + This version only closes the device if it was opened by it. + + \param ftdi pointer to ftdi_context + \param dev libusb usb_dev to use + \param manufacturer Store manufacturer string here if not NULL + \param mnf_len Buffer size of manufacturer string + \param description Store product description string here if not NULL + \param desc_len Buffer size of product description string + \param serial Store serial string here if not NULL + \param serial_len Buffer size of serial string + + \retval 0: all fine + \retval -1: wrong arguments + \retval -4: unable to open device + \retval -7: get product manufacturer failed + \retval -8: get product description failed + \retval -9: get serial number failed + \retval -11: libusb_get_device_descriptor() failed +*/ +int ftdi_usb_get_strings2(struct ftdi_context *ftdi, struct libusb_device *dev, + char *manufacturer, int mnf_len, + char *description, int desc_len, + char *serial, int serial_len) +{ + struct libusb_device_descriptor desc; + + if ((ftdi==NULL) || (dev==NULL)) + return -1; + + char need_open = (ftdi->usb_dev == NULL); + if (need_open && 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"); @@ -447,7 +507,8 @@ int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct libusb_device * dev, } } - ftdi_usb_close_internal (ftdi); + if (need_open) + ftdi_usb_close_internal (ftdi); return 0; } @@ -1470,9 +1531,15 @@ static void LIBUSB_CALL ftdi_read_data_cb(struct libusb_transfer *transfer) } } } - ret = libusb_submit_transfer (transfer); - if (ret < 0) - tc->completed = 1; + + if (transfer->status == LIBUSB_TRANSFER_CANCELLED) + tc->completed = LIBUSB_TRANSFER_CANCELLED; + else + { + ret = libusb_submit_transfer (transfer); + if (ret < 0) + tc->completed = 1; + } } @@ -1497,9 +1564,15 @@ static void LIBUSB_CALL ftdi_write_data_cb(struct libusb_transfer *transfer) transfer->length = write_size; transfer->buffer = tc->buf + tc->offset; - ret = libusb_submit_transfer (transfer); - if (ret < 0) - tc->completed = 1; + + if (transfer->status == LIBUSB_TRANSFER_CANCELLED) + tc->completed = LIBUSB_TRANSFER_CANCELLED; + else + { + ret = libusb_submit_transfer (transfer); + if (ret < 0) + tc->completed = 1; + } } } @@ -1662,17 +1735,19 @@ struct ftdi_transfer_control *ftdi_read_data_submit(struct ftdi_context *ftdi, u int ftdi_transfer_data_done(struct ftdi_transfer_control *tc) { int ret; - + struct timeval to = { 0, 0 }; while (!tc->completed) { - ret = libusb_handle_events(tc->ftdi->usb_ctx); + ret = libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx, + &to, &tc->completed); if (ret < 0) { if (ret == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(tc->transfer); while (!tc->completed) - if (libusb_handle_events(tc->ftdi->usb_ctx) < 0) + if (libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx, + &to, &tc->completed) < 0) break; libusb_free_transfer(tc->transfer); free (tc); @@ -1696,6 +1771,39 @@ int ftdi_transfer_data_done(struct ftdi_transfer_control *tc) } /** + Cancel transfer and wait for completion. + + Use libusb 1.0 asynchronous API. + + \param tc pointer to ftdi_transfer_control + \param to pointer to timeout value or NULL for infinite +*/ + +void ftdi_transfer_data_cancel(struct ftdi_transfer_control *tc, + struct timeval * to) +{ + struct timeval tv = { 0, 0 }; + + if (!tc->completed && tc->transfer != NULL) + { + if (to == NULL) + to = &tv; + + libusb_cancel_transfer(tc->transfer); + while (!tc->completed) + { + if (libusb_handle_events_timeout_completed(tc->ftdi->usb_ctx, to, &tc->completed) < 0) + break; + } + } + + if (tc->transfer) + libusb_free_transfer(tc->transfer); + + free (tc); +} + +/** Configure write buffer chunk size. Default is 4096. @@ -2538,6 +2646,15 @@ static unsigned char type2bit(unsigned char type, enum ftdi_chip_type chip) default: return 0; } } + case TYPE_R: + { + switch (type) + { + case CHANNEL_IS_UART : return 0; + case CHANNEL_IS_FIFO : return 0x01; + default: return 0; + } + } case TYPE_230X: /* FT230X is only UART */ default: return 0; } @@ -2830,6 +2947,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x14] = eeprom->chip; break; case TYPE_R: + output[0x00] = type2bit(eeprom->channel_a_type, TYPE_R); if (eeprom->high_current == HIGH_CURRENT_DRIVE_R) output[0x00] |= HIGH_CURRENT_DRIVE_R; if (eeprom->external_oscillator)