diff --git a/config/hal.c b/config/hal.c index e0ff842ad..806102041 100644 --- a/config/hal.c +++ b/config/hal.c @@ -129,7 +129,7 @@ static void device_added(LibHalContext *hal_ctx, const char *udi) { char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL; - char *hal_tags; + char *hal_tags, *parent; InputOption *options = NULL, *tmpo = NULL; InputAttributes attrs = {0}; DeviceIntPtr dev = NULL; @@ -182,6 +182,12 @@ device_added(LibHalContext *hal_ctx, const char *udi) if (libhal_device_query_capability(hal_ctx, udi, "input.touchscreen", NULL)) attrs.flags |= ATTR_TOUCHSCREEN; + parent = get_prop_string(hal_ctx, udi, "info.parent"); + if (parent) { + attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id"); + free(parent); + } + options = calloc(sizeof(*options), 1); if (!options){ LogMessage(X_ERROR, "config/hal: couldn't allocate space for input options!\n"); @@ -384,6 +390,7 @@ unwind: free(attrs.product); free(attrs.vendor); free(attrs.device); + free(attrs.pnp_id); if (attrs.tags) { char **tag = attrs.tags; while (*tag) { diff --git a/config/udev.c b/config/udev.c index 5d001de5e..f7ed4b2de 100644 --- a/config/udev.c +++ b/config/udev.c @@ -99,6 +99,9 @@ device_added(struct udev_device *udev_device) name = udev_device_get_property_value(parent, "NAME"); LOG_PROPERTY(ppath, "NAME", name); } + + attrs.pnp_id = udev_device_get_sysattr_value(parent, "id"); + LOG_SYSATTR(ppath, "id", attrs.pnp_id); } if (!name) name = "(unnamed)"; diff --git a/dix/inpututils.c b/dix/inpututils.c index df2ace0bb..aa240dd74 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -357,6 +357,8 @@ DuplicateInputAttributes(InputAttributes *attrs) goto unwind; if (attrs->device && !(new_attr->device = strdup(attrs->device))) goto unwind; + if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id))) + goto unwind; new_attr->flags = attrs->flags; @@ -401,6 +403,7 @@ FreeInputAttributes(InputAttributes *attrs) free(attrs->product); free(attrs->vendor); free(attrs->device); + free(attrs->pnp_id); if ((tags = attrs->tags)) while(*tags) diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 0f6ccc1ab..5b0ec8f26 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -530,6 +530,16 @@ match_substring(const char *attr, const char *pattern) return (strstr(attr, pattern)) ? 0 : -1; } +#ifdef HAVE_FNMATCH_H +static int +match_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, 0); +} +#else +#define match_pattern match_substring +#endif + #ifdef HAVE_FNMATCH_H static int match_path_pattern(const char *attr, const char *pattern) @@ -590,6 +600,10 @@ InputClassMatches(const XF86ConfInputClassPtr iclass, if (!MatchAttrToken(HostOS(), iclass->match_os, strcasecmp)) return FALSE; + /* MatchPnPID pattern */ + if (!MatchAttrToken(attrs->pnp_id, iclass->match_pnpid, 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 50d4f3624..c17ecb941 100644 --- a/hw/xfree86/doc/man/xorg.conf.man.pre +++ b/hw/xfree86/doc/man/xorg.conf.man.pre @@ -1095,6 +1095,12 @@ string. This entry is only supported on platforms providing the system call. Multiple operating systems can be matched by separating arguments with a '|' character. .TP 7 +.BI "MatchPnPID \*q" matchpnp \*q +The device's Plug and Play (PnP) ID can be checked against the +.RI \*q matchpnp \*q +shell wildcard pattern. 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 20ebfb503..e5ef96cde 100644 --- a/hw/xfree86/parser/InputClass.c +++ b/hw/xfree86/parser/InputClass.c @@ -48,6 +48,7 @@ xf86ConfigSymTabRec InputClassTab[] = {MATCH_VENDOR, "matchvendor"}, {MATCH_DEVICE_PATH, "matchdevicepath"}, {MATCH_OS, "matchos"}, + {MATCH_PNPID, "matchpnpid"}, {MATCH_TAG, "matchtag"}, {MATCH_IS_KEYBOARD, "matchiskeyboard"}, {MATCH_IS_POINTER, "matchispointer"}, @@ -114,6 +115,11 @@ xf86parseInputClassSection(void) Error(QUOTE_MSG, "MatchOS"); ptr->match_os = xstrtokenize(val.str, TOKEN_SEP); break; + case MATCH_PNPID: + if (xf86getSubToken(&(ptr->comment)) != STRING) + Error(QUOTE_MSG, "MatchPnPID"); + ptr->match_pnpid = xstrtokenize(val.str, TOKEN_SEP); + break; case MATCH_TAG: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchTag"); @@ -231,6 +237,14 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr) *list); fprintf(cf, "\"\n"); } + if (ptr->match_pnpid) { + fprintf(cf, "\tMatchPnPID \""); + for (list = ptr->match_pnpid; *list; list++) + fprintf(cf, "%s%s", + list == ptr->match_pnpid ? "" : TOKEN_SEP, + *list); + fprintf(cf, "\"\n"); + } if (ptr->match_tag) { fprintf(cf, "\tMatchTag \""); for (list = ptr->match_tag; *list; list++) @@ -292,6 +306,11 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr) free(*list); free(ptr->match_os); } + if (ptr->match_pnpid) { + for (list = ptr->match_pnpid; *list; list++) + free(*list); + free(ptr->match_pnpid); + } 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 3623ca16d..87fc31c5f 100644 --- a/hw/xfree86/parser/xf86Parser.h +++ b/hw/xfree86/parser/xf86Parser.h @@ -347,6 +347,7 @@ typedef struct char **match_vendor; char **match_device; char **match_os; + char **match_pnpid; char **match_tag; xf86TriState is_keyboard; xf86TriState is_pointer; diff --git a/hw/xfree86/parser/xf86tokens.h b/hw/xfree86/parser/xf86tokens.h index fd13d6d95..aa33935d1 100644 --- a/hw/xfree86/parser/xf86tokens.h +++ b/hw/xfree86/parser/xf86tokens.h @@ -280,6 +280,7 @@ typedef enum { MATCH_VENDOR, MATCH_DEVICE_PATH, MATCH_OS, + MATCH_PNPID, MATCH_TAG, MATCH_IS_KEYBOARD, MATCH_IS_POINTER, diff --git a/include/input.h b/include/input.h index c68a28441..5969693e1 100644 --- a/include/input.h +++ b/include/input.h @@ -215,6 +215,7 @@ typedef struct _InputAttributes { char *product; char *vendor; char *device; + char *pnp_id; char **tags; /* null-terminated */ uint32_t flags; } InputAttributes; diff --git a/test/input.c b/test/input.c index 12771c59a..dd197dd64 100644 --- a/test/input.c +++ b/test/input.c @@ -801,6 +801,13 @@ static void cmp_attr_fields(InputAttributes *attr1, } else g_assert(attr2->device == NULL); + if (attr1->pnp_id != NULL) + { + g_assert(attr1->pnp_id != attr2->pnp_id); + g_assert(strcmp(attr1->pnp_id, attr2->pnp_id) == 0); + } else + g_assert(attr2->pnp_id == NULL); + tags1 = attr1->tags; tags2 = attr2->tags; @@ -866,6 +873,11 @@ static void dix_input_attributes(void) cmp_attr_fields(&orig, new); FreeInputAttributes(new); + orig.pnp_id = "PnPID"; + new = DuplicateInputAttributes(&orig); + cmp_attr_fields(&orig, new); + FreeInputAttributes(new); + orig.flags = 0xF0; new = DuplicateInputAttributes(&orig); cmp_attr_fields(&orig, new);