libftdi Archives

Subject: Re: Use libusb 1.0

From: Jie Zhang <jie.zhang@xxxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Date: Tue, 11 Aug 2009 18:02:41 +0800
Thomas Jarosch wrote:
Hello Jie,

On Sunday, 9. August 2009 16:44:54 Jie Zhang wrote:
I have almost done the coding. Before sending out the patch, I need to
know what's the best way to deal with libusb 0.1.

Should we still keep support for libusb 0.1 because libusb 1.0 is not
supported on Windows?

Thanks for your coding effort, it's highly appreciated!
We should try to keep libusb 0.1 support.

If so, which is the best way to do it?

1. Add a lot of #if...#else...#endif in source code. There will be too
many such cases. The code will look very ugly.

Yes, too ugly :-)

2. Use new files for libusb 1.0, such as ftdi.c for libusb 0.1 and
ftdi-new.c for libusb 1.0. We can use some #if...#else...#endif in
ftdi.h. There would be much code duplications between these two files.

3. Use a branch for libusb 0.1. This way the code will be kept clean. I
prefer this way. We can roll out a last release which support libusb 0.1
API and in future we will not support libusb 0.1 in new releases. If
people want to use libftdi with libusb 0.1, they can use that release.

Would it be possible to move the libusb interface into an abstraction layer?
Most libftdi functions are using usb_control_msg(),
so only a few functions need "specialization".

Not yet. The API changes a lot between libusb 0.1 and 1.0. I attached the patch I currently have.

The asynchronous API is changed completely with this patch. It fits better for our needs in UrJTAG, but I don't know intra2net will like it or not. Only async read is tested here. An example of async read looks like


  struct ftdi_transfer_control *tc;
  tc = ftdi_read_data_submit(...);
  ...
  recvd = ftdi_transfer_data_done (tc);


The configure script part is copied from SANE. It needs more tweaks after we decide how to deal with libusb 0.1.

To use libusb-1.0, just add --enable-libusb_1_0 when configure.

Some changes in this patch is not related to libusb 1.0. They are here just for fixing some compilation warnings with -Wall option.


Jie



--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx   
Index: ftdipp/ftdi.cpp
===================================================================
--- ftdipp/ftdi.cpp     (revision 3519)
+++ ftdipp/ftdi.cpp     (working copy)
@@ -52,7 +52,7 @@ public:
     bool open;
 
     struct ftdi_context* ftdi;
-    struct usb_device*   dev;
+    struct libusb_device* dev;
 
     std::string vendor;
     std::string description;
@@ -100,7 +100,7 @@ int Context::open(int vendor, int produc
     return ret;
 }
 
