X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=a87d6537a1f700162360c78d631bb3ee50121270;hp=5fce9a6c06260248acc0df221088d770f34c7dc5;hb=0c93de8177ee7310292ac7eab4c2e3ff993b4f2f;hpb=e59bc450ba1b263f549185e16a00c7ab57b6c247 diff --git a/src/ftdi.c b/src/ftdi.c index 5fce9a6..a87d653 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -98,6 +98,7 @@ int ftdi_init(struct ftdi_context *ftdi) ftdi->readbuffer_offset = 0; ftdi->readbuffer_remaining = 0; ftdi->writebuffer_chunksize = 4096; + ftdi->max_packet_size = 0; ftdi->interface = 0; ftdi->index = 0; @@ -385,6 +386,45 @@ int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev, } /** + * Internal function to determine the maximum packet size. + * \param ftdi pointer to ftdi_context + * \param dev libusb usb_dev to use + * \retval Maximum packet size for this device + */ +static unsigned int _ftdi_determine_max_packet_size(struct ftdi_context *ftdi, struct usb_device *dev) +{ + unsigned int packet_size; + + // 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) + packet_size = 512; + else + packet_size = 64; + + if (dev->descriptor.bNumConfigurations > 0 && dev->config) + { + struct usb_config_descriptor config = dev->config[0]; + + if (ftdi->interface < config.bNumInterfaces) + { + struct usb_interface interface = config.interface[ftdi->interface]; + if (interface.num_altsetting > 0) + { + struct usb_interface_descriptor descriptor = interface.altsetting[0]; + if (descriptor.bNumEndpoints > 0) + { + packet_size = descriptor.endpoint[0].wMaxPacketSize; + } + } + } + } + + return packet_size; +} + +/** Opens a ftdi device given by a usb_device. \param ftdi pointer to ftdi_context @@ -400,6 +440,7 @@ int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev, int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) { int detach_errno = 0; + int config_val = 1; if (!(ftdi->usb_dev = usb_open(dev))) ftdi_error_return(-4, "usb_open() failed"); @@ -415,23 +456,32 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) detach_errno = errno; #endif +#ifdef __WIN32__ // set configuration (needed especially for windows) // tolerate EBUSY: one device with one configuration, but two interfaces // and libftdi sessions to both interfaces (e.g. FT2232) - if (dev->descriptor.bNumConfigurations > 0 && - usb_set_configuration(ftdi->usb_dev, dev->config[0].bConfigurationValue) && - errno != EBUSY) + + if (dev->descriptor.bNumConfigurations > 0) { - ftdi_usb_close_internal (ftdi); - if (detach_errno == EPERM) - { - ftdi_error_return(-8, "inappropriate permissions on device!"); - } - else + // libusb-win32 on Windows 64 can return a null pointer for a valid device + if (dev->config) + config_val = dev->config[0].bConfigurationValue; + + if (usb_set_configuration(ftdi->usb_dev, config_val) && + errno != EBUSY) { - ftdi_error_return(-3, "unable to set usb configuration. Make sure ftdi_sio is unloaded!"); + ftdi_usb_close_internal (ftdi); + if (detach_errno == EPERM) + { + ftdi_error_return(-8, "inappropriate permissions on device!"); + } + else + { + ftdi_error_return(-3, "unable to set usb configuration. Make sure ftdi_sio is unloaded!"); + } } } +#endif if (usb_claim_interface(ftdi->usb_dev, ftdi->interface) != 0) { @@ -452,12 +502,6 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) ftdi_error_return(-6, "ftdi_usb_reset failed"); } - if (ftdi_set_baudrate (ftdi, 9600) != 0) - { - ftdi_usb_close_internal (ftdi); - ftdi_error_return(-7, "set baudrate failed"); - } - // Try to guess chip type // Bug in the BM type chips: bcdDevice is 0x200 for serial == 0 if (dev->descriptor.bcdDevice == 0x400 || (dev->descriptor.bcdDevice == 0x200 @@ -487,6 +531,15 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev) break; } + // Determine maximum packet size + ftdi->max_packet_size = _ftdi_determine_max_packet_size(ftdi, dev); + + if (ftdi_set_baudrate (ftdi, 9600) != 0) + { + ftdi_usb_close_internal (ftdi); + ftdi_error_return(-7, "set baudrate failed"); + } + ftdi_error_return(0, "all fine"); } @@ -820,7 +873,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_2232C) + if (ftdi->type == TYPE_2232C || ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H) { *index = (unsigned short)(encoded_divisor >> 8); *index &= 0xFF00; @@ -1256,13 +1309,11 @@ 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; + int packet_size = ftdi->max_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; + // Packet size sanity check (avoid division by zero) + if (packet_size == 0) + ftdi_error_return(-1, "max_packet_size is bogus (zero)"); // everything we want is still in the readbuffer? if (size <= ftdi->readbuffer_remaining)