Increase version
[libftdi] / src / ftdi.c
index b5cb4f3..74b5631 100644 (file)
@@ -223,7 +223,7 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli
 
     curdev = devlist;
     *curdev = NULL;
-    for (bus = usb_busses; bus; bus = bus->next) {
+    for (bus = usb_get_busses(); bus; bus = bus->next) {
         for (dev = bus->devices; dev; dev = dev->next) {
             if (dev->descriptor.idVendor == vendor
                     && dev->descriptor.idProduct == product)
@@ -341,6 +341,7 @@ int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev,
     \param dev libusb usb_dev to use
 
     \retval  0: all fine
+    \retval -3: unable to config device
     \retval -4: unable to open device
     \retval -5: unable to claim device
     \retval -6: reset failed
@@ -353,12 +354,32 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev)
         ftdi_error_return(-4, "usb_open() failed");
 
 #ifdef LIBUSB_HAS_GET_DRIVER_NP
-    // Try to detach ftdi_sio kernel module
-    // Returns ENODATA if driver is not loaded
+    // Try to detach ftdi_sio kernel module.
+    // Returns ENODATA if driver is not loaded.
+    //
+    // The return code is kept in a separate variable and only parsed
+    // if usb_set_configuration() or usb_claim_interface() fails as the
+    // detach operation might be denied and everything still works fine.
+    // Likely scenario is a static ftdi_sio kernel module.
     if (usb_detach_kernel_driver_np(ftdi->usb_dev, ftdi->interface) != 0 && errno != ENODATA)
         detach_errno = errno;
 #endif
 
+    // set configuration (needed especially for windows)
+    // tolerate EBUSY: one device with one configuration, but two interfaces
+    //    and libftdi sessions to both interfaces (e.g. FT2232)
+    if (dev->descriptor.bNumConfigurations > 0 && 
+        usb_set_configuration(ftdi->usb_dev, dev->config[0].bConfigurationValue) &&
+        errno != EBUSY)
+    {
+        usb_close (ftdi->usb_dev);
+        if (detach_errno == EPERM) {
+            ftdi_error_return(-8, "inappropriate permissions on device!");
+        } else {
+            ftdi_error_return(-3, "unable to set usb configuration. Make sure ftdi_sio is unloaded!");
+        }
+    }
+
     if (usb_claim_interface(ftdi->usb_dev, ftdi->interface) != 0) {
         usb_close (ftdi->usb_dev);
         if (detach_errno == EPERM) {
@@ -445,7 +466,7 @@ int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product,
     if (usb_find_devices() < 0)
         ftdi_error_return(-2, "usb_find_devices() failed");
 
-    for (bus = usb_busses; bus; bus = bus->next) {
+    for (bus = usb_get_busses(); bus; bus = bus->next) {
         for (dev = bus->devices; dev; dev = dev->next) {
             if (dev->descriptor.idVendor == vendor
                     && dev->descriptor.idProduct == product) {
@@ -1532,10 +1553,10 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output)
         output[0x07] = 0x02;
 
     // Addr 08: Config descriptor
-    // Bit 7: always 1
-    // Bit 6: 1 if this device is self powered, 0 if bus powered
-    // Bit 5: 1 if this device uses remote wakeup
-    // Bit 4: 1 if this device is battery powered
+    // Bit 7: always 1
+    // Bit 6: 1 if this device is self powered, 0 if bus powered
+    // Bit 5: 1 if this device uses remote wakeup
+    // Bit 4: 1 if this device is battery powered
     j = 0x80;
     if (eeprom->self_powered == 1)
         j |= 0x40;