Skip to content

windows: fix winusb_get_device_string failing for strict USB devices#1796

Open
sonatique wants to merge 1 commit intolibusb:masterfrom
sonatique:fix-winusb-get-device-string-fail-issue-1794
Open

windows: fix winusb_get_device_string failing for strict USB devices#1796
sonatique wants to merge 1 commit intolibusb:masterfrom
sonatique:fix-winusb-get-device-string-fail-issue-1794

Conversation

@sonatique
Copy link
Copy Markdown
Member

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 #1794.

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.
@tormodvolden
Copy link
Copy Markdown
Contributor

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?

@mcuee mcuee added the windows label Apr 9, 2026
@mcuee
Copy link
Copy Markdown
Member

mcuee commented Apr 9, 2026

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.
https://github.com/libusb/libusb/pull/1532/changes#diff-bd7e9ed3e7d8a4a69d0664da0f6b8dbbff0b2c608d8dd63de02c379c98cf88b4R2201-R2222


/*
 * Backend implementation for libusb_get_device_string().
 * 
 * Windows makes getting the common device strings
 * very difficult.  DEVPKEY_Device_* does not have SerialNumber,
 * and it reports the driver manufacturer, not the device manufacturer.
 * 
 * We could parse the serial number from the DEVICE_ID string:
 * https://learn.microsoft.com/en-us/windows-hardware/drivers/install/device-instance-ids
 * https://learn.microsoft.com/en-us/windows-hardware/drivers/install/standard-usb-identifiers
 * 
 * However, using the dev_id for getting the serial number is 
 * definitely not recommended.
 *
 * The following implementation uses an IOCTL
 * to the parent USB hub to perform the USB control request for the
 * string descriptor without opening the USB device.
 * While we would rather not invoke USB IO, we currently lack a 
 * better option.
 */
