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:
parent
d1b4beecbc
commit
645679c152
|
@ -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) {
|
||||
|
|
|
@ -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)";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -280,6 +280,7 @@ typedef enum {
|
|||
MATCH_VENDOR,
|
||||
MATCH_DEVICE_PATH,
|
||||
MATCH_OS,
|
||||
MATCH_PNPID,
|
||||
MATCH_TAG,
|
||||
MATCH_IS_KEYBOARD,
|
||||
MATCH_IS_POINTER,
|
||||
|
|
|
@ -215,6 +215,7 @@ typedef struct _InputAttributes {
|
|||
char *product;
|
||||
char *vendor;
|
||||
char *device;
|
||||
char *pnp_id;
|
||||
char **tags; /* null-terminated */
|
||||
uint32_t flags;
|
||||
} InputAttributes;
|
||||
|
|
12
test/input.c
12
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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user