From: Jim Chen Date: Wed, 3 Feb 2021 18:13:55 +0000 (-0500) Subject: Windows: Try alternative methods to query port number X-Git-Tag: upstream/1.0.25~70 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d551802db593436947a2464a7da1020edf0e7b56;p=platform%2Fupstream%2Flibusb.git Windows: Try alternative methods to query port number This commit is similar to #634 but I think it offers a better approach. The commit adds two more methods for querying the port number, in addition to the existing SPDRP_ADDRESS method, which may not actually return the port number when using USB drivers other than the Microsoft driver. The first method uses SPDRP_LOCATION_INFORMATION, which may return a port in a format similar to "Port_#0002.Hub_#000D". The second method uses SPDRP_LOCATION_PATHS, which returns the device location in a format similar to "PCIROOT(B2)#PCI(0300)#PCI(0000)#USBROOT(0)#USB(1)#USB(2)#USBMI(3)", where the port number is the number within the last "#USB()" token. If both methods fail, SPDRP_ADDRESS is still used as a fallback. Closes #867 Signed-off-by: Nathan Hjelm --- diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index 877a2ab..e1e599c 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -1223,6 +1223,47 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d return LIBUSB_SUCCESS; } +static bool get_dev_port_number(HDEVINFO dev_info, SP_DEVINFO_DATA *dev_info_data, DWORD *port_nr) +{ + char buffer[MAX_KEY_LENGTH]; + DWORD size; + + // First try SPDRP_LOCATION_INFORMATION, which returns a REG_SZ. The string *may* have a format + // similar to "Port_#0002.Hub_#000D", in which case we can extract the port number. However, we + // cannot extract the port if the returned string does not follow this format. + if (pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_LOCATION_INFORMATION, + NULL, (PBYTE)buffer, sizeof(buffer), NULL)) { + // Check for the required format. + if (strncmp(buffer, "Port_#", 6) == 0) { + *port_nr = atoi(buffer + 6); + return true; + } + } + + // Next try SPDRP_LOCATION_PATHS, which returns a REG_MULTI_SZ (but we only examine the first + // string in it). Each path has a format similar to, + // "PCIROOT(B2)#PCI(0300)#PCI(0000)#USBROOT(0)#USB(1)#USB(2)#USBMI(3)", and the port number is + // the number within the last "USB(x)" token. + if (pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_LOCATION_PATHS, + NULL, (PBYTE)buffer, sizeof(buffer), NULL)) { + // Find the last "#USB(x)" substring + for (char *token = strrchr(buffer, '#'); token != NULL; token = strrchr(buffer, '#')) { + if (strncmp(token, "#USB(", 5) == 0) { + *port_nr = atoi(token + 5); + return true; + } + // Shorten the string and try again. + *token = '\0'; + } + } + + // Lastly, try SPDRP_ADDRESS, which returns a REG_DWORD. The address *may* be the port number, + // which is true for the Microsoft driver but may not be true for other drivers. However, we + // have no other options here but to accept what it returns. + return pSetupDiGetDeviceRegistryPropertyA(dev_info, dev_info_data, SPDRP_ADDRESS, + NULL, (PBYTE)port_nr, sizeof(*port_nr), &size) && (size == sizeof(*port_nr)); +} + static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id, uint8_t bus_number, DEVINST devinst) { @@ -1747,10 +1788,8 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_ r = enumerate_hcd_root_hub(ctx, dev_id, (uint8_t)(i + 1), dev_info_data.DevInst); break; case GEN_PASS: - // The SPDRP_ADDRESS for USB devices is the device port number on the hub port_nr = 0; - if (!pSetupDiGetDeviceRegistryPropertyA(*dev_info, &dev_info_data, SPDRP_ADDRESS, - NULL, (PBYTE)&port_nr, sizeof(port_nr), &size) || (size != sizeof(port_nr))) + if (!get_dev_port_number(*dev_info, &dev_info_data, &port_nr)) usbi_warn(ctx, "could not retrieve port number for device '%s': %s", dev_id, windows_error_str(0)); r = init_device(dev, parent_dev, (uint8_t)port_nr, dev_info_data.DevInst); if (r == LIBUSB_SUCCESS) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 53d05fe..6524fe2 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 11621 +#define LIBUSB_NANO 11622