diff --git a/config/hal.c b/config/hal.c index 806102041..8f9aeb8d3 100644 --- a/config/hal.c +++ b/config/hal.c @@ -184,7 +184,24 @@ device_added(LibHalContext *hal_ctx, const char *udi) parent = get_prop_string(hal_ctx, udi, "info.parent"); if (parent) { + int usb_vendor, usb_product; + attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id"); + + /* construct USB ID in lowercase - "0000:ffff" */ + usb_vendor = libhal_device_get_property_int(hal_ctx, parent, + "usb.vendor_id", NULL); + LogMessageVerb(X_INFO, 10, + "config/hal: getting usb.vendor_id on %s " + "returned %04x\n", parent, usb_vendor); + usb_product = libhal_device_get_property_int(hal_ctx, parent, + "usb.product_id", NULL); + LogMessageVerb(X_INFO, 10, + "config/hal: getting usb.product_id on %s " + "returned %04x\n", parent, usb_product); + if (usb_vendor && usb_product) + attrs.usb_id = Xprintf("%04x:%04x", usb_vendor, usb_product); + free(parent); } @@ -391,6 +408,7 @@ unwind: free(attrs.vendor); free(attrs.device); free(attrs.pnp_id); + free(attrs.usb_id); if (attrs.tags) { char **tag = attrs.tags; while (*tag) { diff --git a/config/udev.c b/config/udev.c index f7ed4b2de..16c462455 100644 --- a/config/udev.c +++ b/config/udev.c @@ -28,6 +28,7 @@ #endif #include +#include #include "input.h" #include "inputstr.h" @@ -57,6 +58,7 @@ device_added(struct udev_device *udev_device) char *config_info = NULL; const char *syspath; const char *tags_prop; + const char *usb_vendor = NULL, *usb_model = NULL; const char *key, *value, *tmp; InputOption *options = NULL, *tmpo; InputAttributes attrs = {}; @@ -150,6 +152,12 @@ device_added(struct udev_device *udev_device) } else if (!strcmp(key, "ID_VENDOR")) { LOG_PROPERTY(path, key, value); attrs.vendor = value; + } else if (!strcmp(key, "ID_VENDOR_ID")) { + LOG_PROPERTY(path, key, value); + usb_vendor = value; + } else if (!strcmp(key, "ID_VENDOR_MODEL")) { + LOG_PROPERTY(path, key, value); + usb_model = value; } else if (!strcmp(key, "ID_INPUT_KEY")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_KEYBOARD; @@ -170,6 +178,17 @@ device_added(struct udev_device *udev_device) attrs.flags |= ATTR_TOUCHSCREEN; } } + + /* construct USB ID in lowercase hex - "0000:ffff" */ + if (usb_vendor && usb_model) { + attrs.usb_id = Xprintf("%s:%s", usb_vendor, usb_model); + if (attrs.usb_id) { + char *cur; + for (cur = attrs.usb_id; *cur; cur++) + *cur = tolower(*cur); + } + } + LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n", name, path); rc = NewInputDeviceRequest(options, &attrs, &dev); @@ -190,6 +209,7 @@ device_added(struct udev_device *udev_device) free(tmpo); } + free(attrs.usb_id); if (attrs.tags) { char **tag = attrs.tags; while (*tag) { diff --git a/dix/inpututils.c b/dix/inpututils.c index aa240dd74..8ec80b5e8 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -359,6 +359,8 @@ DuplicateInputAttributes(InputAttributes *attrs) goto unwind; if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id))) goto unwind; + if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id))) + goto unwind; new_attr->flags = attrs->flags; @@ -404,6 +406,7 @@ FreeInputAttributes(InputAttributes *attrs) free(attrs->vendor); free(attrs->device); free(attrs->pnp_id); + free(attrs->usb_id); if ((tags = attrs->tags)) while(*tags) diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 5b0ec8f26..421803962 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -604,6 +604,10 @@ InputClassMatches(const XF86ConfInputClassPtr iclass, if (!MatchAttrToken(attrs->pnp_id, iclass->match_pnpid, match_pattern)) return FALSE; + /* MatchUSBID pattern */ + if (!MatchAttrToken(attrs->usb_id, iclass->match_usbid, match_pattern)) + return FALSE; + /* * MatchTag string * See if any of the device's tags match any of the MatchTag tokens. diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre index c17ecb941..63dbb68b1 100644 --- a/hw/xfree86/doc/man/xorg.conf.man.pre +++ b/hw/xfree86/doc/man/xorg.conf.man.pre @@ -1101,6 +1101,15 @@ The device's Plug and Play (PnP) ID can be checked against the shell wildcard pattern. Multiple IDs can be matched by separating arguments with a '|' character. .TP 7 +.BI "MatchUSBID \*q" matchusb \*q +The device's USB ID can be checked against the +.RI \*q matchusb \*q +shell wildcard pattern. The ID is constructed as lowercase hexadecimal numbers +separated by a ':'. This is the same format as the +.BR lsusb (8) +program. Multiple IDs can be matched by separating arguments with a '|' +character. +.TP 7 .BI "MatchTag \*q" matchtag \*q This entry can be used to check if tags assigned by the config backend matches the diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c index e5ef96cde..bdcfba486 100644 --- a/hw/xfree86/parser/InputClass.c +++ b/hw/xfree86/parser/InputClass.c @@ -49,6 +49,7 @@ xf86ConfigSymTabRec InputClassTab[] = {MATCH_DEVICE_PATH, "matchdevicepath"}, {MATCH_OS, "matchos"}, {MATCH_PNPID, "matchpnpid"}, + {MATCH_USBID, "matchusbid"}, {MATCH_TAG, "matchtag"}, {MATCH_IS_KEYBOARD, "matchiskeyboard"}, {MATCH_IS_POINTER, "matchispointer"}, @@ -120,6 +121,11 @@ xf86parseInputClassSection(void) Error(QUOTE_MSG, "MatchPnPID"); ptr->match_pnpid = xstrtokenize(val.str, TOKEN_SEP); break; + case MATCH_USBID: + if (xf86getSubToken(&(ptr->comment)) != STRING) + Error(QUOTE_MSG, "MatchUSBID"); + ptr->match_usbid = xstrtokenize(val.str, TOKEN_SEP); + break; case MATCH_TAG: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchTag"); @@ -245,6 +251,14 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr) *list); fprintf(cf, "\"\n"); } + if (ptr->match_usbid) { + fprintf(cf, "\tMatchUSBID \""); + for (list = ptr->match_usbid; *list; list++) + fprintf(cf, "%s%s", + list == ptr->match_usbid ? "" : TOKEN_SEP, + *list); + fprintf(cf, "\"\n"); + } if (ptr->match_tag) { fprintf(cf, "\tMatchTag \""); for (list = ptr->match_tag; *list; list++) @@ -311,6 +325,11 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr) free(*list); free(ptr->match_pnpid); } + if (ptr->match_usbid) { + for (list = ptr->match_usbid; *list; list++) + free(*list); + free(ptr->match_usbid); + } if (ptr->match_tag) { for (list = ptr->match_tag; *list; list++) free(*list); diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h index 87fc31c5f..a86462f93 100644 --- a/hw/xfree86/parser/xf86Parser.h +++ b/hw/xfree86/parser/xf86Parser.h @@ -348,6 +348,7 @@ typedef struct char **match_device; char **match_os; char **match_pnpid; + char **match_usbid; char **match_tag; xf86TriState is_keyboard; xf86TriState is_pointer; diff --git a/hw/xfree86/parser/xf86tokens.h b/hw/xfree86/parser/xf86tokens.h index aa33935d1..23460dd73 100644 --- a/hw/xfree86/parser/xf86tokens.h +++ b/hw/xfree86/parser/xf86tokens.h @@ -281,6 +281,7 @@ typedef enum { MATCH_DEVICE_PATH, MATCH_OS, MATCH_PNPID, + MATCH_USBID, MATCH_TAG, MATCH_IS_KEYBOARD, MATCH_IS_POINTER, diff --git a/include/input.h b/include/input.h index 5969693e1..0a08ea425 100644 --- a/include/input.h +++ b/include/input.h @@ -216,6 +216,7 @@ typedef struct _InputAttributes { char *vendor; char *device; char *pnp_id; + char *usb_id; char **tags; /* null-terminated */ uint32_t flags; } InputAttributes; diff --git a/test/input.c b/test/input.c index dd197dd64..b90d3b4fd 100644 --- a/test/input.c +++ b/test/input.c @@ -808,6 +808,13 @@ static void cmp_attr_fields(InputAttributes *attr1, } else g_assert(attr2->pnp_id == NULL); + if (attr1->usb_id != NULL) + { + g_assert(attr1->usb_id != attr2->usb_id); + g_assert(strcmp(attr1->usb_id, attr2->usb_id) == 0); + } else + g_assert(attr2->usb_id == NULL); + tags1 = attr1->tags; tags2 = attr2->tags; @@ -878,6 +885,11 @@ static void dix_input_attributes(void) cmp_attr_fields(&orig, new); FreeInputAttributes(new); + orig.usb_id = "USBID"; + new = DuplicateInputAttributes(&orig); + cmp_attr_fields(&orig, new); + FreeInputAttributes(new); + orig.flags = 0xF0; new = DuplicateInputAttributes(&orig); cmp_attr_fields(&orig, new);