From e2f12a4fb7a27243c9c8fef2755b9ace5751fe5e Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Sun, 15 Nov 2009 12:45:03 +0100 Subject: [PATCH] Determine maximum packet size via usb config descriptor --- src/ftdi.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++------ src/ftdi.h | 2 ++ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/ftdi.c b/src/ftdi.c index d7f4bb0..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 @@ -491,6 +531,9 @@ 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); @@ -1266,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) diff --git a/src/ftdi.h b/src/ftdi.h index 0c4620b..9c19734 100644 --- a/src/ftdi.h +++ b/src/ftdi.h @@ -180,6 +180,8 @@ struct ftdi_context unsigned int readbuffer_chunksize; /** write buffer chunk size */ unsigned int writebuffer_chunksize; + /** maximum packet size. Needed for filtering modem status bytes every n packets. */ + unsigned int max_packet_size; /* FTDI FT2232C requirecments */ /** FT2232C interface number: 0 or 1 */ -- 1.7.1