Hi,

This patch fixes misleading errors being sent to the application from
libftdi.

Background: usb_open() will silently succeed when the device node can
only be opened read-only and not read-write.  When this occurs,
various subsequent ioctls to that node will fail, and are presented to
the application as failures of those specific operations, even though
the root cause is a permissions error.

Using usb_claim_interface after every usb_open() would reveal a
permissions problem earlier, but it is desirable in this case to scan
properties of USB devices to find FTDI chips without necessarily
attempting to claim every device for exclusive access.

The patch ensures that when libftdi performs a libusb operation on an
opened but not claimed USB device, a failure due to a permissions
error will be propagated to the application as a permissions error and
not a different, red-herring error.

-- 
Ryan C. Underwood, <[email protected]>
--- libftdi-0.20/src/ftdi.c	2012-11-16 10:32:50.000000000 -0600
+++ ftdi.eperm.c	2012-11-16 10:30:12.303281040 -0600
@@ -358,6 +358,8 @@
 int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev,
                          char * manufacturer, int mnf_len, char * description, int desc_len, char * serial, int serial_len)
 {
+    int err;
+
     if ((ftdi==NULL) || (dev==NULL))
         return -1;
 
@@ -366,27 +368,33 @@
 
     if (manufacturer != NULL)
     {
-        if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iManufacturer, manufacturer, mnf_len) <= 0)
+        if ((err = usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iManufacturer, manufacturer, mnf_len)) <= 0)
         {
             ftdi_usb_close_internal (ftdi);
+            if (err == -EPERM)
+              ftdi_error_return(-4, usb_strerror());
             ftdi_error_return(-7, usb_strerror());
         }
     }
 
     if (description != NULL)
     {
-        if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, description, desc_len) <= 0)
+        if ((err = usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, description, desc_len)) <= 0)
         {
             ftdi_usb_close_internal (ftdi);
+            if (err == -EPERM)
+              ftdi_error_return(-4, usb_strerror());
             ftdi_error_return(-8, usb_strerror());
         }
     }
 
     if (serial != NULL)
     {
-        if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iSerialNumber, serial, serial_len) <= 0)
+        if ((err = usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iSerialNumber, serial, serial_len)) <= 0)
         {
             ftdi_usb_close_internal (ftdi);
+            if (err == -EPERM)
+              ftdi_error_return(-4, usb_strerror());
             ftdi_error_return(-9, usb_strerror());
         }
     }
@@ -641,6 +649,7 @@
     struct usb_bus *bus;
     struct usb_device *dev;
     char string[256];
+    int err;
 
     usb_init();
 
@@ -664,9 +673,11 @@
 
                 if (description != NULL)
                 {
-                    if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, string, sizeof(string)) <= 0)
+                    if ((err = usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, string, sizeof(string))) <= 0)
                     {
                         ftdi_usb_close_internal (ftdi);
+                        if (err == -EPERM)
+                          ftdi_error_return(-4, "unable to fetch product description");
                         ftdi_error_return(-8, "unable to fetch product description");
                     }
                     if (strncmp(string, description, sizeof(string)) != 0)
@@ -678,9 +689,11 @@
                 }
                 if (serial != NULL)
                 {
-                    if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iSerialNumber, string, sizeof(string)) <= 0)
+                    if ((err = usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iSerialNumber, string, sizeof(string))) <= 0)
                     {
                         ftdi_usb_close_internal (ftdi);
+                        if (err == -EPERM)
+                          ftdi_error_return(-4, "unable to fetch serial number");
                         ftdi_error_return(-9, "unable to fetch serial number");
                     }
                     if (strncmp(string, serial, sizeof(string)) != 0)

Attachment: signature.asc
Description: Digital signature

Reply via email to