-int Context::open(struct usb_device *dev)
+int Context::open(struct libusb_device *dev)
 {
     if (dev != 0)
         d->dev = dev;
@@ -146,10 +146,10 @@ int Context::set_interface(enum ftdi_int
     return ftdi_set_interface(d->ftdi, interface);
 }
 
-void Context::set_usb_device(struct usb_dev_handle *dev)
+void Context::set_usb_device(struct libusb_device_handle *dev)
 {
     ftdi_set_usbdev(d->ftdi, dev);
-    d->dev = usb_device(dev);
+    d->dev = libusb_get_device(dev);
 }
 
 int Context::set_baud_rate(int baudrate)
@@ -329,7 +329,7 @@ void Context::set_context(struct ftdi_co
     d->ftdi = context;
 }
 
-void Context::set_usb_device(struct usb_device *dev)
+void Context::set_usb_device(struct libusb_device *dev)
 {
     d->dev = dev;
 }
Index: ftdipp/ftdi.hpp
===================================================================
--- ftdipp/ftdi.hpp     (revision 3519)
+++ ftdipp/ftdi.hpp     (working copy)
@@ -79,13 +79,13 @@ public:
 
     /* Device manipulators */
     bool is_open();
-    int open(struct usb_device *dev = 0);
+    int open(struct libusb_device *dev = 0);
     int open(int vendor, int product, const std::string& description = 
std::string(), const std::string& serial = std::string());
     int close();
     int reset();
     int flush(int mask = Input|Output);
     int set_interface(enum ftdi_interface interface);
-    void set_usb_device(struct usb_dev_handle *dev);
+    void set_usb_device(struct libusb_device_handle *dev);
 
     /* Line manipulators */
     int set_baud_rate(int baudrate);
@@ -133,7 +133,7 @@ protected:
     /* Properties */
     struct ftdi_context* context();
     void set_context(struct ftdi_context* context);
-    void set_usb_device(struct usb_device *dev);
+    void set_usb_device(struct libusb_device *dev);
 
 private:
     class Private;
Index: src/ftdi.c
===================================================================
--- src/ftdi.c  (revision 3519)
+++ src/ftdi.c  (working copy)
@@ -28,23 +28,14 @@
 /** \addtogroup libftdi */
 /* @{ */
 
-#include <usb.h>
+#include <libusb.h>
 #include <string.h>
 #include <errno.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "ftdi.h"
 
-/* stuff needed for async write */
-#ifdef LIBFTDI_LINUX_ASYNC_MODE
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <linux/usbdevice_fs.h>
-#endif
-
 #define ftdi_error_return(code, str) do {  \
         ftdi->error_str = str;             \
         return code;                       \
@@ -63,8 +54,6 @@
 */
 int ftdi_init(struct ftdi_context *ftdi)
 {
-    unsigned int i;
-
     ftdi->usb_dev = NULL;
     ftdi->usb_read_timeout = 5000;
     ftdi->usb_write_timeout = 5000;
@@ -86,19 +75,6 @@ int ftdi_init(struct ftdi_context *ftdi)
 
     ftdi->error_str = NULL;
 
-#ifdef LIBFTDI_LINUX_ASYNC_MODE
-    ftdi->async_usb_buffer_size=10;
-    if ((ftdi->async_usb_buffer=malloc(sizeof(struct 
usbdevfs_urb)*ftdi->async_usb_buffer_size)) == NULL)
-        ftdi_error_return(-1, "out of memory for async usb buffer");
-
-    /* initialize async usb buffer with unused-marker */
-    for (i=0; i < ftdi->async_usb_buffer_size; i++)
-        ((struct usbdevfs_urb*)ftdi->async_usb_buffer)[i].usercontext = 
FTDI_URB_USERCONTEXT_COOKIE;
-#else
-    ftdi->async_usb_buffer_size=0;
-    ftdi->async_usb_buffer = NULL;
-#endif
-
     ftdi->eeprom_size = FTDI_DEFAULT_EEPROM_SIZE;
 
     /* All fine. Now allocate the readbuffer */
@@ -176,12 +152,6 @@ int ftdi_set_interface(struct ftdi_conte
 */
 void ftdi_deinit(struct ftdi_context *ftdi)
 {
-    if (ftdi->async_usb_buffer != NULL)
-    {
-        free(ftdi->async_usb_buffer);
-        ftdi->async_usb_buffer = NULL;
-    }
-
     if (ftdi->readbuffer != NULL)
     {
         free(ftdi->readbuffer);
@@ -204,9 +174,9 @@ void ftdi_free(struct ftdi_context *ftdi
     Use an already open libusb device.
 
     \param ftdi pointer to ftdi_context
-    \param usb libusb usb_dev_handle to use
+    \param usb libusb libusb_device_handle to use
 */
-void ftdi_set_usbdev (struct ftdi_context *ftdi, usb_dev_handle *usb)
+void ftdi_set_usbdev (struct ftdi_context *ftdi, libusb_device_handle *usb)
 {
     ftdi->usb_dev = usb;
 }
@@ -222,42 +192,46 @@ void ftdi_set_usbdev (struct ftdi_contex
     \param product Product ID to search for
 
     \retval >0: number of devices found
-    \retval -1: usb_find_busses() failed
-    \retval -2: usb_find_devices() failed
     \retval -3: out of memory
+    \retval -4: libusb_init() failed
+    \retval -5: libusb_get_device_list() failed
+    \retval -6: libusb_get_device_descriptor() failed
 */
 int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list 
**devlist, int vendor, int product)
 {
     struct ftdi_device_list **curdev;
-    struct usb_bus *bus;
-    struct usb_device *dev;
+    libusb_device *dev;
+    libusb_device **devs;
     int count = 0;
+    int i = 0;
+
+    if (libusb_init(NULL) < 0)
+        ftdi_error_return(-4, "libusb_init() failed");
 
-    usb_init();
-    if (usb_find_busses() < 0)
-        ftdi_error_return(-1, "usb_find_busses() failed");
-    if (usb_find_devices() < 0)
-        ftdi_error_return(-2, "usb_find_devices() failed");
+    if (libusb_get_device_list(NULL, &devs) < 0)
+        ftdi_error_return(-5, "libusb_get_device_list() failed");
 
     curdev = devlist;
     *curdev = NULL;
-    for (bus = usb_get_busses(); bus; bus = bus->next)
+
+    while ((dev = devs[i++]) != NULL)
     {
-        for (dev = bus->devices; dev; dev = dev->next)
-        {
-            if (dev->descriptor.idVendor == vendor
-                    && dev->descriptor.idProduct == product)
-            {
-                *curdev = (struct ftdi_device_list*)malloc(sizeof(struct 
ftdi_device_list));
-                if (!*curdev)
-                    ftdi_error_return(-3, "out of memory");
+        struct libusb_device_descriptor desc;
 
-                (*curdev)->next = NULL;
-                (*curdev)->dev = dev;
+        if (libusb_get_device_descriptor(dev, &desc) < 0)
+            ftdi_error_return(-6, "libusb_get_device_descriptor() failed");
 
-                curdev = &(*curdev)->next;
-                count++;
-            }
+        if (desc.idVendor == vendor && desc.idProduct == product)
+        {
+            *curdev = (struct ftdi_device_list*)malloc(sizeof(struct 
ftdi_device_list));
+            if (!*curdev)
+                ftdi_error_return(-3, "out of memory");
+             
+            (*curdev)->next = NULL;
+            (*curdev)->dev = dev;
+
+            curdev = &(*curdev)->next;
+            count++;
         }
     }
 
@@ -317,46 +291,50 @@ void ftdi_list_free2(struct ftdi_device_
     \retval  -7: get product manufacturer failed
     \retval  -8: get product description failed
     \retval  -9: get serial number failed
-    \retval -10: unable to close device
+    \retval -11: libusb_get_device_descriptor() failed
 */
-int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct usb_device * dev,
+int ftdi_usb_get_strings(struct ftdi_context * ftdi, struct libusb_device * 
dev,
                          char * manufacturer, int mnf_len, char * description, 
int desc_len, char * serial, int serial_len)
 {
+    struct libusb_device_descriptor desc;
+
     if ((ftdi==NULL) || (dev==NULL))
         return -1;
 
-    if (!(ftdi->usb_dev = usb_open(dev)))
-        ftdi_error_return(-4, usb_strerror());
+    if (libusb_open(dev, &ftdi->usb_dev) < 0)
+        ftdi_error_return(-4, "libusb_open() failed");
+
+    if (libusb_get_device_descriptor(dev, &desc) < 0)
+        ftdi_error_return(-11, "libusb_get_device_descriptor() failed");
 
     if (manufacturer != NULL)
     {
-        if (usb_get_string_simple(ftdi->usb_dev, 
dev->descriptor.iManufacturer, manufacturer, mnf_len) <= 0)
+        if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, 
desc.iManufacturer, (unsigned char *)manufacturer, mnf_len) < 0)
         {
-            usb_close (ftdi->usb_dev);
-            ftdi_error_return(-7, usb_strerror());
+            libusb_close (ftdi->usb_dev);
+            ftdi_error_return(-7, "libusb_get_string_descriptor_ascii() 
failed");
         }
     }
 
     if (description != NULL)
     {
-        if (usb_get_string_simple(ftdi->usb_dev, dev->descriptor.iProduct, 
description, desc_len) <= 0)
+        if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, desc.iProduct, 
(unsigned char *)description, desc_len) < 0)
         {
-            usb_close (ftdi->usb_dev);
-            ftdi_error_return(-8, usb_strerror());
+            libusb_close (ftdi->usb_dev);
+            ftdi_error_return(-8, "libusb_get_string_descriptor_ascii() 
failed");
         }
     }
 
     if (serial != NULL)
     {
-        if (usb_get_string_simple(ftdi->usb_dev, 
dev->descriptor.iSerialNumber, serial, serial_len) <= 0)
+        if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, 
desc.iSerialNumber, (unsigned char *)serial, serial_len) < 0)
         {
-            usb_close (ftdi->usb_dev);
-            ftdi_error_return(-9, usb_strerror());
+            libusb_close (ftdi->usb_dev);
+            ftdi_error_return(-9, "libusb_get_string_descriptor_ascii() 
failed");
         }
     }
 
-    if (usb_close (ftdi->usb_dev) != 0)
-        ftdi_error_return(-10, usb_strerror());
+    libusb_close (ftdi->usb_dev);
 
     return 0;
 }
@@ -373,12 +351,28 @@ int ftdi_usb_get_strings(struct ftdi_con
     \retval -5: unable to claim device
     \retval -6: reset failed
     \retval -7: set baudrate failed
+    \retval -9: libusb_get_device_descriptor() failed
+    \retval -10: libusb_get_config_descriptor() failed
+    \retval -11: libusb_etach_kernel_driver() failed
+    \retval -12: libusb_get_configuration() failed
 */
-int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev)
+int ftdi_usb_open_dev(struct ftdi_context *ftdi, libusb_device *dev)
 {
-    int detach_errno = 0;
-    if (!(ftdi->usb_dev = usb_open(dev)))
-        ftdi_error_return(-4, "usb_open() failed");
+    struct libusb_device_descriptor desc;
+    struct libusb_config_descriptor *config0;
+    int ret;
+    int cfg, cfg0;
+
+    if (libusb_open(dev, &ftdi->usb_dev) < 0)
+        ftdi_error_return(-4, "libusb_open() failed");
+
+    if (libusb_get_device_descriptor(dev, &desc) < 0)
+        ftdi_error_return(-9, "libusb_get_device_descriptor() failed");
+
+    if (libusb_get_config_descriptor(dev, 0, &config0) < 0)
+        ftdi_error_return(-10, "libusb_get_config_descriptor() failed");
+    cfg0 = config0->bConfigurationValue;
+    libusb_free_config_descriptor (config0);
 
 #ifdef LIBUSB_HAS_GET_DRIVER_NP
     // Try to detach ftdi_sio kernel module.
@@ -388,67 +382,58 @@ int ftdi_usb_open_dev(struct ftdi_contex
     // 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;
+    ret = libusb_detach_kernel_driver(ftdi->usb_dev, ftdi->interface);
+    if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND)
+        ftdi_error_return(-11, "libusb_detach_kernel_driver () failed");
 #endif
 
+    if (libusb_get_configuration (ftdi->usb_dev, &cfg) < 0)
+        ftdi_error_return(-12, "libusb_get_configuration () failed");
+
     // 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)
+    if (desc.bNumConfigurations > 0 && cfg != cfg0)
     {
-        usb_close (ftdi->usb_dev);
-        if (detach_errno == EPERM)
-        {
-            ftdi_error_return(-8, "inappropriate permissions on device!");
-        }
-        else
+        if (libusb_set_configuration(ftdi->usb_dev, cfg0) < 0)
         {
+            libusb_close (ftdi->usb_dev);
             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)
+    if (libusb_claim_interface(ftdi->usb_dev, ftdi->interface) < 0)
     {
-        usb_close (ftdi->usb_dev);
-        if (detach_errno == EPERM)
-        {
-            ftdi_error_return(-8, "inappropriate permissions on device!");
-        }
-        else
-        {
-            ftdi_error_return(-5, "unable to claim usb device. Make sure 
ftdi_sio is unloaded!");
-        }
+        libusb_close (ftdi->usb_dev);
+        ftdi_error_return(-5, "unable to claim usb device. Make sure ftdi_sio 
is unloaded!");
     }
 
     if (ftdi_usb_reset (ftdi) != 0)
     {
-        usb_close (ftdi->usb_dev);
+        libusb_close (ftdi->usb_dev);
         ftdi_error_return(-6, "ftdi_usb_reset failed");
     }
 
     if (ftdi_set_baudrate (ftdi, 9600) != 0)
     {
-        usb_close (ftdi->usb_dev);
+        libusb_close (ftdi->usb_dev);
         ftdi_error_return(-7, "set baudrate failed");
     }
 
     // Try to guess chip type
     // Bug in the BM type chips: bcdDevice is 0x200 for serial == 0
-    if (dev->descriptor.bcdDevice == 0x400 || (dev->descriptor.bcdDevice == 
0x200
-            && dev->descriptor.iSerialNumber == 0))
+    if (desc.bcdDevice == 0x400 || (desc.bcdDevice == 0x200
+            && desc.iSerialNumber == 0))
         ftdi->type = TYPE_BM;
-    else if (dev->descriptor.bcdDevice == 0x200)
+    else if (desc.bcdDevice == 0x200)
         ftdi->type = TYPE_AM;
-    else if (dev->descriptor.bcdDevice == 0x500)
+    else if (desc.bcdDevice == 0x500)
         ftdi->type = TYPE_2232C;
-    else if (dev->descriptor.bcdDevice == 0x600)
+    else if (desc.bcdDevice == 0x600)
         ftdi->type = TYPE_R;
-    else if (dev->descriptor.bcdDevice == 0x700)
+    else if (desc.bcdDevice == 0x700)
         ftdi->type = TYPE_2232H;
-    else if (dev->descriptor.bcdDevice == 0x800)
+    else if (desc.bcdDevice == 0x800)
         ftdi->type = TYPE_4232H;
 
     // Set default interface on dual/quad type chips
@@ -492,8 +477,6 @@ int ftdi_usb_open(struct ftdi_context *f
     \param serial Serial to search for. Use NULL if not needed.
 
     \retval  0: all fine
-    \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 -5: unable to claim device
@@ -501,66 +484,66 @@ int ftdi_usb_open(struct ftdi_context *f
     \retval -7: set baudrate failed
     \retval -8: get product description failed
     \retval -9: get serial number failed
-    \retval -10: unable to close device
+    \retval -11: libusb_init() failed
+    \retval -12: libusb_get_device_list() failed
+    \retval -13: libusb_get_device_descriptor() failed
 */
 int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product,
                        const char* description, const char* serial)
 {
-    struct usb_bus *bus;
-    struct usb_device *dev;
+    libusb_device *dev;
+    libusb_device **devs;
     char string[256];
+    int i = 0;
 
-    usb_init();
+    if (libusb_init(NULL) < 0)
+        ftdi_error_return(-11, "libusb_init() failed");
 
-    if (usb_find_busses() < 0)
-        ftdi_error_return(-1, "usb_find_busses() failed");
-    if (usb_find_devices() < 0)
-        ftdi_error_return(-2, "usb_find_devices() failed");
+    if (libusb_get_device_list(NULL, &devs) < 0)
+        ftdi_error_return(-12, "libusb_get_device_list() failed");
 
-    for (bus = usb_get_busses(); bus; bus = bus->next)
+    while ((dev = devs[i++]) != NULL)
     {
-        for (dev = bus->devices; dev; dev = dev->next)
+        struct libusb_device_descriptor desc;
+
+        if (libusb_get_device_descriptor(dev, &desc) < 0)
+            ftdi_error_return(-13, "libusb_get_device_descriptor() failed");
+
+        if (desc.idVendor == vendor && desc.idProduct == product)
         {
-            if (dev->descriptor.idVendor == vendor
-                    && dev->descriptor.idProduct == product)
-            {
-                if (!(ftdi->usb_dev = usb_open(dev)))
-                    ftdi_error_return(-4, "usb_open() failed");
+            if (libusb_open(dev, &ftdi->usb_dev) < 0)
+                ftdi_error_return(-4, "usb_open() failed");
 
-                if (description != NULL)
+            if (description != NULL)
+            {
+                if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, 
desc.iProduct, (unsigned char *)string, sizeof(string)) < 0)
                 {
-                    if (usb_get_string_simple(ftdi->usb_dev, 
dev->descriptor.iProduct, string, sizeof(string)) <= 0)
-                    {
-                        usb_close (ftdi->usb_dev);
-                        ftdi_error_return(-8, "unable to fetch product 
description");
-                    }
-                    if (strncmp(string, description, sizeof(string)) != 0)
-                    {
-                        if (usb_close (ftdi->usb_dev) != 0)
-                            ftdi_error_return(-10, "unable to close device");
-                        continue;
-                    }
+                    libusb_close (ftdi->usb_dev);
+                    ftdi_error_return(-8, "unable to fetch product 
description");
                 }
-                if (serial != NULL)
+                if (strncmp(string, description, sizeof(string)) != 0)
                 {
-                    if (usb_get_string_simple(ftdi->usb_dev, 
dev->descriptor.iSerialNumber, string, sizeof(string)) <= 0)
-                    {
-                        usb_close (ftdi->usb_dev);
-                        ftdi_error_return(-9, "unable to fetch serial number");
-                    }
-                    if (strncmp(string, serial, sizeof(string)) != 0)
-                    {
-                        if (usb_close (ftdi->usb_dev) != 0)
-                            ftdi_error_return(-10, "unable to close device");
-                        continue;
-                    }
+                    libusb_close (ftdi->usb_dev);
+                    continue;
                 }
+            }
+            if (serial != NULL)
+            {
+                if (libusb_get_string_descriptor_ascii(ftdi->usb_dev, 
desc.iSerialNumber, (unsigned char *)string, sizeof(string)) < 0)
+                {
+                    libusb_close (ftdi->usb_dev);
+                    ftdi_error_return(-9, "unable to fetch serial number");
+                }
+                if (strncmp(string, serial, sizeof(string)) != 0)
+                {
+                    libusb_close (ftdi->usb_dev);
+                    continue;
+                }
+            }
 
-                if (usb_close (ftdi->usb_dev) != 0)
-                    ftdi_error_return(-10, "unable to close device");
+            libusb_close (ftdi->usb_dev);
 
-                return ftdi_usb_open_dev(ftdi, dev);
-            }
+            return ftdi_usb_open_dev(ftdi, dev);
         }
     }
 
@@ -578,9 +561,9 @@ int ftdi_usb_open_desc(struct ftdi_conte
 */
 int ftdi_usb_reset(struct ftdi_context *ftdi)
 {
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_RESET_REQUEST, SIO_RESET_SIO,
-                        ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_RESET_REQUEST, SIO_RESET_SIO,
+                                ftdi->index, NULL, 0, ftdi->usb_write_timeout) 
< 0)
         ftdi_error_return(-1,"FTDI reset failed");
 
     // Invalidate data in the readbuffer
@@ -600,9 +583,9 @@ int ftdi_usb_reset(struct ftdi_context *
 */
 int ftdi_usb_purge_rx_buffer(struct ftdi_context *ftdi)
 {
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_RESET_REQUEST, SIO_RESET_PURGE_RX,
-                        ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_RESET_REQUEST, SIO_RESET_PURGE_RX,
+                                ftdi->index, NULL, 0, ftdi->usb_write_timeout) 
< 0)
         ftdi_error_return(-1, "FTDI purge of RX buffer failed");
 
     // Invalidate data in the readbuffer
@@ -622,9 +605,9 @@ int ftdi_usb_purge_rx_buffer(struct ftdi
 */
 int ftdi_usb_purge_tx_buffer(struct ftdi_context *ftdi)
 {
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_RESET_REQUEST, SIO_RESET_PURGE_TX,
-                        ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_RESET_REQUEST, SIO_RESET_PURGE_TX,
+                                ftdi->index, NULL, 0, ftdi->usb_write_timeout) 
< 0)
         ftdi_error_return(-1, "FTDI purge of TX buffer failed");
 
     return 0;
@@ -661,22 +644,15 @@ int ftdi_usb_purge_buffers(struct ftdi_c
 
     \retval  0: all fine
     \retval -1: usb_release failed
-    \retval -2: usb_close failed
 */
 int ftdi_usb_close(struct ftdi_context *ftdi)
 {
     int rtn = 0;
 
-#ifdef LIBFTDI_LINUX_ASYNC_MODE
-    /* try to release some kernel resources */
-    ftdi_async_complete(ftdi,1);
-#endif
-
-    if (usb_release_interface(ftdi->usb_dev, ftdi->interface) != 0)
+    if (libusb_release_interface(ftdi->usb_dev, ftdi->interface) < 0)
         rtn = -1;
 
-    if (usb_close (ftdi->usb_dev) != 0)
-        rtn = -2;
+    libusb_close (ftdi->usb_dev);
 
     return rtn;
 }
@@ -838,9 +814,9 @@ int ftdi_set_baudrate(struct ftdi_contex
                 : (baudrate * 21 < actual_baudrate * 20)))
         ftdi_error_return (-1, "Unsupported baudrate. Note: bitbang baudrates 
are automatically multiplied by 4");
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_SET_BAUDRATE_REQUEST, value,
-                        index, NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_SET_BAUDRATE_REQUEST, value,
+                                index, NULL, 0, ftdi->usb_write_timeout) < 0)
         ftdi_error_return (-2, "Setting new baudrate failed");
 
     ftdi->baudrate = baudrate;
@@ -926,9 +902,9 @@ int ftdi_set_line_property2(struct ftdi_
             break;
     }
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_SET_DATA_REQUEST, value,
-                        ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_SET_DATA_REQUEST, value,
+                                ftdi->index, NULL, 0, ftdi->usb_write_timeout) 
< 0)
         ftdi_error_return (-1, "Setting new line property failed");
 
     return 0;
@@ -946,9 +922,8 @@ int ftdi_set_line_property2(struct ftdi_
 */
 int ftdi_write_data(struct ftdi_context *ftdi, unsigned char *buf, int size)
 {
-    int ret;
     int offset = 0;
-    int total_written = 0;
+    int actual_length;
 
     while (offset < size)
     {
@@ -957,226 +932,307 @@ int ftdi_write_data(struct ftdi_context 
         if (offset+write_size > size)
             write_size = size-offset;
 
-        ret = usb_bulk_write(ftdi->usb_dev, ftdi->in_ep, buf+offset, 
write_size, ftdi->usb_write_timeout);
-        if (ret < 0)
-            ftdi_error_return(ret, "usb bulk write failed");
+        if (libusb_bulk_transfer(ftdi->usb_dev, ftdi->in_ep, buf+offset, 
write_size, &actual_length, ftdi->usb_write_timeout) < 0)
+            ftdi_error_return(-1, "usb bulk write failed");
 
-        total_written += ret;
-        offset += write_size;
+        offset += actual_length;
     }
 
-    return total_written;
+    return offset;
 }
 
 #ifdef LIBFTDI_LINUX_ASYNC_MODE
-/* this is strongly dependent on libusb using the same struct layout. If libusb
-   changes in some later version this may break horribly (this is for libusb 
0.1.12) */
-struct usb_dev_handle
+static void ftdi_read_data_cb(struct libusb_transfer *transfer)
 {
-    int fd;
-    // some other stuff coming here we don't need
-};
+    struct ftdi_transfer_control *tc = (struct ftdi_transfer_control *) 
transfer->user_data;
+    struct ftdi_context *ftdi = tc->ftdi;
+    int packet_size, actual_length, num_of_chunks, chunk_remains, i, ret;
 
-/**
-    Check for pending async urbs
-    \internal
-*/
-static int _usb_get_async_urbs_pending(struct ftdi_context *ftdi)
+    // New hi-speed devices from FTDI use a packet size of 512 bytes
+    if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H)
+        packet_size = 512;
+    else
+        packet_size = 64;
+
+    actual_length = transfer->actual_length;
+
+    if (actual_length > 2)
+    {
+        // skip FTDI status bytes.
+        // Maybe stored in the future to enable modem use
+        num_of_chunks = actual_length / packet_size;
+        chunk_remains = actual_length % packet_size;
+        //printf("actual_length = %X, num_of_chunks = %X, chunk_remains = %X, 
readbuffer_offset = %X\n", actual_length, num_of_chunks, chunk_remains, 
ftdi->readbuffer_offset);
+
+        ftdi->readbuffer_offset += 2;
+        actual_length -= 2;
+
+        if (actual_length > packet_size - 2)
+        {
+            for (i = 1; i < num_of_chunks; i++)
+              memmove (ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size - 
2)*i,
+                       ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*i,
+                       packet_size - 2);
+            if (chunk_remains > 2)
+            {
+                memmove (ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size 
- 2)*i,
+                         
ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*i,
+                         chunk_remains-2);
+                actual_length -= 2*num_of_chunks;
+            }
+            else
+              actual_length -= 2*(num_of_chunks-1)+chunk_remains;
+        }
+
+        if (actual_length > 0)
+        {
+            // data still fits in buf?
+            if (tc->offset + actual_length <= tc->size)
+            {
+                memcpy (tc->buf + tc->offset, ftdi->readbuffer + 
ftdi->readbuffer_offset, actual_length);
+                //printf("buf[0] = %X, buf[1] = %X\n", buf[0], buf[1]);
+                tc->offset += actual_length;
+
+                ftdi->readbuffer_offset = 0;
+                ftdi->readbuffer_remaining = 0;
+
+                /* Did we read exactly the right amount of bytes? */
+                if (tc->offset == tc->size)
+                {
+                    //printf("read_data exact rem %d offset %d\n",
+                    //ftdi->readbuffer_remaining, offset);
+                    tc->completed = 1;
+                    return;
+                }
+            }
+            else
+            {
+                // only copy part of the data or size <= readbuffer_chunksize
+                int part_size = tc->size - tc->offset;
+                memcpy (tc->buf + tc->offset, ftdi->readbuffer + 
ftdi->readbuffer_offset, part_size);
+                tc->offset += part_size;
+
+                ftdi->readbuffer_offset += part_size;
+                ftdi->readbuffer_remaining = actual_length - part_size;
+
+                /* printf("Returning part: %d - size: %d - offset: %d - 
actual_length: %d - remaining: %d\n",
+                part_size, size, offset, actual_length, 
ftdi->readbuffer_remaining); */
+                tc->completed = 1;
+                return;
+            }
+        }
+    }
+    ret = libusb_submit_transfer (transfer);
+    if (ret < 0)
+        tc->completed = 1;
+}
+
+
+static void ftdi_write_data_cb(struct libusb_transfer *transfer)
 {
-    struct usbdevfs_urb *urb;
-    int pending=0;
-    unsigned int i;
+    struct ftdi_transfer_control *tc = (struct ftdi_transfer_control *) 
transfer->user_data;
+    struct ftdi_context *ftdi = tc->ftdi;
+
+    tc->offset = transfer->actual_length;
 
-    for (i=0; i < ftdi->async_usb_buffer_size; i++)
+    if (tc->offset == tc->size)
     {
-        urb=&((struct usbdevfs_urb *)(ftdi->async_usb_buffer))[i];
-        if (urb->usercontext != FTDI_URB_USERCONTEXT_COOKIE)
-            pending++;
+        tc->completed = 1;
     }
+    else
+    {
+        int write_size = ftdi->writebuffer_chunksize;
+        int ret;
 
-    return pending;
+        if (tc->offset + write_size > tc->size)
+            write_size = tc->size - tc->offset;
+
+        transfer->length = write_size;
+        transfer->buffer = tc->buf + tc->offset;
+        ret = libusb_submit_transfer (transfer);
+        if (ret < 0)
+            tc->completed = 1;
+    }
 }
 
+
 /**
-    Wait until one or more async URBs are completed by the kernel and mark 
their
-    positions in the async-buffer as unused
+    Writes data to the chip. Does not wait for completion of the transfer
+    nor does it make sure that the transfer was successful.
+
+    Use libusb 1.0 Asynchronous API.
+    Only available if compiled with --with-async-mode.
 
     \param ftdi pointer to ftdi_context
-    \param wait_for_more if != 0 wait for more than one write to complete
-    \param timeout_msec max milliseconds to wait
+    \param buf Buffer with the data
+    \param size Size of the buffer
 
-    \internal
+    \retval NULL: Some error happens when submit transfer
+    \retval !NULL: Pointer to a ftdi_transfer_control
 */
-static void _usb_async_cleanup(struct ftdi_context *ftdi, int wait_for_more, 
int timeout_msec)
+
+struct ftdi_transfer_control *ftdi_write_data_submit(struct ftdi_context 
*ftdi, unsigned char *buf, int size)
 {
-    struct timeval tv;
-    struct usbdevfs_urb *urb=NULL;
-    int ret;
-    fd_set writefds;
-    int keep_going=0;
+    struct ftdi_transfer_control *tc;
+    struct libusb_transfer *transfer = libusb_alloc_transfer(0);
+    int write_size, ret;
 
-    FD_ZERO(&writefds);
-    FD_SET(ftdi->usb_dev->fd, &writefds);
+    tc = (struct ftdi_transfer_control *) malloc (sizeof (*tc));
 
-    /* init timeout only once, select writes time left after call */
-    tv.tv_sec = timeout_msec / 1000;
-    tv.tv_usec = (timeout_msec % 1000) * 1000;
+    if (!tc || !transfer)
+        return NULL;
 
-    do
-    {
-        while (_usb_get_async_urbs_pending(ftdi)
-                && (ret = ioctl(ftdi->usb_dev->fd, USBDEVFS_REAPURBNDELAY, 
&urb)) == -1
-                && errno == EAGAIN)
-        {
-            if (keep_going && !wait_for_more)
-            {
-                /* don't wait if repeating only for keep_going */
-                keep_going=0;
-                break;
-            }
+    tc->ftdi = ftdi;
+    tc->completed = 0;
+    tc->buf = buf;
+    tc->size = size;
+    tc->offset = 0;
 
-            /* wait for timeout msec or something written ready */
-            select(ftdi->usb_dev->fd+1, NULL, &writefds, NULL, &tv);
-        }
+    if (size < ftdi->writebuffer_chunksize)
+      write_size = size;
+    else
+      write_size = ftdi->writebuffer_chunksize;
 
-        if (ret == 0 && urb != NULL)
-        {
-            /* got a free urb, mark it */
-            urb->usercontext = FTDI_URB_USERCONTEXT_COOKIE;
+    libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->in_ep, buf, 
write_size, ftdi_write_data_cb, tc, ftdi->usb_write_timeout);
+    transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
 
-            /* try to get more urbs that are ready now, but don't wait anymore 
*/
-            urb=NULL;
-            keep_going=1;
-        }
-        else
-        {
-            /* no more urbs waiting */
-            keep_going=0;
-        }
+    ret = libusb_submit_transfer(transfer);
+    if (ret < 0)
+    {
+        libusb_free_transfer(transfer);
+        tc->completed = 1;
+        tc->transfer = NULL;
+        return NULL;
     }
-    while (keep_going);
+    tc->transfer = transfer;
+
+    return tc;
 }
 
 /**
-    Wait until one or more async URBs are completed by the kernel and mark 
their
-    positions in the async-buffer as unused.
+    Reads data from the chip. Does not wait for completion of the transfer
+    nor does it make sure that the transfer was successful.
+
+    Use libusb 1.0 Asynchronous API.
+    Only available if compiled with --with-async-mode.
 
     \param ftdi pointer to ftdi_context
-    \param wait_for_more if != 0 wait for more than one write to complete 
(until write timeout)
-*/
-void ftdi_async_complete(struct ftdi_context *ftdi, int wait_for_more)
-{
-    _usb_async_cleanup(ftdi,wait_for_more,ftdi->usb_write_timeout);
-}
+    \param buf Buffer with the data
+    \param size Size of the buffer
 
-/**
-    Stupid libusb does not offer async writes nor does it allow
-    access to its fd - so we need some hacks here.
-    \internal
+    \retval NULL: Some error happens when submit transfer
+    \retval !NULL: Pointer to a ftdi_transfer_control
 */
-static int _usb_bulk_write_async(struct ftdi_context *ftdi, int ep, char 
*bytes, int size)
+
+struct ftdi_transfer_control *ftdi_read_data_submit(struct ftdi_context *ftdi, 
unsigned char *buf, int size)
 {
-    struct usbdevfs_urb *urb;
-    int bytesdone = 0, requested;
-    int ret, cleanup_count;
-    unsigned int i;
+    struct ftdi_transfer_control *tc;
+    struct libusb_transfer *transfer;
+    int ret;
 
-    do
+    tc = (struct ftdi_transfer_control *) malloc (sizeof (*tc));
+    if (!tc)
+        return NULL;
+
+    tc->ftdi = ftdi;
+    tc->buf = buf;
+    tc->size = size;
+
+    if (size <= ftdi->readbuffer_remaining)
     {
-        /* find a free urb buffer we can use */
-        urb=NULL;
-        for (cleanup_count=0; urb==NULL && cleanup_count <= 1; cleanup_count++)
-        {
-            if (i==ftdi->async_usb_buffer_size)
-            {
-                /* wait until some buffers are free */
-                _usb_async_cleanup(ftdi,0,ftdi->usb_write_timeout);
-            }
+        memcpy (buf, ftdi->readbuffer+ftdi->readbuffer_offset, size);
 
-            for (i=0; i < ftdi->async_usb_buffer_size; i++)
-            {
-                urb=&((struct usbdevfs_urb *)(ftdi->async_usb_buffer))[i];
-                if (urb->usercontext == FTDI_URB_USERCONTEXT_COOKIE)
-                    break;  /* found a free urb position */
-                urb=NULL;
-            }
-        }
+        // Fix offsets
+        ftdi->readbuffer_remaining -= size;
+        ftdi->readbuffer_offset += size;
 
-        /* no free urb position found */
-        if (urb==NULL)
-            return -1;
-
-        requested = size - bytesdone;
-        if (requested > 4096)
-            requested = 4096;
-
-        memset(urb,0,sizeof(urb));
-
-        urb->type = USBDEVFS_URB_TYPE_BULK;
-        urb->endpoint = ep;
-        urb->flags = 0;
-        urb->buffer = bytes + bytesdone;
-        urb->buffer_length = requested;
-        urb->signr = 0;
-        urb->actual_length = 0;
-        urb->number_of_packets = 0;
-        urb->usercontext = 0;
+        /* printf("Returning bytes from buffer: %d - remaining: %d\n", size, 
ftdi->readbuffer_remaining); */
 
-        do
-        {
-            ret = ioctl(ftdi->usb_dev->fd, USBDEVFS_SUBMITURB, urb);
-        }
-        while (ret < 0 && errno == EINTR);
-        if (ret < 0)
-            return ret;       /* the caller can read errno to get more info */
+        tc->completed = 1;
+        tc->offset = size;
+        tc->transfer = NULL;
+        return tc;
+    }
+
+    tc->completed = 0;
+    if (ftdi->readbuffer_remaining != 0)
+    {
+        memcpy (buf, ftdi->readbuffer+ftdi->readbuffer_offset, 
ftdi->readbuffer_remaining);
 
-        bytesdone += requested;
+        tc->offset = ftdi->readbuffer_remaining;
     }
-    while (bytesdone < size);
-    return bytesdone;
+    else
+        tc->offset = 0;
+
+    transfer = libusb_alloc_transfer(0);
+    if (!transfer)
+    {
+        free (tc);
+        return NULL;
+    }
+
+    ftdi->readbuffer_remaining = 0;
+    ftdi->readbuffer_offset = 0;
+
+    libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->out_ep, 
ftdi->readbuffer, ftdi->readbuffer_chunksize, ftdi_read_data_cb, tc, 
ftdi->usb_read_timeout);
+    transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
+
+    ret = libusb_submit_transfer(transfer);
+    if (ret < 0)
+    {
+        libusb_free_transfer(transfer);
+        free (tc);
+        return NULL;
+    }
+    tc->transfer = transfer;
+
+    return tc;
 }
 
 /**
-    Writes data in chunks (see ftdi_write_data_set_chunksize()) to the chip.
-    Does not wait for completion of the transfer nor does it make sure that
-    the transfer was successful.
-
-    This function could be extended to use signals and callbacks to inform the
-    caller of completion or error - but this is not done yet, volunteers 
welcome.
+    Wait for completion of the transfer.
 
-    Works around libusb and directly accesses functions only available on 
Linux.
+    Use libusb 1.0 Asynchronous API.
     Only available if compiled with --with-async-mode.
 
-    \param ftdi pointer to ftdi_context
-    \param buf Buffer with the data
-    \param size Size of the buffer
+    \param tc pointer to ftdi_transfer_control
 
-    \retval <0: error code from usb_bulk_write()
-    \retval >0: number of bytes written
+    \retval < 0: Some error happens
+    \retval >= 0: Data size transferred
 */
-int ftdi_write_data_async(struct ftdi_context *ftdi, unsigned char *buf, int 
size)
+
+int ftdi_transfer_data_done(struct ftdi_transfer_control *tc)
 {
     int ret;
-    int offset = 0;
-    int total_written = 0;
 
-    while (offset < size)
+    while (!tc->completed)
     {
-        int write_size = ftdi->writebuffer_chunksize;
-
-        if (offset+write_size > size)
-            write_size = size-offset;
-
-        ret = _usb_bulk_write_async(ftdi, ftdi->in_ep, buf+offset, write_size);
+        ret = libusb_handle_events(NULL);
         if (ret < 0)
-            ftdi_error_return(ret, "usb bulk write async failed");
-
-        total_written += ret;
-        offset += write_size;
+        {
+            if (ret == LIBUSB_ERROR_INTERRUPTED)
+                continue;
+            libusb_cancel_transfer(tc->transfer);
+            while (!tc->completed)
+                if (libusb_handle_events(NULL) < 0)
+                    break;
+            libusb_free_transfer(tc->transfer);
+            free (tc);
+            tc = NULL;
+            return ret;
+        }
     }
 
-    return total_written;
+    if (tc->transfer->status == LIBUSB_TRANSFER_COMPLETED)
+        ret = tc->offset;
+    else
+        ret = -1;
+
+    libusb_free_transfer(tc->transfer);
+    free(tc);
+    return ret;
 }
+
 #endif // LIBFTDI_LINUX_ASYNC_MODE
 
 /**
@@ -1217,7 +1273,7 @@ int ftdi_write_data_get_chunksize(struct
     \param buf Buffer to store data in
     \param size Size of the buffer
 
-    \retval <0: error code from usb_bulk_read()
+    \retval <0: error code from libusb_bulk_transfer()
     \retval  0: no data was available
     \retval >0: number of bytes read
 
@@ -1226,8 +1282,9 @@ int ftdi_write_data_get_chunksize(struct
 */
 int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size)
 {
-    int offset = 0, ret = 1, i, num_of_chunks, chunk_remains;
+    int offset = 0, ret, i, num_of_chunks, chunk_remains;
     int packet_size;
+    int actual_length = 1;
 
     // New hi-speed devices from FTDI use a packet size of 512 bytes
     if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H)
@@ -1257,27 +1314,27 @@ int ftdi_read_data(struct ftdi_context *
         offset += ftdi->readbuffer_remaining;
     }
     // do the actual USB read
-    while (offset < size && ret > 0)
+    while (offset < size && actual_length > 0)
     {
         ftdi->readbuffer_remaining = 0;
         ftdi->readbuffer_offset = 0;
         /* returns how much received */
-        ret = usb_bulk_read (ftdi->usb_dev, ftdi->out_ep, ftdi->readbuffer, 
ftdi->readbuffer_chunksize, ftdi->usb_read_timeout);
+        ret = libusb_bulk_transfer (ftdi->usb_dev, ftdi->out_ep, 
ftdi->readbuffer, ftdi->readbuffer_chunksize, &actual_length, 
ftdi->usb_read_timeout);
         if (ret < 0)
             ftdi_error_return(ret, "usb bulk read failed");
 
-        if (ret > 2)
+        if (actual_length > 2)
         {
             // skip FTDI status bytes.
             // Maybe stored in the future to enable modem use
-            num_of_chunks = ret / packet_size;
-            chunk_remains = ret % packet_size;
-            //printf("ret = %X, num_of_chunks = %X, chunk_remains = %X, 
readbuffer_offset = %X\n", ret, num_of_chunks, chunk_remains, 
ftdi->readbuffer_offset);
+            num_of_chunks = actual_length / packet_size;
+            chunk_remains = actual_length % packet_size;
+            //printf("actual_length = %X, num_of_chunks = %X, chunk_remains = 
%X, readbuffer_offset = %X\n", actual_length, num_of_chunks, chunk_remains, 
ftdi->readbuffer_offset);
 
             ftdi->readbuffer_offset += 2;
-            ret -= 2;
+            actual_length -= 2;
 
-            if (ret > packet_size - 2)
+            if (actual_length > packet_size - 2)
             {
                 for (i = 1; i < num_of_chunks; i++)
                     memmove 
(ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size - 2)*i,
@@ -1288,25 +1345,25 @@ int ftdi_read_data(struct ftdi_context *
                     memmove 
(ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size - 2)*i,
                              
ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*i,
                              chunk_remains-2);
-                    ret -= 2*num_of_chunks;
+                    actual_length -= 2*num_of_chunks;
                 }
                 else
-                    ret -= 2*(num_of_chunks-1)+chunk_remains;
+                    actual_length -= 2*(num_of_chunks-1)+chunk_remains;
             }
         }
-        else if (ret <= 2)
+        else if (actual_length <= 2)
         {
             // no more data to read?
             return offset;
         }
-        if (ret > 0)
+        if (actual_length > 0)
         {
             // data still fits in buf?
-            if (offset+ret <= size)
+            if (offset+actual_length <= size)
             {
-                memcpy (buf+offset, ftdi->readbuffer+ftdi->readbuffer_offset, 
ret);
+                memcpy (buf+offset, ftdi->readbuffer+ftdi->readbuffer_offset, 
actual_length);
                 //printf("buf[0] = %X, buf[1] = %X\n", buf[0], buf[1]);
-                offset += ret;
+                offset += actual_length;
 
                 /* Did we read exactly the right amount of bytes? */
                 if (offset == size)
@@ -1321,11 +1378,11 @@ int ftdi_read_data(struct ftdi_context *
                 memcpy (buf+offset, ftdi->readbuffer+ftdi->readbuffer_offset, 
part_size);
 
                 ftdi->readbuffer_offset += part_size;
-                ftdi->readbuffer_remaining = ret-part_size;
+                ftdi->readbuffer_remaining = actual_length-part_size;
                 offset += part_size;
 
-                /* printf("Returning part: %d - size: %d - offset: %d - ret: 
%d - remaining: %d\n",
-                part_size, size, offset, ret, ftdi->readbuffer_remaining); */
+                /* printf("Returning part: %d - size: %d - offset: %d - 
actual_length: %d - remaining: %d\n",
+                part_size, size, offset, actual_length, 
ftdi->readbuffer_remaining); */
 
                 return offset;
             }
@@ -1398,9 +1455,9 @@ int ftdi_enable_bitbang(struct ftdi_cont
     /* FT2232C: Set bitbang_mode to 2 to enable SPI */
     usb_val |= (ftdi->bitbang_mode << 8);
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_SET_BITMODE_REQUEST, usb_val, ftdi->index,
-                        NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_SET_BITMODE_REQUEST, usb_val, ftdi->index,
+                                NULL, 0, ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "unable to enter bitbang mode. Perhaps not a BM 
type chip?");
 
     ftdi->bitbang_enabled = 1;
@@ -1417,7 +1474,7 @@ int ftdi_enable_bitbang(struct ftdi_cont
 */
 int ftdi_disable_bitbang(struct ftdi_context *ftdi)
 {
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_BITMODE_REQUEST, 0, ftdi->index, NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_BITMODE_REQUEST, 0, ftdi->index, NULL, 0, ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "unable to leave bitbang mode. Perhaps not a BM 
type chip?");
 
     ftdi->bitbang_enabled = 0;
@@ -1441,7 +1498,7 @@ int ftdi_set_bitmode(struct ftdi_context
 
     usb_val = bitmask; // low byte: bitmask
     usb_val |= (mode << 8);
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_BITMODE_REQUEST, usb_val, ftdi->index, NULL, 0, 
ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_BITMODE_REQUEST, usb_val, ftdi->index, NULL, 0, 
ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "unable to configure bitbang mode. Perhaps not a 
2232C type chip?");
 
     ftdi->bitbang_mode = mode;
@@ -1460,7 +1517,7 @@ int ftdi_set_bitmode(struct ftdi_context
 */
 int ftdi_read_pins(struct ftdi_context *ftdi, unsigned char *pins)
 {
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_READ_PINS_REQUEST, 0, ftdi->index, (char *)pins, 1, ftdi->usb_read_timeout) 
!= 1)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_READ_PINS_REQUEST, 0, ftdi->index, (unsigned char *)pins, 1, 
ftdi->usb_read_timeout) != 1)
         ftdi_error_return(-1, "read pins failed");
 
     return 0;
@@ -1488,7 +1545,7 @@ int ftdi_set_latency_timer(struct ftdi_c
         ftdi_error_return(-1, "latency out of range. Only valid for 1-255");
 
     usb_val = latency;
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_LATENCY_TIMER_REQUEST, usb_val, ftdi->index, NULL, 0, 
ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_LATENCY_TIMER_REQUEST, usb_val, ftdi->index, NULL, 0, 
ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-2, "unable to set latency timer");
 
     return 0;
@@ -1506,7 +1563,7 @@ int ftdi_set_latency_timer(struct ftdi_c
 int ftdi_get_latency_timer(struct ftdi_context *ftdi, unsigned char *latency)
 {
     unsigned short usb_val;
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_GET_LATENCY_TIMER_REQUEST, 0, ftdi->index, (char *)&usb_val, 1, 
ftdi->usb_read_timeout) != 1)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_GET_LATENCY_TIMER_REQUEST, 0, ftdi->index, (unsigned char *)&usb_val, 1, 
ftdi->usb_read_timeout) != 1)
         ftdi_error_return(-1, "reading latency timer failed");
 
     *latency = (unsigned char)usb_val;
@@ -1556,7 +1613,7 @@ int ftdi_poll_modem_status(struct ftdi_c
 {
     char usb_val[2];
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_POLL_MODEM_STATUS_REQUEST, 0, ftdi->index, usb_val, 2, 
ftdi->usb_read_timeout) != 2)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_POLL_MODEM_STATUS_REQUEST, 0, ftdi->index, (unsigned char *)usb_val, 2, 
ftdi->usb_read_timeout) != 2)
         ftdi_error_return(-1, "getting modem status failed");
 
     *status = (usb_val[1] << 8) | usb_val[0];
@@ -1576,9 +1633,9 @@ int ftdi_poll_modem_status(struct ftdi_c
 */
 int ftdi_setflowctrl(struct ftdi_context *ftdi, int flowctrl)
 {
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_SET_FLOW_CTRL_REQUEST, 0, (flowctrl | ftdi->index),
-                        NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_SET_FLOW_CTRL_REQUEST, 0, (flowctrl | 
ftdi->index),
+                                NULL, 0, ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "set flow control failed");
 
     return 0;
@@ -1602,9 +1659,9 @@ int ftdi_setdtr(struct ftdi_context *ftd
     else
         usb_val = SIO_SET_DTR_LOW;
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->index,
-                        NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_SET_MODEM_CTRL_REQUEST, usb_val, 
ftdi->index,
+                                NULL, 0, ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "set dtr failed");
 
     return 0;
@@ -1628,9 +1685,9 @@ int ftdi_setrts(struct ftdi_context *ftd
     else
         usb_val = SIO_SET_RTS_LOW;
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->index,
-                        NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_SET_MODEM_CTRL_REQUEST, usb_val, 
ftdi->index,
+                                NULL, 0, ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "set of rts failed");
 
     return 0;
@@ -1660,9 +1717,9 @@ int ftdi_setdtr_rts(struct ftdi_context 
     else
         usb_val |= SIO_SET_RTS_LOW;
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                        SIO_SET_MODEM_CTRL_REQUEST, usb_val, ftdi->index,
-                        NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                SIO_SET_MODEM_CTRL_REQUEST, usb_val, 
ftdi->index,
+                                NULL, 0, ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "set of rts/dtr failed");
 
     return 0;
@@ -1687,7 +1744,7 @@ int ftdi_set_event_char(struct ftdi_cont
     if (enable)
         usb_val |= 1 << 8;
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_EVENT_CHAR_REQUEST, usb_val, ftdi->index, NULL, 0, 
ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_EVENT_CHAR_REQUEST, usb_val, ftdi->index, NULL, 0, 
ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "setting event character failed");
 
     return 0;
@@ -1712,7 +1769,7 @@ int ftdi_set_error_char(struct ftdi_cont
     if (enable)
         usb_val |= 1 << 8;
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_ERROR_CHAR_REQUEST, usb_val, ftdi->index, NULL, 0, 
ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_SET_ERROR_CHAR_REQUEST, usb_val, ftdi->index, NULL, 0, 
ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "setting error character failed");
 
     return 0;
@@ -1941,7 +1998,7 @@ int ftdi_eeprom_build(struct ftdi_eeprom
    Decode binary EEPROM image into an ftdi_eeprom structure.
 
    \param eeprom Pointer to ftdi_eeprom which will be filled in.
-   \param output Buffer of \a size bytes of raw eeprom data
+   \param buf Buffer of \a size bytes of raw eeprom data
    \param size size size of eeprom data in bytes
 
    \retval 0: all fine
@@ -1955,7 +2012,6 @@ int ftdi_eeprom_decode(struct ftdi_eepro
     unsigned char i, j;
     unsigned short checksum, eeprom_checksum, value;
     unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0;
-    int size_check;
     int eeprom_size = 128;
 #if 0
     size_check = eeprom->size;
@@ -2118,7 +2174,7 @@ int ftdi_read_eeprom(struct ftdi_context
 
     for (i = 0; i < ftdi->eeprom_size/2; i++)
     {
-        if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_READ_EEPROM_REQUEST, 0, i, eeprom+(i*2), 2, ftdi->usb_read_timeout) != 2)
+        if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_READ_EEPROM_REQUEST, 0, i, eeprom+(i*2), 2, ftdi->usb_read_timeout) != 2)
             ftdi_error_return(-1, "reading eeprom failed");
     }
 
@@ -2155,10 +2211,10 @@ int ftdi_read_chipid(struct ftdi_context
 {
     unsigned int a = 0, b = 0;
 
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_READ_EEPROM_REQUEST, 0, 0x43, (char *)&a, 2, ftdi->usb_read_timeout) == 2)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_READ_EEPROM_REQUEST, 0, 0x43, (unsigned char *)&a, 2, 
ftdi->usb_read_timeout) == 2)
     {
         a = a << 8 | a >> 8;
-        if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_READ_EEPROM_REQUEST, 0, 0x44, (char *)&b, 2, ftdi->usb_read_timeout) == 2)
+        if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, 
SIO_READ_EEPROM_REQUEST, 0, 0x44, (unsigned char *)&b, 2, 
ftdi->usb_read_timeout) == 2)
         {
             b = b << 8 | b >> 8;
             a = (a << 16) | (b & 0xFFFF);
@@ -2191,9 +2247,9 @@ int ftdi_read_eeprom_getsize(struct ftdi
     {
         for (j = 0; i < maxsize/2 && j<size; j++)
         {
-            if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE,
-                                SIO_READ_EEPROM_REQUEST, 0, i,
-                                eeprom+(i*2), 2, ftdi->usb_read_timeout) != 2)
+            if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE,
+                                        SIO_READ_EEPROM_REQUEST, 0, i,
+                                        eeprom+(i*2), 2, 
ftdi->usb_read_timeout) != 2)
                 ftdi_error_return(-1, "reading eeprom failed");
             i++;
         }
