Windows: Rework WinUSB enumeration process to fix issues on Win8+
authorChris Dickens <christopher.a.dickens@gmail.com>
Fri, 5 Jan 2018 00:37:09 +0000 (16:37 -0800)
committerChris Dickens <christopher.a.dickens@gmail.com>
Fri, 5 Jan 2018 00:37:09 +0000 (16:37 -0800)
commit71a779d078be83cae91fb2aa972d1069daec38d4
tree7ee2f184b1ee8dd4ef074caf67e9d1dc50cc97fa
parent839235a0b4c55fe420da0c0a7cafbdfb44609820
Windows: Rework WinUSB enumeration process to fix issues on Win8+

As they sometimes do, Microsoft made changes to the way in which the
SetupAPI functions list the devices returned by SetupDiGetClassDevs().
In particular, composite devices started returning their interfaces
before the parent device, which caused some issues with the way the
enumeration logic was assigning things. For composite devices, it
appears that the first interface behaves much like the parent device in
some regards, so the library was creating a device specifically for the
first interface and then again when the actual parent device was
encountered. This caused composite devices to appear in the device list
twice, with the first instance being unusable for most operations.

This commit significantly changes the way in which the enumeration
process is done. Previously we would scan for HCDs, hubs, and generic
devices, in that order and in distinct passes (obtaining a new listing
of devices from SetupAPI). Now we will obtain a single snapshot at the
beginning of the enumeration process and iterate through this to scan
for each type of device.

With a single snapshot, we can be assured that the device instance
handle will not change between passes and thus we can use this as the
unique identifier. This completely removes the need to hash the device
instance ID to obtain a unique identifier and simplifies the process.

The previous enumeration process also created "dummy" libusb_device
instances for the HCDs that were never exposed to the user. This has
been removed in favor of identifying which of the encountered hubs are
actually root hubs.

Finally, the query for the port number has been moved to the GENeric
pass at the point where the devices are actually initialized. This query
operation has been relaxed to allow failure, since some virtual USB
devices don't properly implement this query in their drivers.

Closes #215, Closes #251, Closes #257, Closes #288

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
libusb/os/windows_winusb.c
libusb/os/windows_winusb.h
libusb/version_nano.h