summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2010-06-10 18:39:10 -0700
committerKeith Packard <keithp@keithp.com>2010-06-10 18:39:10 -0700
commit07a093add0b7e40c4d9b9b59273e3ff9e14a88a7 (patch)
treeed1dfc8d0051a15f417d41fa9d3e7f41d131559e /hw
parent84190d20954ef7888e4d96832c2a4b3225b4dfa2 (diff)
parentdc614484f93b67e8b62dbb1bb2fd247fe5a4c850 (diff)
Merge remote branch 'whot/for-keith'
Diffstat (limited to 'hw')
-rw-r--r--hw/xfree86/common/xf86Xinput.c222
-rw-r--r--hw/xfree86/doc/man/xorg.conf.man.pre71
-rw-r--r--hw/xfree86/parser/InputClass.c191
-rw-r--r--hw/xfree86/parser/xf86Parser.h20
-rw-r--r--hw/xfree86/parser/xf86tokens.h4
5 files changed, 383 insertions, 125 deletions
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 889339a9e..76d2d0041 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -80,6 +80,9 @@
#ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
#endif
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
#include "extnsionst.h"
@@ -497,73 +500,152 @@ AddOtherInputDevices(void)
}
/*
- * Classes without any Match statements match all devices. Otherwise, all
- * statements must match.
+ * Get the operating system name from uname and store it statically to avoid
+ * repeating the system call each time MatchOS is checked.
*/
-static Bool
-InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
+static const char *
+HostOS(void)
{
- char **cur;
- Bool match;
-
- if (iclass->match_product) {
- if (!attrs->product)
- return FALSE;
- /* see if any of the values match */
- for (cur = iclass->match_product, match = FALSE; *cur; cur++)
- if (strstr(attrs->product, *cur)) {
- match = TRUE;
- break;
- }
- if (!match)
- return FALSE;
- }
- if (iclass->match_vendor) {
- if (!attrs->vendor)
- return FALSE;
- /* see if any of the values match */
- for (cur = iclass->match_vendor, match = FALSE; *cur; cur++)
- if (strstr(attrs->vendor, *cur)) {
- match = TRUE;
- break;
- }
- if (!match)
- return FALSE;
+#ifdef HAVE_SYS_UTSNAME_H
+ struct utsname name;
+ static char host_os[sizeof(name.sysname)] = "";
+
+ if (*host_os == '\0') {
+ if (uname(&name) >= 0)
+ strcpy(host_os, name.sysname);
+ else {
+ strncpy(host_os, "unknown", sizeof(host_os));
+ host_os[sizeof(host_os)-1] = '\0';
+ }
}
- if (iclass->match_device) {
- if (!attrs->device)
- return FALSE;
- /* see if any of the values match */
- for (cur = iclass->match_device, match = FALSE; *cur; cur++)
+ return host_os;
+#else
+ return "";
+#endif
+}
+
+static int
+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
- if (fnmatch(*cur, attrs->device, FNM_PATHNAME) == 0) {
+static int
+match_path_pattern(const char *attr, const char *pattern)
+{
+ return fnmatch(pattern, attr, FNM_PATHNAME);
+}
#else
- if (strstr(attrs->device, *cur)) {
+#define match_path_pattern match_substring
#endif
+
+/*
+ * Match an attribute against a list of NULL terminated arrays of patterns.
+ * If a pattern in each list entry is matched, return TRUE.
+ */
+static Bool
+MatchAttrToken(const char *attr, struct list *patterns,
+ int (*compare)(const char *attr, const char *pattern))
+{
+ const xf86MatchGroup *group;
+
+ /* If there are no patterns, accept the match */
+ if (list_is_empty(patterns))
+ return TRUE;
+
+ /* If there are patterns but no attribute, reject the match */
+ if (!attr)
+ return FALSE;
+
+ /*
+ * Otherwise, iterate the list of patterns ensuring each entry has a
+ * match. Each list entry is a separate Match line of the same type.
+ */
+ list_for_each_entry(group, patterns, entry) {
+ char * const *cur;
+ Bool match = FALSE;
+
+ for (cur = group->values; *cur; cur++)
+ if ((*compare)(attr, *cur) == 0) {
match = TRUE;
break;
}
if (!match)
return FALSE;
}
- if (iclass->match_tag) {
+
+ /* All the entries in the list matched the attribute */
+ return TRUE;
+}
+
+/*
+ * Classes without any Match statements match all devices. Otherwise, all
+ * statements must match.
+ */
+static Bool
+InputClassMatches(const XF86ConfInputClassPtr iclass, const IDevPtr idev,
+ const InputAttributes *attrs)
+{
+ /* MatchProduct substring */
+ if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring))
+ return FALSE;
+
+ /* MatchVendor substring */
+ if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring))
+ return FALSE;
+
+ /* MatchDevicePath pattern */
+ if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern))
+ return FALSE;
+
+ /* MatchOS case-insensitive string */
+ if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp))
+ return FALSE;
+
+ /* MatchPnPID pattern */
+ if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern))
+ return FALSE;
+
+ /* MatchUSBID pattern */
+ if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern))
+ return FALSE;
+
+ /* MatchDriver string */
+ if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp))
+ return FALSE;
+
+ /*
+ * MatchTag string
+ * See if any of the device's tags match any of the MatchTag tokens.
+ */
+ if (!list_is_empty(&iclass->match_tag)) {
+ char * const *tag;
+ Bool match;
+
if (!attrs->tags)
return FALSE;
-
- for (cur = iclass->match_tag, match = FALSE; *cur && !match; cur++) {
- char * const *tag;
- for(tag = attrs->tags; *tag; tag++) {
- if (!strcmp(*tag, *cur)) {
- match = TRUE;
- break;
- }
+ for (tag = attrs->tags, match = FALSE; *tag; tag++) {
+ if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) {
+ match = TRUE;
+ break;
}
}
-
if (!match)
return FALSE;
}
+ /* MatchIs* booleans */
if (iclass->is_keyboard.set &&
iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
return FALSE;
@@ -582,6 +664,7 @@ InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
if (iclass->is_touchscreen.set &&
iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN))
return FALSE;
+
return TRUE;
}
@@ -591,37 +674,36 @@ InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
* well as any previous InputClass sections.
*/
static int
-MergeInputClasses(IDevPtr idev, InputAttributes *attrs)
+MergeInputClasses(const IDevPtr idev, const InputAttributes *attrs)
{
XF86ConfInputClassPtr cl;
- XF86OptionPtr classopts, mergedopts = NULL;
- char *classdriver = NULL;
+ XF86OptionPtr classopts;
for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) {
- if (!InputClassMatches(cl, attrs))
+ if (!InputClassMatches(cl, idev, attrs))
continue;
- /* Collect class options and merge over previous classes */
+ /* Collect class options and driver settings */
+ classopts = xf86optionListDup(cl->option_lst);
+ if (cl->driver) {
+ free(idev->driver);
+ idev->driver = xstrdup(cl->driver);
+ if (!idev->driver) {
+ xf86Msg(X_ERROR, "Failed to allocate memory while merging "
+ "InputClass configuration");
+ return BadAlloc;
+ }
+ classopts = xf86ReplaceStrOption(classopts, "driver",
+ idev->driver);
+ }
+
+ /* Apply options to device with InputClass settings preferred. */
xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n",
idev->identifier, cl->identifier);
- if (cl->driver)
- classdriver = cl->driver;
- classopts = xf86optionListDup(cl->option_lst);
- mergedopts = xf86optionListMerge(mergedopts, classopts);
+ idev->commonOptions = xf86optionListMerge(idev->commonOptions,
+ classopts);
}
- /* Apply options to device with InputClass settings preferred. */
- if (classdriver) {
- free(idev->driver);
- idev->driver = xstrdup(classdriver);
- if (!idev->driver) {
- xf86Msg(X_ERROR, "Failed to allocate memory while merging "
- "InputClass configuration");
- return BadAlloc;
- }
- mergedopts = xf86ReplaceStrOption(mergedopts, "driver", idev->driver);
- }
- idev->commonOptions = xf86optionListMerge(idev->commonOptions, mergedopts);
return Success;
}
@@ -630,14 +712,14 @@ MergeInputClasses(IDevPtr idev, InputAttributes *attrs)
* value of the last matching class and holler when returning TRUE.
*/
static Bool
-IgnoreInputClass(IDevPtr idev, InputAttributes *attrs)
+IgnoreInputClass(const IDevPtr idev, const InputAttributes *attrs)
{
XF86ConfInputClassPtr cl;
Bool ignore = FALSE;
const char *ignore_class;
for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) {
- if (!InputClassMatches(cl, attrs))
+ if (!InputClassMatches(cl, idev, attrs))
continue;
if (xf86findOption(cl->option_lst, "Ignore")) {
ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE);
diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre
index 9075db64f..6b3636fff 100644
--- a/hw/xfree86/doc/man/xorg.conf.man.pre
+++ b/hw/xfree86/doc/man/xorg.conf.man.pre
@@ -1065,35 +1065,85 @@ of the class. If none of the optional entries appear, the
.B InputClass
section is generic and will match any input device. If more than one of
these entries appear, they all must match for the configuration to apply.
-The allowed matching entries are shown below.
.PP
+There are two types of match entries used in
+.B InputClass
+sections. The first allows various tokens to be matched against attributes
+of the device. An entry can be constructed to match attributes from different
+devices by separating arguments with a '|' character. Multiple entries of the
+same type may be supplied to add multiple matching conditions on the same
+attribute. For example:
+.PP
+.RS 4
+.nf
+.B "Section \*qInputClass\*q"
+.B " Identifier \*qMy Class\*q"
+.B " # product string must contain example and
+.B " # either gizmo or gadget
+.B " MatchProduct \*qexample\*q
+.B " MatchProduct \*qgizmo|gadget\*q
+.I " ..."
+.B "EndSection"
+.fi
+.RE
.TP 7
.BI "MatchProduct \*q" matchproduct \*q
This entry can be used to check if the substring
.RI \*q matchproduct \*q
-occurs in the device's product name. Multiple substrings can be matched by
-separating arguments with a '|' character.
+occurs in the device's product name.
.TP 7
.BI "MatchVendor \*q" matchvendor \*q
This entry can be used to check if the substring
.RI \*q matchvendor \*q
-occurs in the device's vendor name. Multiple substrings can be matched by
-separating arguments with a '|' character.
+occurs in the device's vendor name.
.TP 7
.BI "MatchDevicePath \*q" matchdevice \*q
This entry can be used to check if the device file matches the
.RI \*q matchdevice \*q
-pathname pattern. Multiple patterns can be matched by separating arguments
-with a '|' character.
+pathname pattern.
+.TP 7
+.BI "MatchOS \*q" matchos \*q
+This entry can be used to check if the operating system matches the
+case-insensitive
+.RI \*q matchos \*q
+string. This entry is only supported on platforms providing the
+.BR uname (2)
+system call.
+.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.
+.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.
+.TP 7
+.BI "MatchDriver \*q" matchdriver \*q
+Check the case-sensitive string
+.RI \*q matchdriver \*q
+against the currently configured driver of the device. Ordering of sections
+using this entry is important since it will not match unless the driver has
+been set by the config backend or a previous
+.B InputClass
+section.
.TP 7
.BI "MatchTag \*q" matchtag \*q
This entry can be used to check if tags assigned by the config backend
matches the
.RI \*q matchtag \*q
-pattern. Multiple patterns can be matched by separating arguments
-with a '|' character. A match is found if at least one of the tags given in
+pattern. A match is found if at least one of the tags given in
.RI \*q matchtag \*q
matches at least one of the tags assigned by the backend.
+.PP
+The second type of entry is used to match device types. These entries take a
+boolean argument similar to
+.B Option
+entries.
.TP 7
.BI "MatchIsKeyboard \*q" bool \*q
.TP 7
@@ -1106,9 +1156,6 @@ matches at least one of the tags assigned by the backend.
.BI "MatchIsTouchpad \*q" bool \*q
.TP 7
.BI "MatchIsTouchscreen \*q" bool \*q
-Match device types. These entries take a boolean argument similar to
-.B Option
-entries.
.PP
When an input device has been matched to the
.B InputClass
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
index 7fb2866cd..ce611d990 100644
--- a/hw/xfree86/parser/InputClass.c
+++ b/hw/xfree86/parser/InputClass.c
@@ -47,6 +47,10 @@ xf86ConfigSymTabRec InputClassTab[] =
{MATCH_PRODUCT, "matchproduct"},
{MATCH_VENDOR, "matchvendor"},
{MATCH_DEVICE_PATH, "matchdevicepath"},
+ {MATCH_OS, "matchos"},
+ {MATCH_PNPID, "matchpnpid"},
+ {MATCH_USBID, "matchusbid"},
+ {MATCH_DRIVER, "matchdriver"},
{MATCH_TAG, "matchtag"},
{MATCH_IS_KEYBOARD, "matchiskeyboard"},
{MATCH_IS_POINTER, "matchispointer"},
@@ -61,6 +65,18 @@ xf86ConfigSymTabRec InputClassTab[] =
#define TOKEN_SEP "|"
+static void
+add_group_entry(struct list *head, char **values)
+{
+ xf86MatchGroup *group;
+
+ group = malloc(sizeof(*group));
+ if (group) {
+ group->values = values;
+ list_add(&group->entry, head);
+ }
+}
+
XF86ConfInputClassPtr
xf86parseInputClassSection(void)
{
@@ -69,6 +85,16 @@ xf86parseInputClassSection(void)
parsePrologue(XF86ConfInputClassPtr, XF86ConfInputClassRec)
+ /* Initialize MatchGroup lists */
+ list_init(&ptr->match_product);
+ list_init(&ptr->match_vendor);
+ list_init(&ptr->match_device);
+ list_init(&ptr->match_os);
+ list_init(&ptr->match_pnpid);
+ list_init(&ptr->match_usbid);
+ list_init(&ptr->match_driver);
+ list_init(&ptr->match_tag);
+
while ((token = xf86getToken(InputClassTab)) != ENDSECTION) {
switch (token) {
case COMMENT:
@@ -96,22 +122,50 @@ xf86parseInputClassSection(void)
case MATCH_PRODUCT:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchProduct");
- ptr->match_product = xstrtokenize(val.str, TOKEN_SEP);
+ add_group_entry(&ptr->match_product,
+ xstrtokenize(val.str, TOKEN_SEP));
break;
case MATCH_VENDOR:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchVendor");
- ptr->match_vendor = xstrtokenize(val.str, TOKEN_SEP);
+ add_group_entry(&ptr->match_vendor,
+ xstrtokenize(val.str, TOKEN_SEP));
break;
case MATCH_DEVICE_PATH:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchDevicePath");
- ptr->match_device = xstrtokenize(val.str, TOKEN_SEP);
+ add_group_entry(&ptr->match_device,
+ xstrtokenize(val.str, TOKEN_SEP));
+ break;
+ case MATCH_OS:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchOS");
+ add_group_entry(&ptr->match_os,
+ xstrtokenize(val.str, TOKEN_SEP));
+ break;
+ case MATCH_PNPID:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchPnPID");
+ add_group_entry(&ptr->match_pnpid,
+ xstrtokenize(val.str, TOKEN_SEP));
+ break;
+ case MATCH_USBID:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchUSBID");
+ add_group_entry(&ptr->match_usbid,
+ xstrtokenize(val.str, TOKEN_SEP));
+ break;
+ case MATCH_DRIVER:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchDriver");
+ add_group_entry(&ptr->match_driver,
+ xstrtokenize(val.str, TOKEN_SEP));
break;
case MATCH_TAG:
if (xf86getSubToken(&(ptr->comment)) != STRING)
Error(QUOTE_MSG, "MatchTag");
- ptr->match_tag = xstrtokenize(val.str, TOKEN_SEP);
+ add_group_entry(&ptr->match_tag,
+ xstrtokenize(val.str, TOKEN_SEP));
break;
case MATCH_IS_KEYBOARD:
if (xf86getSubToken(&(ptr->comment)) != STRING)
@@ -183,7 +237,8 @@ xf86parseInputClassSection(void)
void
xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
{
- char **list;
+ const xf86MatchGroup *group;
+ char * const *cur;
while (ptr) {
fprintf(cf, "Section \"InputClass\"\n");
@@ -193,38 +248,64 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier);
if (ptr->driver)
fprintf(cf, "\tDriver \"%s\"\n", ptr->driver);
- if (ptr->match_product) {
+
+ list_for_each_entry(group, &ptr->match_product, entry) {
fprintf(cf, "\tMatchProduct \"");
- for (list = ptr->match_product; *list; list++)
- fprintf(cf, "%s%s",
- list == ptr->match_product ? "" : TOKEN_SEP,
- *list);
+ for (cur = group->values; *cur; cur++)
+ fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+ *cur);
fprintf(cf, "\"\n");
}
- if (ptr->match_vendor) {
+ list_for_each_entry(group, &ptr->match_vendor, entry) {
fprintf(cf, "\tMatchVendor \"");
- for (list = ptr->match_vendor; *list; list++)
- fprintf(cf, "%s%s",
- list == ptr->match_vendor ? "" : TOKEN_SEP,
- *list);
+ for (cur = group->values; *cur; cur++)
+ fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+ *cur);
fprintf(cf, "\"\n");
}
- if (ptr->match_device) {
+ list_for_each_entry(group, &ptr->match_device, entry) {
fprintf(cf, "\tMatchDevicePath \"");
- for (list = ptr->match_device; *list; list++)
- fprintf(cf, "%s%s",
- list == ptr->match_device ? "" : TOKEN_SEP,
- *list);
+ for (cur = group->values; *cur; cur++)
+ fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+ *cur);
+ fprintf(cf, "\"\n");
+ }
+ list_for_each_entry(group, &ptr->match_os, entry) {
+ fprintf(cf, "\tMatchOS \"");
+ for (cur = group->values; *cur; cur++)
+ fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+ *cur);
fprintf(cf, "\"\n");
}
- if (ptr->match_tag) {
- fprintf(cf, "\tMatchTag \"");
- for (list = ptr->match_tag; *list; list++)
- fprintf(cf, "%s%s",
- list == ptr->match_tag ? "" : TOKEN_SEP,
- *list);
+ list_for_each_entry(group, &ptr->match_pnpid, entry) {
+ fprintf(cf, "\tMatchPnPID \"");
+ for (cur = group->values; *cur; cur++)
+ fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+ *cur);
fprintf(cf, "\"\n");
}
+ list_for_each_entry(group, &ptr->match_usbid, entry) {
+ fprintf(cf, "\tMatchUSBID \"");
+ for (cur = group->values; *cur; cur++)
+ fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+ *cur);
+ fprintf(cf, "\"\n");
+ }
+ list_for_each_entry(group, &ptr->match_driver, entry) {
+ fprintf(cf, "\tMatchDriver \"");
+ for (cur = group->values; *cur; cur++)
+ fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+ *cur);
+ fprintf(cf, "\"\n");
+ }
+ list_for_each_entry(group, &ptr->match_tag, entry) {
+ fprintf(cf, "\tMatchTag \"");
+ for (cur = group->values; *cur; cur++)
+ fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+ *cur);
+ fprintf(cf, "\"\n");
+ }
+
if (ptr->is_keyboard.set)
fprintf(cf, "\tIsKeyboard \"%s\"\n",
ptr->is_keyboard.val ? "yes" : "no");
@@ -253,31 +334,63 @@ void
xf86freeInputClassList (XF86ConfInputClassPtr ptr)
{
XF86ConfInputClassPtr prev;
- char **list;
while (ptr) {
+ xf86MatchGroup *group, *next;
+ char **list;
+
TestFree(ptr->identifier);
TestFree(ptr->driver);
- if (ptr->match_product) {
- for (list = ptr->match_product; *list; list++)
+
+ list_for_each_entry_safe(group, next, &ptr->match_product, entry) {
+ list_del(&group->entry);
+ for (list = group->values; *list; list++)
free(*list);
- free(ptr->match_product);
+ free(group);
}
- if (ptr->match_vendor) {
- for (list = ptr->match_vendor; *list; list++)
+ list_for_each_entry_safe(group, next, &ptr->match_vendor, entry) {
+ list_del(&group->entry);
+ for (list = group->values; *list; list++)
free(*list);
- free(ptr->match_vendor);
+ free(group);
}
- if (ptr->match_device) {
- for (list = ptr->match_device; *list; list++)
+ list_for_each_entry_safe(group, next, &ptr->match_device, entry) {
+ list_del(&group->entry);
+ for (list = group->values; *list; list++)
free(*list);
- free(ptr->match_device);
+ free(group);
}
- if (ptr->match_tag) {
- for (list = ptr->match_tag; *list; list++)
+ list_for_each_entry_safe(group, next, &ptr->match_os, entry) {
+ list_del(&group->entry);
+ for (list = group->values; *list; list++)
free(*list);
- free(ptr->match_tag);
+ free(group);
}
+ list_for_each_entry_safe(group, next, &ptr->match_pnpid, entry) {
+ list_del(&group->entry);
+ for (list = group->values; *list; list++)
+ free(*list);
+ free(group);
+ }
+ list_for_each_entry_safe(group, next, &ptr->match_usbid, entry) {
+ list_del(&group->entry);
+ for (list = group->values; *list; list++)
+ free(*list);
+ free(group);
+ }
+ list_for_each_entry_safe(group, next, &ptr->match_driver, entry) {
+ list_del(&group->entry);
+ for (list = group->values; *list; list++)
+ free(*list);
+ free(group);
+ }
+ list_for_each_entry_safe(group, next, &ptr->match_tag, entry) {
+ list_del(&group->entry);
+ for (list = group->values; *list; list++)
+ free(*list);
+ free(group);
+ }
+
TestFree(ptr->comment);
xf86optionListFree(ptr->option_lst);
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index d79544a20..337ad0718 100644
--- a/hw/xfree86/parser/xf86Parser.h
+++ b/hw/xfree86/parser/xf86Parser.h
@@ -66,6 +66,7 @@
#include <X11/Xdefs.h>
#include "xf86Optrec.h"
+#include "list.h"
#define HAVE_PARSER_DECLS
@@ -340,13 +341,24 @@ xf86TriState;
typedef struct
{
+ struct list entry;
+ char **values;
+}
+xf86MatchGroup;
+
+typedef struct
+{
GenericListRec list;
char *identifier;
char *driver;
- char **match_product;
- char **match_vendor;
- char **match_device;
- char **match_tag;
+ struct list match_product;
+ struct list match_vendor;
+ struct list match_device;
+ struct list match_os;
+ struct list match_pnpid;
+ struct list match_usbid;
+ struct list match_driver;
+ struct list match_tag;
xf86TriState is_keyboard;
xf86TriState is_pointer;
xf86TriState is_joystick;
diff --git a/hw/xfree86/parser/xf86tokens.h b/hw/xfree86/parser/xf86tokens.h
index cb600704b..c16a8f551 100644
--- a/hw/xfree86/parser/xf86tokens.h
+++ b/hw/xfree86/parser/xf86tokens.h
@@ -279,6 +279,10 @@ typedef enum {
MATCH_PRODUCT,
MATCH_VENDOR,
MATCH_DEVICE_PATH,
+ MATCH_OS,
+ MATCH_PNPID,
+ MATCH_USBID,
+ MATCH_DRIVER,
MATCH_TAG,
MATCH_IS_KEYBOARD,
MATCH_IS_POINTER,