@@ -2230,9 +2286,9 @@ int ftdi_write_eeprom(struct ftdi_contex
     {
         usb_val = eeprom[i*2];
         usb_val += eeprom[(i*2)+1] << 8;
-        if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
-                            SIO_WRITE_EEPROM_REQUEST, usb_val, i,
-                            NULL, 0, ftdi->usb_write_timeout) != 0)
+        if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+                                    SIO_WRITE_EEPROM_REQUEST, usb_val, i,
+                                    NULL, 0, ftdi->usb_write_timeout) < 0)
             ftdi_error_return(-1, "unable to write eeprom");
     }
 
@@ -2251,7 +2307,7 @@ int ftdi_write_eeprom(struct ftdi_contex
 */
 int ftdi_erase_eeprom(struct ftdi_context *ftdi)
 {
-    if (usb_control_msg(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_ERASE_EEPROM_REQUEST, 0, 0, NULL, 0, ftdi->usb_write_timeout) != 0)
+    if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE, 
SIO_ERASE_EEPROM_REQUEST, 0, 0, NULL, 0, ftdi->usb_write_timeout) < 0)
         ftdi_error_return(-1, "unable to erase eeprom");
 
     return 0;
Index: src/Makefile.am
===================================================================
--- src/Makefile.am     (revision 3519)
+++ src/Makefile.am     (working copy)
@@ -11,5 +11,6 @@ include_HEADERS =  ftdi.h
 #  the library that is made has version (a-c).c.b.  In this
 #  example, the version is 2.1.2. (3:2:1)
 libftdi_la_LDFLAGS = -version-info 17:0:16 $(all_libraries)
