From c6d9bc092c84ad5c68083a126aa7577baa42cef7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 10 Feb 2010 15:36:50 +1000 Subject: [PATCH] Add tag matching to input attributes. Tags may be a list of comma-separated strings that match against a MatchTag InputClass section. If any of the tags specified for a device match against the MatchTag of the section, this match is evaluated true and passed on to the next match condition. Tags are specified as "input.tags" (hal) or "ID_INPUT.tags" (udev), the value of the tags is case-sensitive and require an exact match (not a substring match). i.e. "quirk" will not match "QUIRK", "need_quirk" or "quirk_needed". Example configuration: udev: ENV{ID_INPUT.tags}="foo,bar" hal: foo,bar xorg.conf: Section "InputClass" Identifier "foobar quirks" MatchTag "foo|foobar" Option "Foobar" "on" EndSection Where the xorg.conf section matches against any device with the tag "foo" or tag "foobar" set. Signed-off-by: Peter Hutterer Tested-by: Dan Nicholson Reviewed-by: Dan Nicholson --- config/hal.c | 9 +++++++++ config/udev.c | 10 ++++++++++ hw/xfree86/common/xf86Xinput.c | 18 ++++++++++++++++++ hw/xfree86/doc/man/xorg.conf.man.pre | 9 +++++++++ hw/xfree86/parser/InputClass.c | 19 +++++++++++++++++++ hw/xfree86/parser/xf86Parser.h | 1 + hw/xfree86/parser/xf86tokens.h | 1 + include/input.h | 1 + 8 files changed, 68 insertions(+) diff --git a/config/hal.c b/config/hal.c index 1b01eccaa..d3daa84cd 100644 --- a/config/hal.c +++ b/config/hal.c @@ -164,6 +164,7 @@ device_added(LibHalContext *hal_ctx, const char *udi) attrs.product = xstrdup(name); attrs.vendor = get_prop_string(hal_ctx, udi, "info.vendor"); + attrs.tags = xstrtokenize(get_prop_string(hal_ctx, udi, "input.tags"), ","); if (libhal_device_query_capability(hal_ctx, udi, "input.keys", NULL)) attrs.flags |= ATTR_KEYBOARD; @@ -391,6 +392,14 @@ unwind: xfree(attrs.product); xfree(attrs.vendor); xfree(attrs.device); + if (attrs.tags) { + char **tag = attrs.tags; + while (*tag) { + xfree(*tag); + tag++; + } + xfree(attrs.tags); + } if (xkb_opts.layout) xfree(xkb_opts.layout); diff --git a/config/udev.c b/config/udev.c index 3ef0d7fb3..432ab85e9 100644 --- a/config/udev.c +++ b/config/udev.c @@ -84,6 +84,7 @@ device_added(struct udev_device *udev_device) add_option(&options, "path", path); add_option(&options, "device", path); attrs.device = path; + attrs.tags = xstrtokenize(udev_device_get_property_value(udev_device, "ID_INPUT.tags"), ","); config_info = Xprintf("udev:%s", syspath); if (!config_info) @@ -150,6 +151,15 @@ device_added(struct udev_device *udev_device) xfree(tmpo); } + if (attrs.tags) { + char **tag = attrs.tags; + while (*tag) { + xfree(*tag); + tag++; + } + xfree(attrs.tags); + } + return; } diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index 46047108f..c2d9f49de 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -545,6 +545,24 @@ InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs) if (!match) return FALSE; } + if (iclass->match_tag) { + if (!attrs->tags) + return FALSE; + + for (cur = iclass->match_tag, match = FALSE; *cur && !match; cur++) { + const char *tag; + for(tag = *attrs->tags; *tag; tag++) { + if (!strcmp(tag, *cur)) { + match = TRUE; + break; + } + } + } + + if (!match) + return FALSE; + } + if (iclass->is_keyboard.set && iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) return FALSE; diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre index 69f475107..c8a3c3ac2 100644 --- a/hw/xfree86/doc/man/xorg.conf.man.pre +++ b/hw/xfree86/doc/man/xorg.conf.man.pre @@ -1054,6 +1054,15 @@ This entry can be used to check if the device file matches the pathname pattern. Multiple patterns 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 +.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 +.RI \*q matchtag \*q +matches at least one of the tags assigned by the backend. +.TP 7 .BI "MatchIsKeyboard \*q" bool \*q .TP 7 .BI "MatchIsPointer \*q" bool \*q diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c index 9fabb22cd..7fb2866cd 100644 --- a/hw/xfree86/parser/InputClass.c +++ b/hw/xfree86/parser/InputClass.c @@ -47,6 +47,7 @@ xf86ConfigSymTabRec InputClassTab[] = {MATCH_PRODUCT, "matchproduct"}, {MATCH_VENDOR, "matchvendor"}, {MATCH_DEVICE_PATH, "matchdevicepath"}, + {MATCH_TAG, "matchtag"}, {MATCH_IS_KEYBOARD, "matchiskeyboard"}, {MATCH_IS_POINTER, "matchispointer"}, {MATCH_IS_JOYSTICK, "matchisjoystick"}, @@ -107,6 +108,11 @@ xf86parseInputClassSection(void) Error(QUOTE_MSG, "MatchDevicePath"); ptr->match_device = 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); + break; case MATCH_IS_KEYBOARD: if (xf86getSubToken(&(ptr->comment)) != STRING) Error(QUOTE_MSG, "MatchIsKeyboard"); @@ -211,6 +217,14 @@ xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr) *list); 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); + fprintf(cf, "\"\n"); + } if (ptr->is_keyboard.set) fprintf(cf, "\tIsKeyboard \"%s\"\n", ptr->is_keyboard.val ? "yes" : "no"); @@ -259,6 +273,11 @@ xf86freeInputClassList (XF86ConfInputClassPtr ptr) free(*list); free(ptr->match_device); } + if (ptr->match_tag) { + for (list = ptr->match_tag; *list; list++) + free(*list); + free(ptr->match_tag); + } TestFree(ptr->comment); xf86optionListFree(ptr->option_lst); diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h index b6d40a1f3..d79544a20 100644 --- a/hw/xfree86/parser/xf86Parser.h +++ b/hw/xfree86/parser/xf86Parser.h @@ -346,6 +346,7 @@ typedef struct char **match_product; char **match_vendor; char **match_device; + char **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 e3a9d716b..cb600704b 100644 --- a/hw/xfree86/parser/xf86tokens.h +++ b/hw/xfree86/parser/xf86tokens.h @@ -279,6 +279,7 @@ typedef enum { MATCH_PRODUCT, MATCH_VENDOR, MATCH_DEVICE_PATH, + MATCH_TAG, MATCH_IS_KEYBOARD, MATCH_IS_POINTER, MATCH_IS_JOYSTICK, diff --git a/include/input.h b/include/input.h index 7a6242d08..4a845bedf 100644 --- a/include/input.h +++ b/include/input.h @@ -215,6 +215,7 @@ typedef struct _InputAttributes { char *product; char *vendor; char *device; + char **tags; /* null-terminated */ uint32_t flags; } InputAttributes;