C++ API: Add support to open devices with missing product / serial strings
authorMatthias Janke <janke@physi.uni-heidelberg.de>
Thu, 13 Jul 2017 16:10:44 +0000 (18:10 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Thu, 20 Jul 2017 15:51:24 +0000 (17:51 +0200)
The C++ API and C API differ in how they open a device. The C API only
considers the user supplied strings iVendor, iProduct and iSerial to open a device.

The C++ API behaves differently. After opening the device with specific supplied strings,
it tries to read all strings via get_strings_and_reopen().
This fails if one string like iSerial is not defined
in the descriptor. As such the whole open() operation fails
and the C++ API would only open devices with complete descriptors.

This commit fixes this behaviour, by extending the get_strings_and_reopen()
and get_strings() argument lists, to configure the strings to read.

ftdipp/ftdi.cpp
ftdipp/ftdi.hpp

index 3d59d9d..aca686a 100644 (file)
@@ -87,7 +87,7 @@ int Context::open(int vendor, int product)
     if (ret < 0)
        return ret;
 
-    return get_strings_and_reopen();
+    return get_strings_and_reopen(false,false,false);
 }
 
 int Context::open(int vendor, int product, const std::string& description, const std::string& serial, unsigned int index)
@@ -106,7 +106,7 @@ int Context::open(int vendor, int product, const std::string& description, const
     if (ret < 0)
        return ret;
 
-    return get_strings_and_reopen();
+    return get_strings_and_reopen(false,description.empty(),serial.empty());
 }
 
 int Context::open(const std::string& description)
@@ -116,7 +116,7 @@ int Context::open(const std::string& description)
     if (ret < 0)
        return ret;
 
-    return get_strings_and_reopen();
+    return get_strings_and_reopen(false,true,false);
 }
 
 int Context::open(struct libusb_device *dev)
@@ -319,41 +319,46 @@ const char* Context::error_string()
     return ftdi_get_error_string(d->ftdi);
 }
 
-int Context::get_strings()
+int Context::get_strings(bool vendor, bool description, bool serial)
 {
     // Prepare buffers
-    char vendor[512], desc[512], serial[512];
+    char ivendor[512], idesc[512], iserial[512];
 
-    int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor, 512, desc, 512, serial, 512);
+    int ret = ftdi_usb_get_strings(d->ftdi, d->dev, vendor?ivendor:NULL, 512, description?idesc:NULL, 512, serial?iserial:NULL, 512);
 
     if (ret < 0)
         return -1;
 
-    d->vendor = vendor;
-    d->description = desc;
-    d->serial = serial;
+    d->vendor = ivendor;
+    d->description = idesc;
+    d->serial = iserial;
 
     return 1;
 }
 
-int Context::get_strings_and_reopen()
+int Context::get_strings_and_reopen(bool vendor, bool description, bool serial)
 {
-    if ( d->dev == 0 )
-    {
-        d->dev = libusb_get_device(d->ftdi->usb_dev);
-    }
+    int ret = 0;
 
-    // Get device strings (closes device)
-    int ret=get_strings();
-    if (ret < 0)
+    if(vendor || description || serial)
     {
-        d->open = 0;
-        return ret;
-    }
+        if (d->dev == 0)
+        {
+            d->dev = libusb_get_device(d->ftdi->usb_dev);
+        }
+
+        // Get device strings (closes device)
+        ret=get_strings(vendor, description, serial);
+        if (ret < 0)
+        {
+            d->open = 0;
+            return ret;
+        }
 
-    // Reattach device
-    ret = ftdi_usb_open_dev(d->ftdi, d->dev);
-    d->open = (ret >= 0);
+        // Reattach device
+        ret = ftdi_usb_open_dev(d->ftdi, d->dev);
+        d->open = (ret >= 0);
+    }
 
     return ret;
 }
@@ -362,6 +367,8 @@ int Context::get_strings_and_reopen()
  */
 const std::string& Context::vendor()
 {
+    if(d->vendor.empty())
+        get_strings_and_reopen(true,false,false);
     return d->vendor;
 }
 
@@ -369,6 +376,8 @@ const std::string& Context::vendor()
  */
 const std::string& Context::description()
 {
+    if(d->description.empty())
+        get_strings_and_reopen(false,true,false);
     return d->description;
 }
 
@@ -376,6 +385,8 @@ const std::string& Context::description()
  */
 const std::string& Context::serial()
 {
+    if(d->serial.empty())
+        get_strings_and_reopen(false,false,true);
     return d->serial;
 }
 
index 6a7f893..dc035cc 100644 (file)
@@ -134,8 +134,8 @@ public:
     const char* error_string();
 
 protected:
-    int get_strings();
-    int get_strings_and_reopen();
+    int get_strings(bool vendor=true, bool description=true, bool serial=true);
+    int get_strings_and_reopen(bool vendor=true, bool description=true, bool serial=true);
 
     /* Properties */
     struct ftdi_context* context();