summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-08-19 16:18:25 +0100
committerPete Batard <pbatard@gmail.com>2010-08-19 16:18:25 +0100
commitd981c216327a227665b58ed9d33da5f391c58724 (patch)
treee44cb244c1de297d2aa63ee3348b5635f13910d6
parente68165152f69e5a127dadee657ae467958e8bc50 (diff)
downloadlibusb-d981c216327a227665b58ed9d33da5f391c58724.tar.gz
added full support for filter drivers
* precedence is driver > upper filter > lower filter and defined in struct driver_lookup lookup from set_device_paths()
-rw-r--r--libusb/os/windows_usb.c91
-rw-r--r--libusb/os/windows_usb.h10
2 files changed, 66 insertions, 35 deletions
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 93da268..9311dbf 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -423,11 +423,20 @@ static int windows_assign_endpoints(struct libusb_device *dev, int iface, int al
bool is_api_driver(char* driver, uint8_t api)
{
uint8_t i;
- for (i=0; i<usb_api_backend[api].nb_driver_names; i++) {
- if (safe_strcmp(driver, usb_api_backend[api].driver_name_list[i]) == 0) {
- return true;
+ const char sep_str[2] = {LIST_SEPARATOR, 0};
+ char *tok, *tmp_str = _strdup(driver);
+ if (tmp_str == NULL) return false;
+ tok = strtok(tmp_str, sep_str);
+ while (tok != NULL) {
+ for (i=0; i<usb_api_backend[api].nb_driver_names; i++) {
+ if (safe_strcmp(tok, usb_api_backend[api].driver_name_list[i]) == 0) {
+ free(tmp_str);
+ return true;
+ }
}
+ tok = strtok(NULL, sep_str);
}
+ free (tmp_str);
return false;
}
@@ -1407,10 +1416,15 @@ static int set_hid_device(struct libusb_context *ctx, struct windows_device_priv
*/
static int set_device_paths(struct libusb_context *ctx, struct discovered_devs *discdevs)
{
+ // Precedence for filter drivers vs driver is in the order of this array
+ struct driver_lookup lookup[3] = {
+ {"\0\0", SPDRP_SERVICE, "driver"},
+ {"\0\0", SPDRP_UPPERFILTERS, "upper filter driver"},
+ {"\0\0", SPDRP_LOWERFILTERS, "lower filter driver"}
+ };
struct windows_device_priv *priv;
struct windows_device_priv *parent_priv;
char path[MAX_PATH_LENGTH];
- char driver[MAX_KEY_LENGTH], filter_driver[MAX_KEY_LENGTH];
char *sanitized_path = NULL;
HDEVINFO dev_info;
SP_DEVICE_INTERFACE_DETAIL_DATA *dev_interface_details = NULL;
@@ -1418,8 +1432,8 @@ static int set_device_paths(struct libusb_context *ctx, struct discovered_devs *
DEVINST parent_devinst;
GUID guid;
DWORD size, reg_type, install_state, port_nr;
- int r = LIBUSB_SUCCESS;
- unsigned i, j, k;
+ int r = LIBUSB_SUCCESS;
+ unsigned i, j, k, l;
uint8_t api;
bool found;
@@ -1500,37 +1514,42 @@ static int set_device_paths(struct libusb_context *ctx, struct discovered_devs *
usbi_dbg("path (%d:%d): %s", discdevs->devices[j]->bus_number,
discdevs->devices[j]->device_address, priv->path);
- // Check the service name to know what kind of device we have.
- // The service name is really the driver name without ".sys" ("WinUSB", "HidUsb", ...)
- // It tells us if we can use WinUSB, if we have a composite device, and the API to use
- if(SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_SERVICE,
- &reg_type, (BYTE*)driver, MAX_KEY_LENGTH, &size)) {
- upperize(driver);
- usbi_dbg("driver: %s", driver);
- found = true;
- } else {
- driver[0] = 0;
- }
-
- // The device might also have a filter driver we can use
- if(SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_LOWERFILTERS,
- &reg_type, (BYTE*)filter_driver, MAX_KEY_LENGTH, &size)) {
- upperize(filter_driver);
- usbi_dbg("filter driver: %s", filter_driver);
- found = true;
- } else {
- filter_driver[0] = 0;
+ // Check the service & filter names to know the API we should use
+ for (k=0; k<3; k++) {
+ if (SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, lookup[k].reg_prop,
+ &reg_type, (BYTE*)lookup[k].list, MAX_KEY_LENGTH, &size)) {
+ // Turn the REG_SZ SPDRP_SERVICE into REG_MULTI_SZ
+ if (lookup[k].reg_prop == SPDRP_SERVICE) {
+ // our buffers are MAX_KEY_LENGTH+1 so we can overflow if needed
+ lookup[k].list[safe_strlen(lookup[k].list)+1] = 0;
+ }
+ // MULTI_SZ is a pain to work with. Turn it into something much more manageable
+ // NB: none of the driver names we check against contain LIST_SEPARATOR,
+ // (currently ';'), so even if an unsuported one does, it's not an issue
+ for (l=0; (lookup[k].list[l] != 0) || (lookup[k].list[l+1] != 0); l++) {
+ if (lookup[k].list[l] == 0) {
+ lookup[k].list[l] = LIST_SEPARATOR;
+ }
+ }
+ upperize(lookup[k].list);
+ usbi_dbg("%s(s): %s", lookup[k].designation, lookup[k].list);
+ found = true;
+ } else {
+ if (GetLastError() != ERROR_INVALID_DATA) {
+ usbi_dbg("could not access %s: %s", lookup[k].designation, windows_error_str(0));
+ }
+ lookup[k].list[0] = 0;
+ }
}
- for (api = 0; api<USB_API_MAX; api++) {
- // For now, driver has precedence over filter driver
- if ((driver[0] != 0) && (is_api_driver(driver, api))) {
- usbi_dbg("matched device using driver");
- } else if ((filter_driver[0] != 0) && (is_api_driver(filter_driver, api))) {
- usbi_dbg("matched device using filter driver");
- } else {
- continue;
+ for (api=0; api<USB_API_MAX; api++) {
+ for (k=0; k<3; k++) {
+ if (is_api_driver(lookup[k].list, api)) {
+ usbi_dbg("matched %s name against %s", lookup[k].designation, usb_api_backend[api].designation);
+ break;
+ }
}
+ if (k >= 3) continue;
priv->apib = &usb_api_backend[api];
switch(api) {
case USB_API_COMPOSITE:
@@ -2327,6 +2346,7 @@ const char* hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"};
const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
{
USB_API_UNSUPPORTED,
+ "Unsupported API",
&CLASS_GUID_UNSUPPORTED,
NULL,
0,
@@ -2347,6 +2367,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
unsupported_copy_transfer_data,
}, {
USB_API_COMPOSITE,
+ "Composite API",
&CLASS_GUID_COMPOSITE,
composite_driver_names,
sizeof(composite_driver_names)/sizeof(composite_driver_names[0]),
@@ -2367,6 +2388,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
composite_copy_transfer_data,
}, {
USB_API_WINUSB,
+ "WinUSB API",
&CLASS_GUID_LIBUSB_WINUSB,
winusb_driver_names,
sizeof(winusb_driver_names)/sizeof(winusb_driver_names[0]),
@@ -2387,6 +2409,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
winusb_copy_transfer_data,
}, {
USB_API_HID,
+ "HID API",
&CLASS_GUID_HID,
hid_driver_names,
sizeof(hid_driver_names)/sizeof(hid_driver_names[0]),
diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h
index 2353488..fce75af 100644
--- a/libusb/os/windows_usb.h
+++ b/libusb/os/windows_usb.h
@@ -95,8 +95,9 @@ inline void upperize(char* str) {
#define MAX_PATH_LENGTH 128
#define MAX_KEY_LENGTH 256
#define MAX_TIMER_SEMAPHORES 128
-#define TIMER_REQUEST_RETRY_MS 100
+#define TIMER_REQUEST_RETRY_MS 100
#define ERR_BUFFER_SIZE 256
+#define LIST_SEPARATOR ';'
// Handle code for HID interface that have been claimed ("dibs")
#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5)
@@ -129,6 +130,7 @@ const GUID CLASS_GUID_COMPOSITE = { 0x36FC9E60, 0xC465, 0x11cF, {0x80, 0x56,
struct windows_usb_api_backend {
const uint8_t id;
+ const char* designation;
const GUID *class_guid; // The Class GUID (for fallback in case the driver name cannot be read)
const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
const uint8_t nb_driver_names;
@@ -312,6 +314,12 @@ struct windows_transfer_priv {
size_t hid_expected_size;
};
+// used to match a device driver (including filter drivers) against a supported API
+struct driver_lookup {
+ char list[MAX_KEY_LENGTH+1];// REG_MULTI_SZ list of services (driver) names
+ const DWORD reg_prop; // SPDRP registry key to use to retreive list
+ const char* designation; // internal designation (for debug output)
+};
/*
* API macros - from libusb-win32 1.x