libftdi: (gerd) tolerate EBUSY when setting configuration (EBUSY will be returned...
[libftdi] / src / ftdi.c
index b17e898..e269021 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
@@ -359,6 +360,21 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev)
         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 +461,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) {
@@ -557,11 +573,11 @@ int ftdi_usb_purge_buffers(struct ftdi_context *ftdi)
     int result;
 
     result = ftdi_usb_purge_rx_buffer(ftdi);
-    if (!result)
+    if (result < 0)
         return -1;
 
     result = ftdi_usb_purge_tx_buffer(ftdi);
-    if (!result)
+    if (result < 0)
         return -2;
 
     return 0;
@@ -1532,19 +1548,19 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output)
         output[0x07] = 0x02;
 
     // Addr 08: Config descriptor
-    // Bit 1: remote wakeup if 1
-    // Bit 0: self powered if 1
-    //
-    j = 0;
+    // 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 = j | 1;
+        j |= 0x40;
     if (eeprom->remote_wakeup == 1)
-        j = j | 2;
+        j |= 0x20;
     output[0x08] = j;
 
     // Addr 09: Max power consumption: max power = value * 2 mA
     output[0x09] = eeprom->max_power;
-    ;
 
     // Addr 0A: Chip configuration
     // Bit 7: 0 - reserved