+libftdi_la_LIBADD = @USB_LIBS@
 
 EXTRA_DIST = CMakeLists.txt
Index: src/ftdi.h
===================================================================
--- src/ftdi.h  (revision 3519)
+++ src/ftdi.h  (working copy)
@@ -17,7 +17,7 @@
 #ifndef __libftdi_h__
 #define __libftdi_h__
 
-#include <usb.h>
+#include <libusb.h>
 
 #define FTDI_DEFAULT_EEPROM_SIZE 128
 
@@ -104,8 +104,8 @@ enum ftdi_interface
 #define SIO_SET_BAUD_RATE  3 /* Set baud rate */
 #define SIO_SET_DATA       4 /* Set the data characteristics of the port */
 
-#define FTDI_DEVICE_OUT_REQTYPE (USB_TYPE_VENDOR | USB_RECIP_DEVICE | 
USB_ENDPOINT_OUT)
-#define FTDI_DEVICE_IN_REQTYPE (USB_TYPE_VENDOR | USB_RECIP_DEVICE | 
USB_ENDPOINT_IN)
+#define FTDI_DEVICE_OUT_REQTYPE (LIBUSB_REQUEST_TYPE_VENDOR | 
LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT)
+#define FTDI_DEVICE_IN_REQTYPE (LIBUSB_REQUEST_TYPE_VENDOR | 
LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN)
 
 /* Requests */
 #define SIO_RESET_REQUEST             SIO_RESET
