summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-10-06 17:51:07 +0100
committerPete Batard <pbatard@gmail.com>2010-10-06 17:51:07 +0100
commit228b4bd59a35ea771b8675343defdc6656079c88 (patch)
treedb0644bcb0e89b7d9fac003abe9bfa61310cf910
parentcd0d837682dcae9fd7a0efcbf631c81ddd5f2550 (diff)
downloadlibusb-228b4bd59a35ea771b8675343defdc6656079c88.tar.gz
ignore non USB grandparents on HID interface detection
* not all HID interfaces belong to USB devices * issue reported by Xiaofan Chen
-rw-r--r--libusb/os/windows_usb.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 4c91bca..4ff4d6a 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -387,7 +387,7 @@ err_exit:
/*
* Hash a string (Nokia suggestion)
- * TODO: add collision detection!
+ * TODO: add collision detection (also flag 0x00000000 as reserved)
*/
static inline unsigned long hash(const char* sz)
{
@@ -400,7 +400,6 @@ static inline unsigned long hash(const char* sz)
/*
* Returns the Device ID path of a device's parent
- * The returned string needs to be freed by the caller
*/
static unsigned long get_parent_session_id(DWORD devinst)
{
@@ -426,15 +425,15 @@ static unsigned long get_parent_session_id(DWORD devinst)
/*
* Returns the Device ID path of a device's grandparent
- * The returned string needs to be freed by the caller
*/
-static unsigned long get_grandparent_session_id(DWORD devinst)
+static unsigned long get_grandparent_session_id(DWORD devinst, bool* non_usb_gp)
{
DWORD parent_devinst, grandparent_devinst;
unsigned long session_id = 0;
char* sanitized_path = NULL;
char path[MAX_PATH_LENGTH];
+ *non_usb_gp = false;
if (CM_Get_Parent(&parent_devinst, devinst, 0) != CR_SUCCESS) {
return 0;
}
@@ -444,6 +443,12 @@ static unsigned long get_grandparent_session_id(DWORD devinst)
if (CM_Get_Device_IDA(grandparent_devinst, path, MAX_PATH_LENGTH, 0) != CR_SUCCESS) {
return 0;
}
+ // If the grandparent is not USB (as can be the case for HID), flag it
+ if ((path[0] != 'U') && (path[1] != 'S') && (path[2] != 'B')) {
+ usbi_dbg("detected non USB grandparent '%s'", path);
+ *non_usb_gp = true;
+ return 0;
+ }
// TODO: try without sanitizing
sanitized_path = sanitize_path(path);
if (sanitized_path == NULL) {
@@ -1124,6 +1129,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
GUID* if_guid;
LONG s;
uint8_t api;
+ bool non_usb_hid_parent;
// Keep a chained list of newly allocated devs to unref
// TODO: use a perf friendly realloc instead of a chained list
struct unref_dev {
@@ -1259,7 +1265,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
if (s == ERROR_SUCCESS) {
if (nb_guids >= MAX_ENUM_GUIDS) {
// If this assert is ever reported, grow a GUID table dynamically
- usbi_err(ctx, "program assertion error: too many GUIDs");
+ usbi_err(ctx, "program assertion failed: too many GUIDs");
LOOP_BREAK(LIBUSB_ERROR_OVERFLOW);
}
if_guid = calloc(1, sizeof(GUID));
@@ -1302,8 +1308,12 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
parent_dev = usbi_get_device_by_session_id(ctx, session_id);
// Composite HID devices have double indirection => Check grandparent
if (pass == HID_PASS) {
- session_id = get_grandparent_session_id(dev_info_data.DevInst);
+ session_id = get_grandparent_session_id(dev_info_data.DevInst, &non_usb_hid_parent);
if (session_id == 0) {
+ if (non_usb_hid_parent) {
+ usbi_dbg("skipping non USB HID interface '%s'", dev_id_path);
+ continue;
+ }
usbi_err(ctx, "program assertion failed: no grandparent for '%s'", dev_id_path);
LOOP_BREAK(LIBUSB_ERROR_NO_DEVICE);
}