The ftdi_usb_open_desc_index function would fail immediately in the case of a
first failed device which is undesireable if several devices are present
that share ids but might not be accessible. This specific edge case fixes an
issue
in containers that sees devices not passed through but still being seen by
libusb
failing when they can't be accessed in the container by moving onto the next
device
until a device is found it can open and check correctly.
---
src/ftdi.c | 46 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 37 insertions(+), 9 deletions(-)
diff --git a/src/ftdi.c b/src/ftdi.c
index 0a7fb27..7ab6c55 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -763,7 +763,7 @@ int ftdi_usb_open_desc(struct ftdi_context *ftdi, int
vendor, int product,
\retval -1: usb_find_busses() failed
\retval -2: usb_find_devices() failed
\retval -3: usb device not found
- \retval -4: unable to open device
+ \retval -4: unable to open device. We made at least one match and it
failed to open.
\retval -5: unable to claim device
\retval -6: reset failed
\retval -7: set baudrate failed
@@ -780,6 +780,8 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int
vendor, int product,
libusb_device **devs;
char string[256];
int i = 0;
+ int error_code = -3;
+ int open_counter = 0, open_fail_counter = 0;
if (ftdi == NULL)
ftdi_error_return(-11, "ftdi context invalid");
@@ -797,8 +799,13 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi,
int vendor, int product,
if (desc.idVendor == vendor && desc.idProduct == product)
{
+ open_counter++;
if (libusb_open(dev, &ftdi->usb_dev) < 0)
- ftdi_error_return_free_device_list(-4, "usb_open() failed",
devs);
+ {
+ open_fail_counter++;
+ error_code = -4;
+ continue;
+ }
if (description != NULL)
{
@@ -810,9 +817,11 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi,
int vendor, int product,
if (strncmp(string, description, sizeof(string)) != 0)
{
ftdi_usb_close_internal (ftdi);
+ error_code = -3;
continue;
}
}
+
if (serial != NULL)
{
if (libusb_get_string_descriptor_ascii(ftdi->usb_dev,
desc.iSerialNumber, (unsigned char *)string, sizeof(string)) < 0)
@@ -820,15 +829,16 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi,
int vendor, int product,
ftdi_usb_close_internal (ftdi);
ftdi_error_return_free_device_list(-9, "unable to fetch
serial number", devs);
}
+
if (strncmp(string, serial, sizeof(string)) != 0)
{
ftdi_usb_close_internal (ftdi);
+ error_code = -3;
continue;
}
}
ftdi_usb_close_internal (ftdi);
-
if (index > 0)
{
index--;
@@ -836,13 +846,28 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi,
int vendor, int product,
}
res = ftdi_usb_open_dev(ftdi, dev);
- libusb_free_device_list(devs,1);
+ libusb_free_device_list(devs, 1);
return res;
}
}
- // device not found
- ftdi_error_return_free_device_list(-3, "device not found", devs);
+ switch(error_code)
+ {
+ case -3:
+ // device not found
+ ftdi_error_return_free_device_list(-3, "device not found", devs);
+ break;
+ case -4:
+ {
+ // Failure to open any devices. We made at least one match and it
failed to open.
+ char buf [256];
+ sprintf(buf, "usb_open() ran %d times and failed %d times.",
open_counter, open_fail_counter);
+ ftdi_error_return_free_device_list(-4, buf, devs);
+ }
+ break;
+ }
+
+ return -3;
}
/**
@@ -4491,10 +4516,13 @@ int ftdi_read_eeprom(struct ftdi_context *ftdi)
for (i = 0; i < FTDI_MAX_EEPROM_SIZE/2; i++)
{
- if (libusb_control_transfer(
+ int ret = libusb_control_transfer(
ftdi->usb_dev,
FTDI_DEVICE_IN_REQTYPE,SIO_READ_EEPROM_REQUEST, 0, i,
- buf+(i*2), 2, ftdi->usb_read_timeout) != 2)
- ftdi_error_return(-1, "reading eeprom failed");
+ buf+(i*2), 2, ftdi->usb_read_timeout);
+ // fprintf(stderr, "eeprom check: %d\n", ret);
+ if ( ret != 2 || ret == 0)
+ fprintf(stderr, "reading eeprom faield (-1)");
+ // ftdi_error_return(-1, "reading eeprom failed");
}
if (ftdi->type == TYPE_R)
--
2.34.1
--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx
|