xfree86: Match devices based on PnP ID

Serial input devices lack properties such as product or vendor name. This
makes matching InputClass sections difficult. Add a MatchPnPID entry to
test against the PnP ID of the device. The entry supports a shell pattern
match on platforms that support fnmatch(3). For example:

	MatchPnPID "WACf*"

A match type for non-path pattern matching, match_pattern, has been added.
The difference between this and match_path_pattern is the FNM_PATHNAME
flag in fnmatch(3).

Signed-off-by: Dan Nicholson <dbn.lists@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Dan Nicholson 2010-06-10 06:11:10 -07:00 committed by Peter Hutterer
parent d1b4beecbc
commit 645679c152
10 changed files with 68 additions and 1 deletions

View File

@ -129,7 +129,7 @@ static void
device_added(LibHalContext *hal_ctx, const char *udi) device_added(LibHalContext *hal_ctx, const char *udi)
{ {
char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL; char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL;
char *hal_tags; char *hal_tags, *parent;
InputOption *options = NULL, *tmpo = NULL; InputOption *options = NULL, *tmpo = NULL;
InputAttributes attrs = {0}; InputAttributes attrs = {0};
DeviceIntPtr dev = NULL; 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)) if (libhal_device_query_capability(hal_ctx, udi, "input.touchscreen", NULL))
attrs.flags |= ATTR_TOUCHSCREEN; 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); options = calloc(sizeof(*options), 1);
if (!options){ if (!options){
LogMessage(X_ERROR, "config/hal: couldn't allocate space for input options!\n"); LogMessage(X_ERROR, "config/hal: couldn't allocate space for input options!\n");
@ -384,6 +390,7 @@ unwind:
free(attrs.product); free(attrs.product);
free(attrs.vendor); free(attrs.vendor);
free(attrs.device); free(attrs.device);
free(attrs.pnp_id);
if (attrs.tags) { if (attrs.tags) {
char **tag = attrs.tags; char **tag = attrs.tags;
while (*tag) { while (*tag) {

View File

@ -99,6 +99,9 @@ device_added(struct udev_device *udev_device)
name = udev_device_get_property_value(parent, "NAME"); name = udev_device_get_property_value(parent, "NAME");
LOG_PROPERTY(ppath, "NAME", 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) if (!name)
name = "(unnamed)"; name = "(unnamed)";

View File

@ -357,6 +357,8 @@ DuplicateInputAttributes(InputAttributes *attrs)
goto unwind; goto unwind;
if (attrs->device && !(new_attr->device = strdup(attrs->device))) if (attrs->device && !(new_attr->device = strdup(attrs->device)))
goto unwind; goto unwind;
if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id)))
goto unwind;
new_attr->flags = attrs->flags; new_attr->flags = attrs->flags;
@ -401,6 +403,7 @@ FreeInputAttributes(InputAttributes *attrs)
free(attrs->product); free(attrs->product);
free(attrs->vendor); free(attrs->vendor);
free(attrs->device); free(attrs->device);
free(attrs->pnp_id);
if ((tags = attrs->tags)) if ((tags = attrs->tags))
while(*tags) while(*tags)

View File

@ -530,6 +530,16 @@ match_substring(const char *attr, const char *pattern)
return (strstr(attr, pattern)) ? 0 : -1; 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 #ifdef HAVE_FNMATCH_H
static int static int
match_path_pattern(const char *attr, const char *pattern) match_path_pattern(const char *attr, const char *pattern)
@ -590,6 +600,10 @@ InputClassMatches(const XF86ConfInputClassPtr iclass,
if (!MatchAttrToken(HostOS(), iclass->match_os, strcasecmp)) if (!MatchAttrToken(HostOS(), iclass->match_os, strcasecmp))
return FALSE; return FALSE;
/* MatchPnPID pattern */
if (!MatchAttrToken(attrs->pnp_id, iclass->match_pnpid, match_pattern))
return FALSE;
/* /*
* MatchTag string * MatchTag string
* See if any of the device's tags match any of the MatchTag tokens. * See if any of the device's tags match any of the MatchTag tokens.

View File

@ -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 system call. Multiple operating systems can be matched by separating arguments
with a '|' character. with a '|' character.
.TP 7 .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 .BI "MatchTag \*q" matchtag \*q
This entry can be used to check if tags assigned by the config backend This entry can be used to check if tags assigned by the config backend
matches the matches the

View File

@ -48,6 +48,7 @@ xf86ConfigSymTabRec InputClassTab[] =
{MATCH_VENDOR, "matchvendor"}, {MATCH_VENDOR, "matchvendor"},
{MATCH_DEVICE_PATH, "matchdevicepath"}, {MATCH_DEVICE_PATH, "matchdevicepath"},
{MATCH_OS, "matchos"}, {MATCH_OS, "matchos"},
{MATCH_PNPID, "matchpnpid"},
{MATCH_TAG, "matchtag"}, {MATCH_TAG, "matchtag"},
{MATCH_IS_KEYBOARD, "matchiskeyboard"}, {MATCH_IS_KEYBOARD, "matchiskeyboard"},
{MATCH_IS_POINTER, "matchispointer"}, {MATCH_IS_POINTER, "matchispointer"},
@ -114,6 +115,11 @@ xf86parseInputClassSection(void)
Error(QUOTE_MSG, "MatchOS"); Error(QUOTE_MSG, "MatchOS");
ptr->match_os = xstrtokenize(val.str, TOKEN_SEP); ptr->match_os = xstrtokenize(val.str, TOKEN_SEP);
break; 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: case MATCH_TAG:
if (xf86getSubToken(&(ptr->comment)) != STRING) if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchTag"); Error(QUOTE_MSG, "MatchTag");
@ -231,6 +237,14 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
*list); *list);
fprintf(cf, "\"\n"); 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) { if (ptr->match_tag) {
fprintf(cf, "\tMatchTag \""); fprintf(cf, "\tMatchTag \"");
for (list = ptr->match_tag; *list; list++) for (list = ptr->match_tag; *list; list++)
@ -292,6 +306,11 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr)
free(*list); free(*list);
free(ptr->match_os); 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) { if (ptr->match_tag) {
for (list = ptr->match_tag; *list; list++) for (list = ptr->match_tag; *list; list++)
free(*list); free(*list);

View File

@ -347,6 +347,7 @@ typedef struct
char **match_vendor; char **match_vendor;
char **match_device; char **match_device;
char **match_os; char **match_os;
char **match_pnpid;
char **match_tag; char **match_tag;
xf86TriState is_keyboard; xf86TriState is_keyboard;
xf86TriState is_pointer; xf86TriState is_pointer;

View File

@ -280,6 +280,7 @@ typedef enum {
MATCH_VENDOR, MATCH_VENDOR,
MATCH_DEVICE_PATH, MATCH_DEVICE_PATH,
MATCH_OS, MATCH_OS,
MATCH_PNPID,
MATCH_TAG, MATCH_TAG,
MATCH_IS_KEYBOARD, MATCH_IS_KEYBOARD,
MATCH_IS_POINTER, MATCH_IS_POINTER,

View File

@ -215,6 +215,7 @@ typedef struct _InputAttributes {
char *product; char *product;
char *vendor; char *vendor;
char *device; char *device;
char *pnp_id;
char **tags; /* null-terminated */ char **tags; /* null-terminated */
uint32_t flags; uint32_t flags;
} InputAttributes; } InputAttributes;

View File

@ -801,6 +801,13 @@ static void cmp_attr_fields(InputAttributes *attr1,
} else } else
g_assert(attr2->device == NULL); 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; tags1 = attr1->tags;
tags2 = attr2->tags; tags2 = attr2->tags;
@ -866,6 +873,11 @@ static void dix_input_attributes(void)
cmp_attr_fields(&orig, new); cmp_attr_fields(&orig, new);
FreeInputAttributes(new); FreeInputAttributes(new);
orig.pnp_id = "PnPID";
new = DuplicateInputAttributes(&orig);
cmp_attr_fields(&orig, new);
FreeInputAttributes(new);
orig.flags = 0xF0; orig.flags = 0xF0;
new = DuplicateInputAttributes(&orig); new = DuplicateInputAttributes(&orig);
cmp_attr_fields(&orig, new); cmp_attr_fields(&orig, new);