xfree86: Match devices based on current driver setting

Often we want to apply a driver specific option to a set of devices and
don't care how the driver was selected for that device. The MatchDriver
entry can be used to match the current driver string:

	MatchDriver "evdev|mouse"
	Option "Emulate3Buttons" "yes"

The driver string is a case sensitive match.

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-07 20:39:58 -07:00 committed by Peter Hutterer
parent a71bdff47d
commit 66b21b2f45
5 changed files with 57 additions and 22 deletions

View File

@ -594,7 +594,7 @@ MatchAttrToken(const char *attr, struct list *patterns,
* statements must match.
*/
static Bool
InputClassMatches(const XF86ConfInputClassPtr iclass,
InputClassMatches(const XF86ConfInputClassPtr iclass, const IDevPtr idev,
const InputAttributes *attrs)
{
/* MatchProduct substring */
@ -621,6 +621,10 @@ InputClassMatches(const XF86ConfInputClassPtr iclass,
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.
@ -673,34 +677,33 @@ static int
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;
}
@ -716,7 +719,7 @@ IgnoreInputClass(const IDevPtr idev, const InputAttributes *attrs)
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);

View File

@ -1123,6 +1123,15 @@ 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

View File

@ -50,6 +50,7 @@ xf86ConfigSymTabRec InputClassTab[] =
{MATCH_OS, "matchos"},
{MATCH_PNPID, "matchpnpid"},
{MATCH_USBID, "matchusbid"},
{MATCH_DRIVER, "matchdriver"},
{MATCH_TAG, "matchtag"},
{MATCH_IS_KEYBOARD, "matchiskeyboard"},
{MATCH_IS_POINTER, "matchispointer"},
@ -91,6 +92,7 @@ xf86parseInputClassSection(void)
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) {
@ -153,6 +155,12 @@ xf86parseInputClassSection(void)
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");
@ -283,6 +291,13 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
*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++)
@ -363,6 +378,12 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr)
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++)

View File

@ -357,6 +357,7 @@ typedef struct
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;

View File

@ -282,6 +282,7 @@ typedef enum {
MATCH_OS,
MATCH_PNPID,
MATCH_USBID,
MATCH_DRIVER,
MATCH_TAG,
MATCH_IS_KEYBOARD,
MATCH_IS_POINTER,