xfree86: Allow multiple arguments to InputClass matches
In order to keep the number of InputClass sections manageable, allow matches to contain multiple arguments. The arguments will be separated by the '|' character. This allows a policy to apply to multiple types of devices. For example: Section "InputClass" Identifier "Inverted Mice" MatchProduct "Crazy Mouse|Silly Mouse" Option "InvertX" "yes" EndSection This applies to the MatchProduct, MatchVendor and MatchDevicePath entries. Currently there is no way to escape characters, so names or patterns cannot contain '|'. 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
a378e361a5
commit
9b369f7127
|
@ -502,20 +502,49 @@ AddOtherInputDevices(void)
|
||||||
static Bool
|
static Bool
|
||||||
InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
|
InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
|
||||||
{
|
{
|
||||||
if (iclass->match_product &&
|
char **cur;
|
||||||
(!attrs->product || !strstr(attrs->product, iclass->match_product)))
|
Bool match;
|
||||||
return FALSE;
|
|
||||||
if (iclass->match_vendor &&
|
if (iclass->match_product) {
|
||||||
(!attrs->vendor || !strstr(attrs->vendor, iclass->match_vendor)))
|
if (!attrs->product)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (iclass->match_device &&
|
/* 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;
|
||||||
|
}
|
||||||
|
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++)
|
||||||
#ifdef HAVE_FNMATCH_H
|
#ifdef HAVE_FNMATCH_H
|
||||||
(!attrs->device ||
|
if (fnmatch(*cur, attrs->device, 0) == 0) {
|
||||||
fnmatch(iclass->match_device, attrs->device, 0) != 0))
|
|
||||||
#else
|
#else
|
||||||
(!attrs->device || !strstr(attrs->device, iclass->match_device)))
|
if (strstr(attrs->device, *cur)) {
|
||||||
#endif
|
#endif
|
||||||
return FALSE;
|
match = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!match)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
if (iclass->is_keyboard.set &&
|
if (iclass->is_keyboard.set &&
|
||||||
iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
|
iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -1039,17 +1039,20 @@ The allowed matching entries are shown below.
|
||||||
.BI "MatchProduct \*q" matchproduct \*q
|
.BI "MatchProduct \*q" matchproduct \*q
|
||||||
This entry can be used to check if the substring
|
This entry can be used to check if the substring
|
||||||
.RI \*q matchproduct \*q
|
.RI \*q matchproduct \*q
|
||||||
occurs in the device's product name.
|
occurs in the device's product name. Multiple substrings can be matched by
|
||||||
|
separating arguments with a '|' character.
|
||||||
.TP 7
|
.TP 7
|
||||||
.BI "MatchVendor \*q" matchvendor \*q
|
.BI "MatchVendor \*q" matchvendor \*q
|
||||||
This entry can be used to check if the substring
|
This entry can be used to check if the substring
|
||||||
.RI \*q matchvendor \*q
|
.RI \*q matchvendor \*q
|
||||||
occurs in the device's vendor name.
|
occurs in the device's vendor name. Multiple substrings can be matched by
|
||||||
|
separating arguments with a '|' character.
|
||||||
.TP 7
|
.TP 7
|
||||||
.BI "MatchDevicePath \*q" matchdevice \*q
|
.BI "MatchDevicePath \*q" matchdevice \*q
|
||||||
This entry can be used to check if the device file matches the
|
This entry can be used to check if the device file matches the
|
||||||
.RI \*q matchdevice \*q
|
.RI \*q matchdevice \*q
|
||||||
pathname pattern.
|
pathname pattern. Multiple patterns can be matched by separating arguments
|
||||||
|
with a '|' character.
|
||||||
.TP 7
|
.TP 7
|
||||||
.BI "MatchIsKeyboard \*q" bool \*q
|
.BI "MatchIsKeyboard \*q" bool \*q
|
||||||
.TP 7
|
.TP 7
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include <xorg-config.h>
|
#include <xorg-config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "os.h"
|
||||||
#include "xf86Parser.h"
|
#include "xf86Parser.h"
|
||||||
#include "xf86tokens.h"
|
#include "xf86tokens.h"
|
||||||
#include "Configint.h"
|
#include "Configint.h"
|
||||||
|
@ -56,6 +58,46 @@ xf86ConfigSymTabRec InputClassTab[] =
|
||||||
|
|
||||||
#define CLEANUP xf86freeInputClassList
|
#define CLEANUP xf86freeInputClassList
|
||||||
|
|
||||||
|
#define TOKEN_SEP "|"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tokenize a string into a NULL terminated array of strings. Always returns
|
||||||
|
* an allocated array unless an error occurs.
|
||||||
|
*/
|
||||||
|
static char **
|
||||||
|
tokenize(const char *str)
|
||||||
|
{
|
||||||
|
char **list, **nlist;
|
||||||
|
char *tok, *tmp;
|
||||||
|
unsigned num = 0, n;
|
||||||
|
|
||||||
|
list = calloc(1, sizeof(*list));
|
||||||
|
if (!list)
|
||||||
|
return NULL;
|
||||||
|
tmp = strdup(str);
|
||||||
|
if (!tmp)
|
||||||
|
goto error;
|
||||||
|
for (tok = strtok(tmp, TOKEN_SEP); tok; tok = strtok(NULL, TOKEN_SEP)) {
|
||||||
|
nlist = realloc(list, (num + 2) * sizeof(*list));
|
||||||
|
if (!nlist)
|
||||||
|
goto error;
|
||||||
|
list = nlist;
|
||||||
|
list[num] = strdup(tok);
|
||||||
|
if (!list[num])
|
||||||
|
goto error;
|
||||||
|
list[++num] = NULL;
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
return list;
|
||||||
|
|
||||||
|
error:
|
||||||
|
TestFree(tmp);
|
||||||
|
for (n = 0; n < num; n++)
|
||||||
|
free(list[n]);
|
||||||
|
TestFree(list);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
XF86ConfInputClassPtr
|
XF86ConfInputClassPtr
|
||||||
xf86parseInputClassSection(void)
|
xf86parseInputClassSection(void)
|
||||||
{
|
{
|
||||||
|
@ -91,17 +133,17 @@ xf86parseInputClassSection(void)
|
||||||
case MATCH_PRODUCT:
|
case MATCH_PRODUCT:
|
||||||
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
||||||
Error(QUOTE_MSG, "MatchProduct");
|
Error(QUOTE_MSG, "MatchProduct");
|
||||||
ptr->match_product = val.str;
|
ptr->match_product = tokenize(val.str);
|
||||||
break;
|
break;
|
||||||
case MATCH_VENDOR:
|
case MATCH_VENDOR:
|
||||||
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
||||||
Error(QUOTE_MSG, "MatchVendor");
|
Error(QUOTE_MSG, "MatchVendor");
|
||||||
ptr->match_vendor = val.str;
|
ptr->match_vendor = tokenize(val.str);
|
||||||
break;
|
break;
|
||||||
case MATCH_DEVICE_PATH:
|
case MATCH_DEVICE_PATH:
|
||||||
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
||||||
Error(QUOTE_MSG, "MatchDevicePath");
|
Error(QUOTE_MSG, "MatchDevicePath");
|
||||||
ptr->match_device = val.str;
|
ptr->match_device = tokenize(val.str);
|
||||||
break;
|
break;
|
||||||
case MATCH_IS_KEYBOARD:
|
case MATCH_IS_KEYBOARD:
|
||||||
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
if (xf86getSubToken(&(ptr->comment)) != STRING)
|
||||||
|
@ -173,6 +215,8 @@ xf86parseInputClassSection(void)
|
||||||
void
|
void
|
||||||
xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
|
xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
|
||||||
{
|
{
|
||||||
|
char **list;
|
||||||
|
|
||||||
while (ptr) {
|
while (ptr) {
|
||||||
fprintf(cf, "Section \"InputClass\"\n");
|
fprintf(cf, "Section \"InputClass\"\n");
|
||||||
if (ptr->comment)
|
if (ptr->comment)
|
||||||
|
@ -181,12 +225,30 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
|
||||||
fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier);
|
fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier);
|
||||||
if (ptr->driver)
|
if (ptr->driver)
|
||||||
fprintf(cf, "\tDriver \"%s\"\n", ptr->driver);
|
fprintf(cf, "\tDriver \"%s\"\n", ptr->driver);
|
||||||
if (ptr->match_product)
|
if (ptr->match_product) {
|
||||||
fprintf(cf, "\tMatchProduct \"%s\"\n", ptr->match_product);
|
fprintf(cf, "\tMatchProduct \"");
|
||||||
if (ptr->match_vendor)
|
for (list = ptr->match_product; *list; list++)
|
||||||
fprintf(cf, "\tMatchVendor \"%s\"\n", ptr->match_vendor);
|
fprintf(cf, "%s%s",
|
||||||
if (ptr->match_device)
|
list == ptr->match_product ? "" : TOKEN_SEP,
|
||||||
fprintf(cf, "\tMatchDevicePath \"%s\"\n", ptr->match_device);
|
*list);
|
||||||
|
fprintf(cf, "\"\n");
|
||||||
|
}
|
||||||
|
if (ptr->match_vendor) {
|
||||||
|
fprintf(cf, "\tMatchVendor \"");
|
||||||
|
for (list = ptr->match_vendor; *list; list++)
|
||||||
|
fprintf(cf, "%s%s",
|
||||||
|
list == ptr->match_vendor ? "" : TOKEN_SEP,
|
||||||
|
*list);
|
||||||
|
fprintf(cf, "\"\n");
|
||||||
|
}
|
||||||
|
if (ptr->match_device) {
|
||||||
|
fprintf(cf, "\tMatchDevicePath \"");
|
||||||
|
for (list = ptr->match_device; *list; list++)
|
||||||
|
fprintf(cf, "%s%s",
|
||||||
|
list == ptr->match_device ? "" : TOKEN_SEP,
|
||||||
|
*list);
|
||||||
|
fprintf(cf, "\"\n");
|
||||||
|
}
|
||||||
if (ptr->is_keyboard.set)
|
if (ptr->is_keyboard.set)
|
||||||
fprintf(cf, "\tIsKeyboard \"%s\"\n",
|
fprintf(cf, "\tIsKeyboard \"%s\"\n",
|
||||||
ptr->is_keyboard.val ? "yes" : "no");
|
ptr->is_keyboard.val ? "yes" : "no");
|
||||||
|
@ -215,13 +277,26 @@ void
|
||||||
xf86freeInputClassList (XF86ConfInputClassPtr ptr)
|
xf86freeInputClassList (XF86ConfInputClassPtr ptr)
|
||||||
{
|
{
|
||||||
XF86ConfInputClassPtr prev;
|
XF86ConfInputClassPtr prev;
|
||||||
|
char **list;
|
||||||
|
|
||||||
while (ptr) {
|
while (ptr) {
|
||||||
TestFree(ptr->identifier);
|
TestFree(ptr->identifier);
|
||||||
TestFree(ptr->driver);
|
TestFree(ptr->driver);
|
||||||
TestFree(ptr->match_product);
|
if (ptr->match_product) {
|
||||||
TestFree(ptr->match_vendor);
|
for (list = ptr->match_product; *list; list++)
|
||||||
TestFree(ptr->match_device);
|
free(*list);
|
||||||
|
free(ptr->match_product);
|
||||||
|
}
|
||||||
|
if (ptr->match_vendor) {
|
||||||
|
for (list = ptr->match_vendor; *list; list++)
|
||||||
|
free(*list);
|
||||||
|
free(ptr->match_vendor);
|
||||||
|
}
|
||||||
|
if (ptr->match_device) {
|
||||||
|
for (list = ptr->match_device; *list; list++)
|
||||||
|
free(*list);
|
||||||
|
free(ptr->match_device);
|
||||||
|
}
|
||||||
TestFree(ptr->comment);
|
TestFree(ptr->comment);
|
||||||
xf86optionListFree(ptr->option_lst);
|
xf86optionListFree(ptr->option_lst);
|
||||||
|
|
||||||
|
|
|
@ -343,9 +343,9 @@ typedef struct
|
||||||
GenericListRec list;
|
GenericListRec list;
|
||||||
char *identifier;
|
char *identifier;
|
||||||
char *driver;
|
char *driver;
|
||||||
char *match_product;
|
char **match_product;
|
||||||
char *match_vendor;
|
char **match_vendor;
|
||||||
char *match_device;
|
char **match_device;
|
||||||
xf86TriState is_keyboard;
|
xf86TriState is_keyboard;
|
||||||
xf86TriState is_pointer;
|
xf86TriState is_pointer;
|
||||||
xf86TriState is_joystick;
|
xf86TriState is_joystick;
|
||||||
|
|
Loading…
Reference in New Issue