summaryrefslogtreecommitdiff
path: root/libusb/os/windows_winusb.h
diff options
context:
space:
mode:
authorChris Dickens <christopher.a.dickens@gmail.com>2018-01-04 16:37:09 -0800
committerChris Dickens <christopher.a.dickens@gmail.com>2018-01-04 16:37:09 -0800
commit71a779d078be83cae91fb2aa972d1069daec38d4 (patch)
tree7ee2f184b1ee8dd4ef074caf67e9d1dc50cc97fa /libusb/os/windows_winusb.h
parent839235a0b4c55fe420da0c0a7cafbdfb44609820 (diff)
downloadlibusb-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.h17
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,