[PATCH 10/11] xfree86: Match devices based on USB ID
Dan Nicholson
dbn.lists at gmail.com
Thu May 20 07:09:12 PDT 2010
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 at gmail.com>
---
config/hal.c | 27 ++++++++++++++++++++++++++-
config/udev.c | 24 ++++++++++++++++++++++++
hw/xfree86/common/xf86Xinput.c | 4 ++++
hw/xfree86/doc/man/xorg.conf.man.pre | 9 +++++++++
hw/xfree86/parser/InputClass.c | 6 ++++++
hw/xfree86/parser/xf86Parser.h | 1 +
hw/xfree86/parser/xf86tokens.h | 1 +
include/input.h | 1 +
8 files changed, 72 insertions(+), 1 deletions(-)
diff --git a/config/hal.c b/config/hal.c
index 64e6967..9a303cc 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -130,7 +130,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
{
char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL;
char **tags = NULL;
- char *vendor = NULL, *hal_tags, *parent, *pnp_id = NULL;
+ char *vendor = NULL, *hal_tags, *parent, *pnp_id = NULL, *usb_id = NULL;
InputOption *options = NULL, *tmpo = NULL;
InputAttributes attrs = {0};
DeviceIntPtr dev = NULL;
@@ -186,7 +186,31 @@ 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 = 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) {
+ /* assume "0000:ffff" format */
+ usb_id = malloc(sizeof("xxxx:xxxx"));
+ if (usb_id) {
+ snprintf(usb_id, sizeof("xxxx:xxxx"), "%04x:%04x",
+ usb_vendor, usb_product);
+ attrs.usb_id = usb_id;
+ }
+ }
+
free(parent);
}
@@ -402,6 +426,7 @@ unwind:
free(vendor);
free(pnp_id);
+ free(usb_id);
if (tags) {
char **tag = tags;
while (*tag) {
diff --git a/config/udev.c b/config/udev.c
index 274e2a0..27a8155 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -28,6 +28,7 @@
#endif
#include <libudev.h>
+#include <ctype.h>
#include "input.h"
#include "inputstr.h"
@@ -57,6 +58,8 @@ 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;
+ char *usb_id = NULL;
const char *key, *value, *tmp;
char **tags = NULL;
InputOption *options = NULL, *tmpo;
@@ -152,6 +155,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;
@@ -172,6 +181,20 @@ device_added(struct udev_device *udev_device)
attrs.flags |= ATTR_TOUCHSCREEN;
}
}
+
+ /* construct USB ID in lowercase hex - "0000:ffff" */
+ if (usb_vendor && usb_model) {
+ usb_id = malloc(strlen(usb_vendor) + strlen(usb_model) + 2);
+ if (usb_id) {
+ char *cur;
+
+ sprintf(usb_id, "%s:%s", usb_vendor, usb_model);
+ for (cur = usb_id; *cur; cur++)
+ *cur = tolower(*cur);
+ attrs.usb_id = usb_id;
+ }
+ }
+
LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
name, path);
rc = NewInputDeviceRequest(options, &attrs, &dev);
@@ -192,6 +215,7 @@ device_added(struct udev_device *udev_device)
free(tmpo);
}
+ free(usb_id);
if (tags) {
char **tag = tags;
while (*tag) {
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 72c9bbf..4323725 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -601,6 +601,10 @@ InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
if (!MatchAttrToken(attrs->pnp_id, iclass->match_pnpid, MatchPattern))
return FALSE;
+ /* MatchUSBID pattern */
+ if (!MatchAttrToken(attrs->usb_id, iclass->match_usbid, MatchPattern))
+ 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 e74c78b..0f7aab6 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 c1a785a..e07c7af 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");
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index 87fc31c..a86462f 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 aa33935..23460dd 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 9991624..a710ce3 100644
--- a/include/input.h
+++ b/include/input.h
@@ -216,6 +216,7 @@ typedef struct _InputAttributes {
const char *vendor;
const char *device;
const char *pnp_id;
+ const char *usb_id;
const char * const *tags; /* null-terminated */
uint32_t flags;
} InputAttributes;
--
1.6.6.1
More information about the xorg-devel
mailing list