xfree86: Match devices based on USB ID
Sometimes the vendor and product names aren't specific enough to target a USB device, so expose the numeric codes in the ID. A MatchUSBID entry has been added that supports shell pattern matching when fnmatch(3) is available. For example: MatchUSBID "046d:*" The IDs are stored in lowercase hex separated by a ':' like "lsusb" or "lspci -n". 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
645679c152
commit
87a1507da7
18
config/hal.c
18
config/hal.c
|
@ -184,7 +184,24 @@ device_added(LibHalContext *hal_ctx, const char *udi)
|
||||||
|
|
||||||
parent = get_prop_string(hal_ctx, udi, "info.parent");
|
parent = get_prop_string(hal_ctx, udi, "info.parent");
|
||||||
if (parent) {
|
if (parent) {
|
||||||
|
int usb_vendor, usb_product;
|
||||||
|
|
||||||
attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id");
|
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);
|
free(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,6 +408,7 @@ unwind:
|
||||||
free(attrs.vendor);
|
free(attrs.vendor);
|
||||||
free(attrs.device);
|
free(attrs.device);
|
||||||
free(attrs.pnp_id);
|
free(attrs.pnp_id);
|
||||||
|
free(attrs.usb_id);
|
||||||
if (attrs.tags) {
|
if (attrs.tags) {
|
||||||
char **tag = attrs.tags;
|
char **tag = attrs.tags;
|
||||||
while (*tag) {
|
while (*tag) {
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "inputstr.h"
|
#include "inputstr.h"
|
||||||
|
@ -57,6 +58,7 @@ device_added(struct udev_device *udev_device)
|
||||||
char *config_info = NULL;
|
char *config_info = NULL;
|
||||||
const char *syspath;
|
const char *syspath;
|
||||||
const char *tags_prop;
|
const char *tags_prop;
|
||||||
|
const char *usb_vendor = NULL, *usb_model = NULL;
|
||||||
const char *key, *value, *tmp;
|
const char *key, *value, *tmp;
|
||||||
InputOption *options = NULL, *tmpo;
|
InputOption *options = NULL, *tmpo;
|
||||||
InputAttributes attrs = {};
|
InputAttributes attrs = {};
|
||||||
|
@ -150,6 +152,12 @@ device_added(struct udev_device *udev_device)
|
||||||
} else if (!strcmp(key, "ID_VENDOR")) {
|
} else if (!strcmp(key, "ID_VENDOR")) {
|
||||||
LOG_PROPERTY(path, key, value);
|
LOG_PROPERTY(path, key, value);
|
||||||
attrs.vendor = 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")) {
|
} else if (!strcmp(key, "ID_INPUT_KEY")) {
|
||||||
LOG_PROPERTY(path, key, value);
|
LOG_PROPERTY(path, key, value);
|
||||||
attrs.flags |= ATTR_KEYBOARD;
|
attrs.flags |= ATTR_KEYBOARD;
|
||||||
|
@ -170,6 +178,17 @@ device_added(struct udev_device *udev_device)
|
||||||
attrs.flags |= ATTR_TOUCHSCREEN;
|
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",
|
LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
|
||||||
name, path);
|
name, path);
|
||||||
rc = NewInputDeviceRequest(options, &attrs, &dev);
|
rc = NewInputDeviceRequest(options, &attrs, &dev);
|
||||||
|
@ -190,6 +209,7 @@ device_added(struct udev_device *udev_device)
|
||||||
free(tmpo);
|
free(tmpo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(attrs.usb_id);
|
||||||
if (attrs.tags) {
|
if (attrs.tags) {
|
||||||
char **tag = attrs.tags;
|
char **tag = attrs.tags;
|
||||||
while (*tag) {
|
while (*tag) {
|
||||||
|
|
|
@ -359,6 +359,8 @@ DuplicateInputAttributes(InputAttributes *attrs)
|
||||||
goto unwind;
|
goto unwind;
|
||||||
if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id)))
|
if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id)))
|
||||||
goto unwind;
|
goto unwind;
|
||||||
|
if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id)))
|
||||||
|
goto unwind;
|
||||||
|
|
||||||
new_attr->flags = attrs->flags;
|
new_attr->flags = attrs->flags;
|
||||||
|
|
||||||
|
@ -404,6 +406,7 @@ FreeInputAttributes(InputAttributes *attrs)
|
||||||
free(attrs->vendor);
|
free(attrs->vendor);
|
||||||
free(attrs->device);
|
free(attrs->device);
|
||||||
free(attrs->pnp_id);
|
free(attrs->pnp_id);
|
||||||
|
free(attrs->usb_id);
|
||||||
|
|
||||||
if ((tags = attrs->tags))
|
if ((tags = attrs->tags))
|
||||||
while(*tags)
|
while(*tags)
|
||||||
|
|
|
@ -604,6 +604,10 @@ InputClassMatches(const XF86ConfInputClassPtr iclass,
|
||||||
if (!MatchAttrToken(attrs->pnp_id, iclass->match_pnpid, match_pattern))
|
if (!MatchAttrToken(attrs->pnp_id, iclass->match_pnpid, match_pattern))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
/* MatchUSBID pattern */
|
||||||
|
if (!MatchAttrToken(attrs->usb_id, iclass->match_usbid, 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.
|
||||||
|
|
|
@ -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
|
shell wildcard pattern. Multiple IDs can be matched by separating arguments
|
||||||
with a '|' character.
|
with a '|' character.
|
||||||
.TP 7
|
.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
|
.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
|
||||||
|
|
|
@ -49,6 +49,7 @@ xf86ConfigSymTabRec InputClassTab[] =
|
||||||
{MATCH_DEVICE_PATH, "matchdevicepath"},
|
{MATCH_DEVICE_PATH, "matchdevicepath"},
|
||||||
{MATCH_OS, "matchos"},
|
{MATCH_OS, "matchos"},
|
||||||
{MATCH_PNPID, "matchpnpid"},
|
{MATCH_PNPID, "matchpnpid"},
|
||||||
|
{MATCH_USBID, "matchusbid"},
|
||||||
{MATCH_TAG, "matchtag"},
|
{MATCH_TAG, "matchtag"},
|
||||||
{MATCH_IS_KEYBOARD, "matchiskeyboard"},
|
{MATCH_IS_KEYBOARD, "matchiskeyboard"},
|
||||||
{MATCH_IS_POINTER, "matchispointer"},
|
{MATCH_IS_POINTER, "matchispointer"},
|
||||||
|
@ -120,6 +121,11 @@ xf86parseInputClassSection(void)
|
||||||
Error(QUOTE_MSG, "MatchPnPID");
|
Error(QUOTE_MSG, "MatchPnPID");
|
||||||
ptr->match_pnpid = xstrtokenize(val.str, TOKEN_SEP);
|
ptr->match_pnpid = xstrtokenize(val.str, TOKEN_SEP);
|
||||||
break;
|
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:
|
case MATCH_TAG:
|
||||||
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
||||||
Error(QUOTE_MSG, "MatchTag");
|
Error(QUOTE_MSG, "MatchTag");
|
||||||
|
@ -245,6 +251,14 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
|
||||||
*list);
|
*list);
|
||||||
fprintf(cf, "\"\n");
|
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) {
|
if (ptr->match_tag) {
|
||||||
fprintf(cf, "\tMatchTag \"");
|
fprintf(cf, "\tMatchTag \"");
|
||||||
for (list = ptr->match_tag; *list; list++)
|
for (list = ptr->match_tag; *list; list++)
|
||||||
|
@ -311,6 +325,11 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr)
|
||||||
free(*list);
|
free(*list);
|
||||||
free(ptr->match_pnpid);
|
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) {
|
if (ptr->match_tag) {
|
||||||
for (list = ptr->match_tag; *list; list++)
|
for (list = ptr->match_tag; *list; list++)
|
||||||
free(*list);
|
free(*list);
|
||||||
|
|
|
@ -348,6 +348,7 @@ typedef struct
|
||||||
char **match_device;
|
char **match_device;
|
||||||
char **match_os;
|
char **match_os;
|
||||||
char **match_pnpid;
|
char **match_pnpid;
|
||||||
|
char **match_usbid;
|
||||||
char **match_tag;
|
char **match_tag;
|
||||||
xf86TriState is_keyboard;
|
xf86TriState is_keyboard;
|
||||||
xf86TriState is_pointer;
|
xf86TriState is_pointer;
|
||||||
|
|
|
@ -281,6 +281,7 @@ typedef enum {
|
||||||
MATCH_DEVICE_PATH,
|
MATCH_DEVICE_PATH,
|
||||||
MATCH_OS,
|
MATCH_OS,
|
||||||
MATCH_PNPID,
|
MATCH_PNPID,
|
||||||
|
MATCH_USBID,
|
||||||
MATCH_TAG,
|
MATCH_TAG,
|
||||||
MATCH_IS_KEYBOARD,
|
MATCH_IS_KEYBOARD,
|
||||||
MATCH_IS_POINTER,
|
MATCH_IS_POINTER,
|
||||||
|
|
|
@ -216,6 +216,7 @@ typedef struct _InputAttributes {
|
||||||
char *vendor;
|
char *vendor;
|
||||||
char *device;
|
char *device;
|
||||||
char *pnp_id;
|
char *pnp_id;
|
||||||
|
char *usb_id;
|
||||||
char **tags; /* null-terminated */
|
char **tags; /* null-terminated */
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
} InputAttributes;
|
} InputAttributes;
|
||||||
|
|
12
test/input.c
12
test/input.c
|
@ -808,6 +808,13 @@ static void cmp_attr_fields(InputAttributes *attr1,
|
||||||
} else
|
} else
|
||||||
g_assert(attr2->pnp_id == NULL);
|
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;
|
tags1 = attr1->tags;
|
||||||
tags2 = attr2->tags;
|
tags2 = attr2->tags;
|
||||||
|
|
||||||
|
@ -878,6 +885,11 @@ static void dix_input_attributes(void)
|
||||||
cmp_attr_fields(&orig, new);
|
cmp_attr_fields(&orig, new);
|
||||||
FreeInputAttributes(new);
|
FreeInputAttributes(new);
|
||||||
|
|
||||||
|
orig.usb_id = "USBID";
|
||||||
|
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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user