X-Git-Url: http://developer.intra2net.com/git/?a=blobdiff_plain;f=src%2Fftdi.c;h=8b589ebe761ad4aa162296eaae634ad63a4c7dcf;hb=f3f81007ff33dd6a856ea5f289187f10235635a0;hp=e0c9213b8b80a45832ccf3444bd3e2c4fbfc7fda;hpb=bf35baa04ec3e21b679ca10d90d2a65ec2a1270a;p=libftdi diff --git a/src/ftdi.c b/src/ftdi.c index e0c9213..8b589eb 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -50,6 +50,27 @@ return code; \ } while(0); +/** + Internal function to close usb device pointer. + Sets ftdi->usb_dev to NULL. + \internal + + \param ftdi pointer to ftdi_context + + \retval zero if all is fine, otherwise error code from usb_close() +*/ +static int ftdi_usb_close_internal (struct ftdi_context *ftdi) +{ + int ret = 0; + + if (ftdi->usb_dev) + { + ret = usb_close (ftdi->usb_dev); + ftdi->usb_dev = NULL; + } + + return ret; +} /** Initializes a ftdi_context. @@ -110,7 +131,7 @@ int ftdi_init(struct ftdi_context *ftdi) \return a pointer to a new ftdi_context, or NULL on failure */ -struct ftdi_context *ftdi_new() +struct ftdi_context *ftdi_new(void) { struct ftdi_context * ftdi = (struct ftdi_context *)malloc(sizeof(struct ftdi_context)); @@ -132,7 +153,7 @@ struct ftdi_context *ftdi_new() Open selected channels on a chip, otherwise use first channel. \param ftdi pointer to ftdi_context - \param interface Interface to use for FT2232C chips. + \param interface Interface to use for FT2232C/2232H/4232H chips. \retval 0: all fine \retval -1: unknown interface @@ -151,6 +172,18 @@ int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface) ftdi->in_ep = 0x04; ftdi->out_ep = 0x83; break; + case INTERFACE_C: + ftdi->interface = 2; + ftdi->index = INTERFACE_C; + ftdi->in_ep = 0x06; + ftdi->out_ep = 0x85; + break; + case INTERFACE_D: + ftdi->interface = 3; + ftdi->index = INTERFACE_D; + ftdi->in_ep = 0x08; + ftdi->out_ep = 0x87; + break; default: ftdi_error_return(-1, "Unknown interface"); } @@ -164,6 +197,8 @@ int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface) */ void ftdi_deinit(struct ftdi_context *ftdi) { + ftdi_usb_close_internal (ftdi); + if (ftdi->async_usb_buffer != NULL) { free(ftdi->async_usb_buffer); @@ -320,7 +355,7 @@ int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev, { if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iManufacturer, manufacturer, mnf_len) <= 0) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); ftdi_error_return(-7, usb_strerror()); } } @@ -329,7 +364,7 @@ int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev, { if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, description, desc_len) <= 0) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); ftdi_error_return(-8, usb_strerror()); } } @@ -338,12 +373,12 @@ int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev, { if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iSerialNumber, serial, serial_len) <= 0) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); ftdi_error_return(-9, usb_strerror()); } } - if (usb_close (ftdi->usb_dev) != 0) + if (ftdi_usb_close_internal (ftdi) != 0) ftdi_error_return(-10, usb_strerror()); return 0; @@ -387,7 +422,7 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) usb_set_configuration(ftdi->usb_dev, dev->config[0].bConfigurationValue) && errno != EBUSY) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); if (detach_errno == EPERM) { ftdi_error_return(-8, "inappropriate permissions on device!"); @@ -400,7 +435,7 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) if (usb_claim_interface(ftdi->usb_dev, ftdi->interface) != 0) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); if (detach_errno == EPERM) { ftdi_error_return(-8, "inappropriate permissions on device!"); @@ -413,13 +448,13 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) if (ftdi_usb_reset (ftdi) != 0) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); ftdi_error_return(-6, "ftdi_usb_reset failed"); } if (ftdi_set_baudrate (ftdi, 9600) != 0) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); ftdi_error_return(-7, "set baudrate failed"); } @@ -431,13 +466,26 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) else if (dev->descriptor.bcdDevice == 0x200) ftdi->type = TYPE_AM; else if (dev->descriptor.bcdDevice == 0x500) - { ftdi->type = TYPE_2232C; - if (!ftdi->index) - ftdi->index = INTERFACE_A; - } else if (dev->descriptor.bcdDevice == 0x600) ftdi->type = TYPE_R; + else if (dev->descriptor.bcdDevice == 0x700) + ftdi->type = TYPE_2232H; + else if (dev->descriptor.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; + } ftdi_error_return(0, "all fine"); } @@ -506,12 +554,12 @@ int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, { if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, string, sizeof(string)) <= 0) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); ftdi_error_return(-8, "unable to fetch product description"); } if (strncmp(string, description, sizeof(string)) != 0) { - if (usb_close (ftdi->usb_dev) != 0) + if (ftdi_usb_close_internal (ftdi) != 0) ftdi_error_return(-10, "unable to close device"); continue; } @@ -520,18 +568,18 @@ int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product, { if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iSerialNumber, string, sizeof(string)) <= 0) { - usb_close (ftdi->usb_dev); + ftdi_usb_close_internal (ftdi); ftdi_error_return(-9, "unable to fetch serial number"); } if (strncmp(string, serial, sizeof(string)) != 0) { - if (usb_close (ftdi->usb_dev) != 0) + if (ftdi_usb_close_internal (ftdi) != 0) ftdi_error_return(-10, "unable to close device"); continue; } } - if (usb_close (ftdi->usb_dev) != 0) + if (ftdi_usb_close_internal (ftdi) != 0) ftdi_error_return(-10, "unable to close device"); return ftdi_usb_open_dev(ftdi, dev); @@ -629,6 +677,8 @@ int ftdi_usb_purge_buffers(struct ftdi_context *ftdi) return 0; } + + /** Closes the ftdi device. Call ftdi_deinit() if you're cleaning up. @@ -647,10 +697,11 @@ int ftdi_usb_close(struct ftdi_context *ftdi) ftdi_async_complete(ftdi,1); #endif - if (usb_release_interface(ftdi->usb_dev, ftdi->interface) != 0) - rtn = -1; + if (ftdi->usb_dev != NULL) + if (usb_release_interface(ftdi->usb_dev, ftdi->interface) != 0) + rtn = -1; - if (usb_close (ftdi->usb_dev) != 0) + if (ftdi_usb_close_internal (ftdi) != 0) rtn = -2; return rtn; @@ -1202,6 +1253,13 @@ int ftdi_write_data_get_chunksize(struct ftdi_context *ftdi, unsigned int *chunk int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) { int offset = 0, ret = 1, i, num_of_chunks, chunk_remains; + int packet_size; + + // New hi-speed devices from FTDI use a packet size of 512 bytes + if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H) + packet_size = 512; + else + packet_size = 64; // everything we want is still in the readbuffer? if (size <= ftdi->readbuffer_remaining) @@ -1238,23 +1296,23 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) { // skip FTDI status bytes. // Maybe stored in the future to enable modem use - num_of_chunks = ret / 64; - chunk_remains = ret % 64; + num_of_chunks = ret / packet_size; + chunk_remains = ret % packet_size; //printf("ret = %X, num_of_chunks = %X, chunk_remains = %X, readbuffer_offset = %X\n", ret, num_of_chunks, chunk_remains, ftdi->readbuffer_offset); ftdi->readbuffer_offset += 2; ret -= 2; - if (ret > 62) + if (ret > packet_size - 2) { for (i = 1; i < num_of_chunks; i++) - memmove (ftdi->readbuffer+ftdi->readbuffer_offset+62*i, - ftdi->readbuffer+ftdi->readbuffer_offset+64*i, - 62); + memmove (ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size - 2)*i, + ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*i, + packet_size - 2); if (chunk_remains > 2) { - memmove (ftdi->readbuffer+ftdi->readbuffer_offset+62*i, - ftdi->readbuffer+ftdi->readbuffer_offset+64*i, + memmove (ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size - 2)*i, + ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*i, chunk_remains-2); ret -= 2*num_of_chunks; } @@ -1909,7 +1967,7 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) Decode binary EEPROM image into an ftdi_eeprom structure. \param eeprom Pointer to ftdi_eeprom which will be filled in. - \param output Buffer of \a size bytes of raw eeprom data + \param buf Buffer of \a size bytes of raw eeprom data \param size size size of eeprom data in bytes \retval 0: all fine @@ -1954,7 +2012,8 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) // Addr 04: Product ID eeprom->product_id = buf[0x04] + (buf[0x05] << 8); - switch (buf[0x06] + (buf[0x07]<<8)) + value = buf[0x06] + (buf[0x07]<<8); + switch (value) { case 0x0400: eeprom->BM_type_chip = 1; @@ -2183,12 +2242,15 @@ int ftdi_read_eeprom_getsize(struct ftdi_context *ftdi, unsigned char *eeprom, i int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) { unsigned short usb_val, status; - int i; + int i, ret; /* These commands were traced while running MProg */ - ftdi_usb_reset(ftdi); - ftdi_poll_modem_status(ftdi, &status); - ftdi_set_latency_timer(ftdi, 0x77); + if ((ret = ftdi_usb_reset(ftdi)) != 0) + return ret; + if ((ret = ftdi_poll_modem_status(ftdi, &status)) != 0) + return ret; + if ((ret = ftdi_set_latency_timer(ftdi, 0x77)) != 0) + return ret; for (i = 0; i < ftdi->eeprom_size/2; i++) {