@@ -147,6 +147,16 @@ enum ftdi_interface
    (taken from libusb) */
 #define FTDI_URB_USERCONTEXT_COOKIE ((void *)0x1)
 
+struct ftdi_transfer_control
+{
+    int completed;
+    unsigned char *buf;
+    int size;
+    int offset;
+    struct ftdi_context *ftdi;
+    struct libusb_transfer *transfer;
+};
+
 /**
     \brief Main context structure for all libftdi functions.
 
@@ -156,7 +166,7 @@ struct ftdi_context
 {
     /* USB specific */
     /** libusb's usb_dev_handle */
-    struct usb_dev_handle *usb_dev;
+    struct libusb_device_handle *usb_dev;
     /** usb read timeout */
     int usb_read_timeout;
     /** usb write timeout */
@@ -198,11 +208,6 @@ struct ftdi_context
 
     /** String representation of last error */
     char *error_str;
-
-    /** Buffer needed for async communication */
-    char *async_usb_buffer;
-    /** Number of URB-structures we can buffer */
-    unsigned int async_usb_buffer_size;
 };
 
 /**
@@ -213,7 +218,7 @@ struct ftdi_device_list
     /** pointer to next entry */
     struct ftdi_device_list *next;
     /** pointer to libusb's usb_device */
-    struct usb_device *dev;
+    struct libusb_device *dev;
 };
 
 /**
@@ -272,13 +277,13 @@ extern "C"
 
     void ftdi_deinit(struct ftdi_context *ftdi);
     void ftdi_free(struct ftdi_context *ftdi);
-    void ftdi_set_usbdev (struct ftdi_context *ftdi, usb_dev_handle *usbdev);
+    void ftdi_set_usbdev (struct ftdi_context *ftdi, struct 
libusb_device_handle *usbdev);
 
     int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list 
**devlist,
                           int vendor, int product);
     void ftdi_list_free(struct ftdi_device_list **devlist);
     void ftdi_list_free2(struct ftdi_device_list *devlist);
-    int ftdi_usb_get_strings(struct ftdi_context *ftdi, struct usb_device *dev,
+    int ftdi_usb_get_strings(struct ftdi_context *ftdi, struct libusb_device 
*dev,
                              char * manufacturer, int mnf_len,
                              char * description, int desc_len,
                              char * serial, int serial_len);
@@ -286,7 +291,7 @@ extern "C"
     int ftdi_usb_open(struct ftdi_context *ftdi, int vendor, int product);
     int ftdi_usb_open_desc(struct ftdi_context *ftdi, int vendor, int product,
                            const char* description, const char* serial);
-    int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct usb_device *dev);
+    int ftdi_usb_open_dev(struct ftdi_context *ftdi, struct libusb_device 
*dev);
 
     int ftdi_usb_close(struct ftdi_context *ftdi);
     int ftdi_usb_reset(struct ftdi_context *ftdi);
Index: configure.in
===================================================================
--- configure.in        (revision 3519)
+++ configure.in        (working copy)
@@ -7,30 +7,70 @@ AC_PROG_CC
 AM_PROG_LIBTOOL
 AC_PROG_CXX
 
-dnl check for libusb-config
-AC_PATH_PROG(HAVELIBUSB, libusb-config, $PATH)
+AC_CONFIG_MACRO_DIR([m4])
 
-if test ! -z "$HAVELIBUSB"; then
-   LIBUSB_CFLAGS=`$HAVELIBUSB --cflags`
-   LIBUSB_LIBS=`$HAVELIBUSB --libs`
+dnl ***********
+dnl USB Support
+dnl ***********
+
+dnl Enable libusb-1.0, if available
+AC_ARG_ENABLE(libusb_1_0,
+       AC_HELP_STRING([--enable-libusb_1_0], [enable libusb-1.0 support if 
available]),
+       [enable_libusb_1_0=$enableval], [enable_libusb_1_0=no])
+
+dnl USB support enabled by default (if found).  Note: Overloading libusb
+dnl option right now to disable USB support on any platform; even
+dnl if they use a different library name.
+AC_ARG_ENABLE(libusb, 
+    AC_HELP_STRING([--disable-libusb], [disable support for USB in SANE]),,
+    enable_libusb=auto)
+HAVE_USB=no
+if test "$enable_libusb" != "no"; then
+  case ${host_os} in
+  *)
+  dnl If libusb-1.0 is enabled and available, prefer that to the old libusb
+  have_libusb_1_0=no
+  if test "$enable_libusb_1_0" = "yes"; then
+    PKG_CHECK_MODULES(LIBUSB_1_0, [ libusb-1.0 >= 1.0.0 ], 
have_libusb_1_0=yes, have_libusb_1_0=no)
+    if test "$have_libusb_1_0" = "yes"; then
+      CFLAGS="$CFLAGS $LIBUSB_1_0_CFLAGS"
+      CXXFLAGS="$CXXFLAGS $LIBUSB_1_0_CFLAGS"
+      USB_LIBS="$USB_LIBS $LIBUSB_1_0_LIBS"
+      HAVE_USB=yes
+    fi
+  fi
 
-   CFLAGS="$CFLAGS $LIBUSB_CFLAGS"
-   LIBS="$LIBS $LIBUSB_LIBS"
-else
-   AC_MSG_ERROR([*** libusb-config not found. You need a working libusb 
installation.])
+  if test "$have_libusb_1_0" = "no"; then
+    dnl Fallback to the old libusb
+    dnl libusb >= 0.1.8 is required, as we need usb_interrupt_read()
+    AC_CHECK_HEADER(usb.h,
+                    AC_CHECK_LIB(usb, usb_interrupt_read, 
+                                 [USB_LIBS="$USB_LIBS -lusb"
+                                  HAVE_USB=yes]))
+  fi
+  ;;
+  esac
 fi
-
-dnl check for version of libusb
-AC_MSG_CHECKING([if libusb version is >= 0.1.7])
-libusb_version_needed="1007"
-libusb_version=`$HAVELIBUSB --version | sed -e "s/libusb //" | awk 'BEGIN { FS 
= "."; } { printf "%d", ($''1 * 1000 + $''2) * 1000 + $''3;}'`
-
-if test $libusb_version -lt $libusb_version_needed; then
-   AC_MSG_RESULT(no)
-   AC_MSG_ERROR([*** libusb is too old ($libusb_version). You need a libusb 
installation newer or equal to 0.1.7.])
-else
-   AC_MSG_RESULT(yes)
+dnl The following logic is useful for distributions.  If they force
+dnl USB support with --enable-libusb=yes then configure will fail
+dnl when its detected that it can not be supported.  Default is
+dnl "auto" which means only enable if libraries are found and do
+dnl not error out.
+if test "$enable_libusb" = "yes" && test "$HAVE_USB" = "no"; then
+  AC_MSG_ERROR([USB support requested but required libraries not found.])
+fi
+if test "$HAVE_USB" = "yes"; then
+  case ${host_os} in
+  *)
+  if test "$have_libusb_1_0" = "yes"; then
+    AC_DEFINE(HAVE_LIBUSB_1_0, 1, [Define to 1 if you have libusb-1.0.])
+  else
+    AC_DEFINE(HAVE_LIBUSB, 1, [Define to 1 if you have libusb.])
+  fi
+  ;;
+  esac
 fi
+AC_SUBST(USB_LIBS)
 
 ENABLE_ASYNC_MODE=0
 AC_ARG_WITH(async-mode,
Index: config.h.in
===================================================================
--- config.h.in (revision 3519)
+++ config.h.in (working copy)
@@ -9,6 +9,12 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have libusb. */
+#undef HAVE_LIBUSB
+
+/* Define to 1 if you have libusb-1.0. */
+#undef HAVE_LIBUSB_1_0
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -33,6 +39,10 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
 /* Name of package */
 #undef PACKAGE
 
