libftdi Archives

Subject: [PATCH] Fixed first device failure in open_desc function

From: Harrison Marcks <hmarcks@xxxxxxxxxxxxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Cc: amurray@xxxxxxxxxxxxxxxxxxxx, Harrison Marcks <hmarcks@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 7 Jul 2022 12:53:34 +0100
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   

Current Thread