X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=573080a92f80ef5ae218312b6f3c9a291add8d03;hp=68489ea096be6f1e4dd4224104d9210fa9a88d69;hb=f838a4e3b0466abc34823750e9eef24d785c8232;hpb=1162549f619aad91ba30008b64827b3716d15b76 diff --git a/src/ftdi.c b/src/ftdi.c index 68489ea..573080a 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -1470,9 +1470,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 +1503,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 +1674,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 +1710,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. @@ -2563,7 +2610,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; @@ -2598,14 +2645,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: - user_area_size = 96; - break; case TYPE_230X: user_area_size = 88; // four extra config bytes + 4 bytes PnP stuff break; @@ -2712,6 +2757,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 @@ -2779,7 +2825,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; @@ -2821,7 +2867,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; @@ -2833,6 +2879,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) @@ -3072,6 +3120,38 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) 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; @@ -3203,8 +3283,8 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom->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 @@ -3318,6 +3398,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." @@ -3431,8 +3512,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) @@ -3465,7 +3548,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) (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)) @@ -3752,6 +3835,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"); } @@ -3942,6 +4028,12 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu 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"); @@ -3984,7 +4076,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) { @@ -4000,6 +4092,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