Windows: add USB 3.0 controller support
authorPete Batard <pete@akeo.ie>
Mon, 19 Sep 2011 14:41:39 +0000 (15:41 +0100)
committerPeter Stuge <peter@stuge.se>
Mon, 17 Oct 2011 14:25:51 +0000 (16:25 +0200)
* Windows 8, NEC/Renesas, TI, Fresco Logic, Etron, VIA, ASMedia
  (some of which untested!)
* includes workaround for NEC/Renesas USB 3.0 root hubs

libusb/os/windows_usb.c

index f8f1fcd..a96c8c4 100644 (file)
@@ -245,7 +245,7 @@ static int init_dlls(void)
  * Parameters:
  * dev_info: a pointer to a dev_info list
  * dev_info_data: a pointer to an SP_DEVINFO_DATA to be filled (or NULL if not needed)
- * guid: the GUID for which to retrieve interface details
+ * usb_class: the generic USB class for which to retrieve interface details
  * index: zero based index of the interface in the device info list
  *
  * Note: it is the responsibility of the caller to free the DEVICE_INTERFACE_DETAIL_DATA
@@ -253,10 +253,10 @@ static int init_dlls(void)
  * incremented index starting at zero) until all interfaces have been returned.
  */
 static bool get_devinfo_data(struct libusb_context *ctx,
-       HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, unsigned _index)
+       HDEVINFO *dev_info, SP_DEVINFO_DATA *dev_info_data, char* usb_class, unsigned _index)
 {
        if (_index <= 0) {
-               *dev_info = pSetupDiGetClassDevsA(NULL, "USB", NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
+               *dev_info = pSetupDiGetClassDevsA(NULL, usb_class, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
                if (*dev_info == INVALID_HANDLE_VALUE) {
                        return false;
                }
@@ -1183,7 +1183,8 @@ static int set_composite_interface(struct libusb_context* ctx, struct libusb_dev
 static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs)
 {
        struct discovered_devs *discdevs = *_discdevs;
-       HDEVINFO dev_info;
+       HDEVINFO dev_info = { 0 };
+       char* usb_class[2] = {"USB", "NUSB3"};
        SP_DEVINFO_DATA dev_info_data;
        SP_DEVICE_INTERFACE_DETAIL_DATA_A *dev_interface_details = NULL;
 #define MAX_ENUM_GUIDS 64
@@ -1193,6 +1194,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
 #define GEN_PASS 2
 #define DEV_PASS 3
        int r = LIBUSB_SUCCESS;
+       int class_index = 0;
        unsigned int nb_guids, pass, i, j, ancestor;
        char path[MAX_PATH_LENGTH];
        char strbuf[MAX_PATH_LENGTH];
@@ -1202,6 +1204,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
        char* dev_id_path = NULL;
        unsigned long session_id;
        DWORD size, reg_type, port_nr, install_state;
+       BOOL b = FALSE;
        HKEY key;
        WCHAR guid_string_w[MAX_GUID_STRING_LENGTH];
        GUID* if_guid;
@@ -1283,9 +1286,14 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
                                        }
                                }
                        } else {
-                               if (!get_devinfo_data(ctx, &dev_info, &dev_info_data, i)) {
-                                       break;
+                               // Workaround for a Nec/Renesas USB 3.0 driver bug where root hubs are
+                               // being listed under the "NUSB3" PnP Symbolic Name rather than "USB"
+                               while ( (class_index < 2) &&
+                                           (!(b = get_devinfo_data(ctx, &dev_info, &dev_info_data, usb_class[class_index], i))) ) {
+                                               class_index++;
+                                               i = 0;
                                }
+                               if (!b) break;
                        }
 
                        // Read the Device ID path. This is what we'll use as UID
@@ -2211,7 +2219,7 @@ static int unsupported_copy_transfer_data(struct usbi_transfer *itransfer, uint3
 }
 
 // These names must be uppercase
-const char* hub_driver_names[] = {"USBHUB"};
+const char* hub_driver_names[] = {"USBHUB", "USBHUB3", "NUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3"};
 const char* composite_driver_names[] = {"USBCCGP"};
 const char* winusb_driver_names[] = {"WINUSB"};
 const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {