diff options
author | Chris Dickens <christopher.a.dickens@gmail.com> | 2018-01-04 16:37:09 -0800 |
---|---|---|
committer | Chris Dickens <christopher.a.dickens@gmail.com> | 2018-01-04 16:37:09 -0800 |
commit | 71a779d078be83cae91fb2aa972d1069daec38d4 (patch) | |
tree | 7ee2f184b1ee8dd4ef074caf67e9d1dc50cc97fa /libusb/os/windows_winusb.h | |
parent | 839235a0b4c55fe420da0c0a7cafbdfb44609820 (diff) | |
download | libusb-71a779d078be83cae91fb2aa972d1069daec38d4.tar.gz |
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>
Diffstat (limited to 'libusb/os/windows_winusb.h')
-rw-r--r-- | libusb/os/windows_winusb.h | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h index c58847a..b0e834a 100644 --- a/libusb/os/windows_winusb.h +++ b/libusb/os/windows_winusb.h @@ -196,14 +196,17 @@ struct hid_device_priv { }; struct windows_device_priv { - uint8_t depth; // distance to HCD + bool initialized; + bool root_hub; uint8_t active_config; - struct windows_usb_api_backend const *apib; + uint8_t depth; + const struct windows_usb_api_backend *apib; + char *dev_id; char *path; // device interface path int sub_api; // for WinUSB-like APIs struct { char *path; // each interface needs a device interface path, - struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support), + const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support), int sub_api; int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS) uint8_t *endpoint; @@ -212,7 +215,7 @@ struct windows_device_priv { } usb_interface[USB_MAXINTERFACES]; struct hid_device_priv *hid; USB_DEVICE_DESCRIPTOR dev_descriptor; - unsigned char **config_descriptor; // list of pointers to the cached config descriptors + PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors }; static inline struct windows_device_priv *_device_priv(struct libusb_device *dev) @@ -240,6 +243,7 @@ static inline void windows_device_priv_release(struct libusb_device *dev) struct windows_device_priv *p = _device_priv(dev); int i; + free(p->dev_id); free(p->path); if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) { for (i = 0; i < dev->num_configurations; i++) @@ -296,11 +300,10 @@ typedef RETURN_TYPE CONFIGRET; #define CR_SUCCESS 0x00000000 -/* Cfgmgr32.dll interface */ +/* Cfgmgr32 dependencies */ DLL_DECLARE_HANDLE(Cfgmgr32); DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Parent, (PDEVINST, DEVINST, ULONG)); DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Child, (PDEVINST, DEVINST, ULONG)); -DLL_DECLARE_FUNC(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG)); /* AdvAPI32 dependencies */ DLL_DECLARE_HANDLE(AdvAPI32); @@ -322,6 +325,8 @@ DLL_DECLARE_FUNC_PREFIXED(WINAPI, HDEVINFO, p, SetupDiGetClassDevsA, (LPCGUID, P DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInfo, (HDEVINFO, DWORD, PSP_DEVINFO_DATA)); DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiEnumDeviceInterfaces, (HDEVINFO, PSP_DEVINFO_DATA, LPCGUID, DWORD, PSP_DEVICE_INTERFACE_DATA)); +DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInstanceIdA, (HDEVINFO, PSP_DEVINFO_DATA, + PCSTR, DWORD, PDWORD)); DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceInterfaceDetailA, (HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA)); DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, SetupDiGetDeviceRegistryPropertyA, (HDEVINFO, |