@@ -48,6 +58,9 @@
 /* Define to the one symbol short name of this package. */
 #undef PACKAGE_TARNAME
 
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
Index: Makefile.am
===================================================================
--- Makefile.am (revision 3519)
+++ Makefile.am (working copy)
@@ -14,3 +14,7 @@ bin_SCRIPTS = libftdi-config
 # Install the pkg-config file:
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libftdi.pc $(LIBFTDI_MODULES_PKGCONFIG)
+
+USB_LIBS = @USB_LIBS@
+
+ACLOCAL_AMFLAGS=-I m4
Index: examples/bitbang_cbus.c
===================================================================
--- examples/bitbang_cbus.c     (revision 3519)
+++ examples/bitbang_cbus.c     (working copy)
@@ -40,7 +40,7 @@ int main(void)
     int f;
     unsigned char buf[1];
     unsigned char bitmask;
-    unsigned char input[10];
+    char input[10];
 
     if (ftdi_init(&ftdic) < 0)
     {
@@ -84,4 +84,6 @@ int main(void)
 
     ftdi_usb_close(&ftdic);
     ftdi_deinit(&ftdic);
+
+    return 0;
 }
Index: examples/bitbang.c
===================================================================
--- examples/bitbang.c  (revision 3519)
+++ examples/bitbang.c  (working copy)
@@ -1,6 +1,7 @@
 /* This program is distributed under the GPL, version 2 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #ifdef __WIN32__
 #define sleep(x) Sleep(x)
@@ -11,7 +12,7 @@ int main(int argc, char **argv)
 {
     struct ftdi_context ftdic;
     int f,i;
-    char buf[1];
+    unsigned char buf[1];
 
     if (ftdi_init(&ftdic) < 0)
     {
@@ -78,4 +79,6 @@ int main(int argc, char **argv)
 
     ftdi_usb_close(&ftdic);
     ftdi_deinit(&ftdic);
+
+    return 0;
 }
Index: examples/bitbang2.c
===================================================================
--- examples/bitbang2.c (revision 3519)
+++ examples/bitbang2.c (working copy)
@@ -30,6 +30,7 @@
 
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #ifdef __WIN32__
 #define usleep(x) Sleep((x+999)/1000)
Index: examples/bitbang_ft2232.c
===================================================================
--- examples/bitbang_ft2232.c   (revision 3519)
+++ examples/bitbang_ft2232.c   (working copy)
@@ -9,6 +9,7 @@
 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #ifdef __WIN32__
 #define sleep(x) _sleep(x)
@@ -18,7 +19,7 @@
 int main(int argc, char **argv)
 {
     struct ftdi_context ftdic, ftdic2;
-    char buf[1];
+    unsigned char buf[1];
     int f,i;
 
     // Init 1. channel
@@ -101,4 +102,6 @@ int main(int argc, char **argv)
     ftdi_disable_bitbang(&ftdic2);
     ftdi_usb_close(&ftdic2);
     ftdi_deinit(&ftdic2);
+
+    return 0;
 }
Index: examples/find_all.c
===================================================================
--- examples/find_all.c (revision 3519)
+++ examples/find_all.c (working copy)
@@ -6,6 +6,7 @@
 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <ftdi.h>
 
 int main(void)
Index: examples/simple.c
===================================================================
--- examples/simple.c   (revision 3519)
+++ examples/simple.c   (working copy)
@@ -6,6 +6,7 @@
 */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <ftdi.h>
 
 int main(void)
Current Thread