windows: fix winusb_get_device_string failing for strict USB devices#1796
windows: fix winusb_get_device_string failing for strict USB devices#1796sonatique wants to merge 1 commit intolibusb:masterfrom
Conversation
Two bugs in winusb_get_device_string caused libusb_get_device_string to return empty strings instead of actual device strings on Windows: 1. The function used wIndex=0 (invalid LANGID) when requesting string descriptors via IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION. While some devices tolerate LANGID 0, strict USB devices correctly STALL the request (Windows error 31). Fix: first fetch string descriptor 0 to get the device's language table (USB 2.0 section 9.6.7), then use the primary LANGID for actual string requests. The LANGID is cached per device to avoid redundant IOCTLs. 2. On IOCTL failure, the function returned 0 instead of a negative LIBUSB_ERROR code. The caller in libusb_get_device_string only checks for rv < 0, so 0 was treated as success: an empty string was permanently cached, and subsequent calls returned 1 (empty string + null terminator) without ever retrying. Fix: return LIBUSB_ERROR_IO on both error paths. Closes libusb#1794.
|
I thought libusb_get_device_string() would not create I/O and use cached values from the OS, but here I see a DeviceIoControl() call. Does this call create I/O? Or is libusb_get_device_string() not I/O free on Windows anyway? |
As per the comments in PR #1532, no better ways for Windows now. From PR #1532. |
|
Not able to recreate the issues for Issue #1794, but at least no regressions now. |
|
Changing my Windows 11 system to Singapore Chinese -- still the same. |
|
BTW, another interesting finding. For thebuilt-in USB devices of the Acer Swift Go 14 laptop (2024 model) like the WebCAM, USBview and USBTreeView will not be able to get the string descriptors since they are in Low Power mode. But all the different versions of libusb testlibusb example will be able to get the string descriptors. Looks like libusb Windows will wake up the device and get the string descriptors. I have tested libusb git, this PR, 1.0.29 release and 1.0.28 release. |
|
I will check the behavior of the dual boot Ubuntu 26.04 beta version as well tomorrow. |
| sd.req.ConnectionIndex = (ULONG)dev->port_number; | ||
| sd.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN; | ||
| sd.req.SetupPacket.bRequest = LIBUSB_REQUEST_GET_DESCRIPTOR; | ||
| sd.req.SetupPacket.wValue = (LIBUSB_DT_STRING << 8) | 0; |
Two bugs in winusb_get_device_string caused libusb_get_device_string to return empty strings instead of actual device strings on Windows:
The function used wIndex=0 (invalid LANGID) when requesting string descriptors via IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION. While some devices tolerate LANGID 0, strict USB devices correctly STALL the request (Windows error 31). Fix: first fetch string descriptor 0 to get the device's language table (USB 2.0 section 9.6.7), then use the primary LANGID for actual string requests. The LANGID is cached per device to avoid redundant IOCTLs.
On IOCTL failure, the function returned 0 instead of a negative LIBUSB_ERROR code. The caller in libusb_get_device_string only checks for rv < 0, so 0 was treated as success: an empty string was permanently cached, and subsequent calls returned 1 (empty string + null terminator) without ever retrying. Fix: return LIBUSB_ERROR_IO on both error paths.
Closes #1794.