static int winusb_get_device_string(libusb_device *dev,
	enum libusb_device_string_type string_type, char *data, int length)
{

@mcuee
Copy link
Copy Markdown
Member

mcuee commented Apr 9, 2026

Not able to recreate the issues for Issue #1794, but at least no regressions now.

PS C:\work\libusb\libusb> .\build\v145\x64\Release-Hotplug-MT\testlibusb.exe
Dev (bus 2, device 12): 1EA7 - 0064 speed: 12M
  Product:                   2.4G Mouse
Dev (bus 2, device 11): 25A7 - FA61 speed: 12M
  Manufacturer:              Compx
  Product:                   2.4G Receiver
Dev (bus 2, device 9): 046D - C548 speed: 12M
  Manufacturer:              Logitech
  Product:                   USB Receiver
Dev (bus 1, device 7): 05E3 - 0747 speed: 5G
Dev (bus 2, device 3): 0408 - 4044 speed: 480M
  Manufacturer:              Quanta
  Product:                   ACER QHD User Facing
Dev (bus 2, device 10): 16C0 - 05DC speed: 1.5M
  Manufacturer:              www.fischl.de
  Product:                   USBasp
Dev (bus 2, device 4): 0BDA - 0129 speed: 480M
Dev (bus 2, device 1): 248A - 5B2F speed: 12M
  Manufacturer:              SSCYPL
  Product:                   Wireless-Receiver
Dev (bus 2, device 2): 1C7A - 0584 speed: 12M
Dev (bus 2, device 5): 8087 - 0036 speed: 12M
Dev (bus 2, device 7): 03EB - 2106 speed: 12M
  Manufacturer:              ATMEL
  Product:                   STK600
Dev (bus 1, device 6): 0BDA - 8156 speed: 5G
Dev (bus 1, device 5): 05E3 - 0625 speed: 10G
Dev (bus 2, device 8): 05E3 - 0610 speed: 480M
Dev (bus 2, device 0): 8086 - 7E7D speed: 10G
Dev (bus 1, device 0): 8086 - 7EC0 speed: 10G
Dev (bus 2, device 6): 05E3 - 0610 speed: 480M
Dev (bus 1, device 8): 05E3 - 0616 speed: 5G

PS C:\work\libusb\libusb> cd ..
PS C:\work\libusb> cd .\libusb_pr1796\

PS C:\work\libusb\libusb_pr1796> .\build\v145\x64\Release-Hotplug-MT\testlibusb.exe
Dev (bus 2, device 12): 1EA7 - 0064 speed: 12M
  Product:                   2.4G Mouse
Dev (bus 2, device 11): 25A7 - FA61 speed: 12M
  Manufacturer:              Compx
  Product:                   2.4G Receiver
Dev (bus 2, device 9): 046D - C548 speed: 12M
  Manufacturer:              Logitech
  Product:                   USB Receiver
Dev (bus 1, device 7): 05E3 - 0747 speed: 5G
Dev (bus 2, device 3): 0408 - 4044 speed: 480M
  Manufacturer:              Quanta
  Product:                   ACER QHD User Facing
Dev (bus 2, device 10): 16C0 - 05DC speed: 1.5M
  Manufacturer:              www.fischl.de
  Product:                   USBasp
Dev (bus 2, device 4): 0BDA - 0129 speed: 480M
Dev (bus 2, device 1): 248A - 5B2F speed: 12M
  Manufacturer:              SSCYPL
  Product:                   Wireless-Receiver
Dev (bus 2, device 2): 1C7A - 0584 speed: 12M
Dev (bus 2, device 5): 8087 - 0036 speed: 12M
Dev (bus 2, device 7): 03EB - 2106 speed: 12M
  Manufacturer:              ATMEL
  Product:                   STK600
Dev (bus 1, device 6): 0BDA - 8156 speed: 5G
Dev (bus 1, device 5): 05E3 - 0625 speed: 10G
Dev (bus 2, device 8): 05E3 - 0610 speed: 480M
Dev (bus 2, device 0): 8086 - 7E7D speed: 10G
Dev (bus 1, device 0): 8086 - 7EC0 speed: 10G
Dev (bus 2, device 6): 05E3 - 0610 speed: 480M
Dev (bus 1, device 8): 05E3 - 0616 speed: 5G

@mcuee
Copy link
Copy Markdown
Member

mcuee commented Apr 9, 2026

Changing my Windows 11 system to Singapore Chinese -- still the same.

PS C:\work\libusb\libusb_pr1796> Get-Culture

LCID             Name             DisplayName
----             ----             -----------
4100             zh-SG            中文(新加坡)

PS C:\work\libusb\libusb_pr1796> .\build\v145\x64\Release-Hotplug-MT\testlibusb.exe
Dev (bus 2, device 12): 1EA7 - 0064 speed: 12M
  Product:                   2.4G Mouse
Dev (bus 2, device 11): 25A7 - FA61 speed: 12M
  Manufacturer:              Compx
  Product:                   2.4G Receiver
Dev (bus 2, device 9): 046D - C548 speed: 12M
  Manufacturer:              Logitech
  Product:                   USB Receiver
Dev (bus 1, device 7): 05E3 - 0747 speed: 5G
Dev (bus 2, device 3): 0408 - 4044 speed: 480M
  Manufacturer:              Quanta
  Product:                   ACER QHD User Facing
Dev (bus 2, device 10): 16C0 - 05DC speed: 1.5M
  Manufacturer:              www.fischl.de
  Product:                   USBasp
Dev (bus 2, device 4): 0BDA - 0129 speed: 480M
Dev (bus 2, device 1): 248A - 5B2F speed: 12M
  Manufacturer:              SSCYPL
  Product:                   Wireless-Receiver
Dev (bus 2, device 2): 1C7A - 0584 speed: 12M
Dev (bus 2, device 5): 8087 - 0036 speed: 12M
Dev (bus 2, device 7): 03EB - 2106 speed: 12M
  Manufacturer:              ATMEL
  Product:                   STK600
Dev (bus 1, device 6): 0BDA - 8156 speed: 5G
Dev (bus 1, device 5): 05E3 - 0625 speed: 10G
Dev (bus 2, device 8): 05E3 - 0610 speed: 480M
Dev (bus 2, device 0): 8086 - 7E7D speed: 10G
Dev (bus 1, device 0): 8086 - 7EC0 speed: 10G
Dev (bus 2, device 6): 05E3 - 0610 speed: 480M
Dev (bus 1, device 8): 05E3 - 0616 speed: 5G

PS C:\work\libusb\libusb_pr1796> cd ..

PS C:\work\libusb> cd libusb

PS C:\work\libusb\libusb> .\build\v145\x64\Release-Hotplug-MT\testlibusb.exe
Dev (bus 2, device 12): 1EA7 - 0064 speed: 12M
  Product:                   2.4G Mouse
Dev (bus 2, device 11): 25A7 - FA61 speed: 12M
  Manufacturer:              Compx
  Product:                   2.4G Receiver
Dev (bus 2, device 9): 046D - C548 speed: 12M
  Manufacturer:              Logitech
  Product:                   USB Receiver
Dev (bus 1, device 7): 05E3 - 0747 speed: 5G
Dev (bus 2, device 3): 0408 - 4044 speed: 480M
  Manufacturer:              Quanta
  Product:                   ACER QHD User Facing
Dev (bus 2, device 10): 16C0 - 05DC speed: 1.5M
  Manufacturer:              www.fischl.de
  Product:                   USBasp
Dev (bus 2, device 4): 0BDA - 0129 speed: 480M
Dev (bus 2, device 1): 248A - 5B2F speed: 12M
  Manufacturer:              SSCYPL
  Product:                   Wireless-Receiver
Dev (bus 2, device 2): 1C7A - 0584 speed: 12M
Dev (bus 2, device 5): 8087 - 0036 speed: 12M
Dev (bus 2, device 7): 03EB - 2106 speed: 12M
  Manufacturer:              ATMEL
  Product:                   STK600
Dev (bus 1, device 6): 0BDA - 8156 speed: 5G
Dev (bus 1, device 5): 05E3 - 0625 speed: 10G
Dev (bus 2, device 8): 05E3 - 0610 speed: 480M
Dev (bus 2, device 0): 8086 - 7E7D speed: 10G
Dev (bus 1, device 0): 8086 - 7EC0 speed: 10G
Dev (bus 2, device 6): 05E3 - 0610 speed: 480M
Dev (bus 1, device 8): 05E3 - 0616 speed: 5G

@mcuee
Copy link
Copy Markdown
Member

mcuee commented Apr 9, 2026

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.

Dev (bus 2, device 3): 0408 - 4044 speed: 480M
  Manufacturer:              Quanta
  Product:                   ACER QHD User Facing

@mcuee
Copy link
Copy Markdown
Member

mcuee commented Apr 9, 2026

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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

| 0? Is that a typo?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New libusb_get_device_string function does not work for all devices

4 participants