summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xi/stubs.c3
-rw-r--r--config/dbus.c2
-rw-r--r--config/hal.c25
-rw-r--r--configure.ac2
-rw-r--r--hw/dmx/dmxinput.c3
-rw-r--r--hw/kdrive/src/kinput.c3
-rw-r--r--hw/xfree86/common/xf86Module.h2
-rw-r--r--hw/xfree86/common/xf86Option.c25
-rw-r--r--hw/xfree86/common/xf86Xinput.c96
-rw-r--r--hw/xfree86/doc/man/xorg.conf.man.pre96
-rw-r--r--hw/xfree86/parser/Configint.h2
-rw-r--r--hw/xfree86/parser/InputClass.c232
-rw-r--r--hw/xfree86/parser/Makefile.am1
-rw-r--r--hw/xfree86/parser/configProcs.h4
-rw-r--r--hw/xfree86/parser/read.c8
-rw-r--r--hw/xfree86/parser/scan.c30
-rw-r--r--hw/xfree86/parser/write.c2
-rw-r--r--hw/xfree86/parser/xf86Parser.h29
-rw-r--r--hw/xfree86/parser/xf86tokens.h13
-rw-r--r--hw/xquartz/darwinXinput.c3
-rw-r--r--include/dix-config.h.in3
-rw-r--r--include/input.h16
22 files changed, 567 insertions, 33 deletions
diff --git a/Xi/stubs.c b/Xi/stubs.c
index 400e937d1..04ba9769e 100644
--- a/Xi/stubs.c
+++ b/Xi/stubs.c
@@ -227,7 +227,8 @@ ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev,
*
*/
int
-NewInputDeviceRequest(InputOption *options, DeviceIntPtr *pdev)
+NewInputDeviceRequest(InputOption *options, InputAttributes *attrs,
+ DeviceIntPtr *pdev)
{
return BadValue;
}
diff --git a/config/dbus.c b/config/dbus.c
index 37462ace0..86d9d287f 100644
--- a/config/dbus.c
+++ b/config/dbus.c
@@ -147,7 +147,7 @@ add_device(DBusMessage *message, DBusMessage *reply, DBusError *error)
dbus_message_iter_next(&iter);
}
- ret = NewInputDeviceRequest(options, &dev);
+ ret = NewInputDeviceRequest(options, NULL, &dev);
if (ret != Success) {
DebugF("[config/dbus] NewInputDeviceRequest failed\n");
goto unwind;
diff --git a/config/hal.c b/config/hal.c
index 28f55a02f..6bebbdf34 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -191,6 +191,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
{
char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL;
InputOption *options = NULL, *tmpo = NULL;
+ InputAttributes attrs = {0};
DeviceIntPtr dev = NULL;
DBusError error;
struct xkb_options xkb_opts = {0};
@@ -215,10 +216,28 @@ device_added(LibHalContext *hal_ctx, const char *udi)
LogMessage(X_WARNING,"config/hal: no driver or path specified for %s\n", udi);
goto unwind;
}
+ attrs.device = xstrdup(path);
name = get_prop_string(hal_ctx, udi, "info.product");
if (!name)
name = xstrdup("(unnamed)");
+ else
+ attrs.product = xstrdup(name);
+
+ attrs.vendor = get_prop_string(hal_ctx, udi, "info.vendor");
+
+ if (libhal_device_query_capability(hal_ctx, udi, "input.keys", NULL))
+ attrs.flags |= ATTR_KEYBOARD;
+ if (libhal_device_query_capability(hal_ctx, udi, "input.mouse", NULL))
+ attrs.flags |= ATTR_POINTER;
+ if (libhal_device_query_capability(hal_ctx, udi, "input.joystick", NULL))
+ attrs.flags |= ATTR_JOYSTICK;
+ if (libhal_device_query_capability(hal_ctx, udi, "input.tablet", NULL))
+ attrs.flags |= ATTR_TABLET;
+ if (libhal_device_query_capability(hal_ctx, udi, "input.touchpad", NULL))
+ attrs.flags |= ATTR_TOUCHPAD;
+ if (libhal_device_query_capability(hal_ctx, udi, "input.touchscreen", NULL))
+ attrs.flags |= ATTR_TOUCHSCREEN;
options = xcalloc(sizeof(*options), 1);
if (!options){
@@ -400,7 +419,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
/* this isn't an error, but how else do you output something that the user can see? */
LogMessage(X_INFO, "config/hal: Adding input device %s\n", name);
- if ((rc = NewInputDeviceRequest(options, &dev)) != Success) {
+ if ((rc = NewInputDeviceRequest(options, &attrs, &dev)) != Success) {
LogMessage(X_ERROR, "config/hal: NewInputDeviceRequest failed (%d)\n", rc);
dev = NULL;
goto unwind;
@@ -430,6 +449,10 @@ unwind:
xfree(tmpo);
}
+ xfree(attrs.product);
+ xfree(attrs.vendor);
+ xfree(attrs.device);
+
if (xkb_opts.layout)
xfree(xkb_opts.layout);
if (xkb_opts.rules)
diff --git a/configure.ac b/configure.ac
index b55eaaa35..e5eb380bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -122,7 +122,7 @@ AM_CONDITIONAL(SPECIAL_DTRACE_OBJECTS, [test "x$SPECIAL_DTRACE_OBJECTS" = "xyes"
AC_HEADER_DIRENT
AC_HEADER_STDC
-AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h])
+AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h])
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
diff --git a/hw/dmx/dmxinput.c b/hw/dmx/dmxinput.c
index d9118b6a0..c099349d8 100644
--- a/hw/dmx/dmxinput.c
+++ b/hw/dmx/dmxinput.c
@@ -103,7 +103,8 @@ void dmxUpdateWindowInfo(DMXUpdateType type, WindowPtr pWindow)
}
int
-NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
+NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
+ DeviceIntPtr *pdev)
{
return BadRequest;
}
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 65fc75a54..c08459112 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -2249,7 +2249,8 @@ ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev,
}
int
-NewInputDeviceRequest(InputOption *options, DeviceIntPtr *pdev)
+NewInputDeviceRequest(InputOption *options, InputAttributes *attrs,
+ DeviceIntPtr *pdev)
{
InputOption *option = NULL;
KdPointerInfo *pi = NULL;
diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index 8e5d5cfb5..bbf5786c9 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -83,7 +83,7 @@ typedef enum {
*/
#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(7, 0)
-#define ABI_XINPUT_VERSION SET_ABI_VERSION(8, 0)
+#define ABI_XINPUT_VERSION SET_ABI_VERSION(9, 0)
#define ABI_EXTENSION_VERSION SET_ABI_VERSION(3, 0)
#define ABI_FONT_VERSION SET_ABI_VERSION(0, 6)
diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c
index ad8d1c426..a2868bf21 100644
--- a/hw/xfree86/common/xf86Option.c
+++ b/hw/xfree86/common/xf86Option.c
@@ -42,6 +42,7 @@
#include "xf86.h"
#include "xf86Xinput.h"
#include "xf86Optrec.h"
+#include "xf86Parser.h"
static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p,
Bool markUsed);
@@ -456,29 +457,7 @@ xf86ShowUnusedOptions(int scrnIndex, pointer options)
static Bool
GetBoolValue(OptionInfoPtr p, const char *s)
{
- if (*s == '\0') {
- p->value.bool = TRUE;
- } else {
- if (xf86NameCmp(s, "1") == 0)
- p->value.bool = TRUE;
- else if (xf86NameCmp(s, "on") == 0)
- p->value.bool = TRUE;
- else if (xf86NameCmp(s, "true") == 0)
- p->value.bool = TRUE;
- else if (xf86NameCmp(s, "yes") == 0)
- p->value.bool = TRUE;
- else if (xf86NameCmp(s, "0") == 0)
- p->value.bool = FALSE;
- else if (xf86NameCmp(s, "off") == 0)
- p->value.bool = FALSE;
- else if (xf86NameCmp(s, "false") == 0)
- p->value.bool = FALSE;
- else if (xf86NameCmp(s, "no") == 0)
- p->value.bool = FALSE;
- else
- return FALSE;
- }
- return TRUE;
+ return xf86getBoolValue(&p->value.bool, s);
}
static Bool
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index f637cfe19..e0c783089 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -57,9 +57,11 @@
#include <X11/Xatom.h>
#include "xf86.h"
#include "xf86Priv.h"
+#include "xf86Config.h"
#include "xf86Xinput.h"
#include "XIstubs.h"
#include "xf86Optrec.h"
+#include "xf86Parser.h"
#include "mipointer.h"
#include "xf86InPriv.h"
#include "compiler.h"
@@ -74,6 +76,11 @@
#include "exglobals.h"
#include "eventstr.h"
+#include <string.h> /* InputClassMatches */
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+
#include "extnsionst.h"
#include "windowstr.h" /* screenIsSaved */
@@ -466,6 +473,85 @@ AddOtherInputDevices(void)
{
}
+/*
+ * Classes without any Match statements match all devices. Otherwise, all
+ * statements must match.
+ */
+static Bool
+InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs)
+{
+ if (iclass->match_product &&
+ (!attrs->product || !strstr(attrs->product, iclass->match_product)))
+ return False;
+ if (iclass->match_vendor &&
+ (!attrs->vendor || !strstr(attrs->vendor, iclass->match_vendor)))
+ return False;
+ if (iclass->match_device &&
+#ifdef HAVE_FNMATCH_H
+ (!attrs->device ||
+ fnmatch(iclass->match_device, attrs->device, 0) != 0))
+#else
+ (!attrs->device || !strstr(attrs->device, iclass->match_device)))
+#endif
+ return False;
+ if (iclass->is_keyboard.set &&
+ iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD))
+ return False;
+ if (iclass->is_pointer.set &&
+ iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER))
+ return False;
+ if (iclass->is_joystick.set &&
+ iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK))
+ return False;
+ if (iclass->is_tablet.set &&
+ iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET))
+ return False;
+ if (iclass->is_touchpad.set &&
+ iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD))
+ return False;
+ if (iclass->is_touchscreen.set &&
+ iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN))
+ return False;
+ return True;
+}
+
+/*
+ * Merge in any InputClass configurations. Each InputClass section can
+ * add to the original device configuration as well as any previous
+ * InputClass sections.
+ */
+static int
+MergeInputClasses(IDevPtr idev, InputAttributes *attrs)
+{
+ XF86ConfInputClassPtr cl;
+ XF86OptionPtr classopts;
+
+ for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) {
+ if (!InputClassMatches(cl, attrs))
+ continue;
+
+ xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n",
+ idev->identifier, cl->identifier);
+ if (cl->driver && !idev->driver) {
+ idev->driver = xstrdup(cl->driver);
+ if (!idev->driver) {
+ xf86Msg(X_ERROR, "Could not allocate memory while merging "
+ "InputClass configuration");
+ return BadAlloc;
+ }
+ }
+
+ classopts = xf86optionListDup(cl->option_lst);
+ if (idev->commonOptions)
+ idev->commonOptions = xf86optionListMerge(classopts,
+ idev->commonOptions);
+ else
+ idev->commonOptions = classopts;
+ }
+
+ return Success;
+}
+
/**
* Create a new input device, activate and enable it.
*
@@ -568,7 +654,8 @@ unwind:
}
int
-NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
+NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
+ DeviceIntPtr *pdev)
{
IDevRec *idev = NULL;
InputOption *option = NULL;
@@ -635,6 +722,13 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
option->value = NULL;
}
+ /* Apply InputClass settings */
+ if (attrs) {
+ rval = MergeInputClasses(idev, attrs);
+ if (rval != Success)
+ goto unwind;
+ }
+
rval = xf86NewInputDevice(idev, pdev,
(!is_auto || (is_auto && xf86Info.autoEnableDevices)));
if (rval == Success)
diff --git a/hw/xfree86/doc/man/xorg.conf.man.pre b/hw/xfree86/doc/man/xorg.conf.man.pre
index 7941a470a..5b98bda63 100644
--- a/hw/xfree86/doc/man/xorg.conf.man.pre
+++ b/hw/xfree86/doc/man/xorg.conf.man.pre
@@ -144,6 +144,7 @@ The section names are:
.BR "Module " "Dynamic module loading"
.BR "Extensions " "Extension enabling"
.BR "InputDevice " "Input device description"
+.BR "InputClass " "Input class description"
.BR "Device " "Graphics device description"
.BR "VideoAdaptor " "Xv video adaptor description"
.BR "Monitor " "Monitor description"
@@ -914,6 +915,101 @@ may be reattached or set floating at runtime.
.TP 7
.BI "Option \*qSendDragEvents\*q \*q" boolean \*q
???
+.SH "INPUTCLASS SECTION"
+The config file may have multiple
+.B InputClass
+sections.
+These sections are optional and are used to provide configuration for a
+class of input devices as they are automatically added. An input device can
+match more than one
+.B InputClass
+section. Each class can only supplement settings from a previous class, so
+it is best to arrange the sections with the most generic matches last.
+.PP
+.B InputClass
+sections have the following format:
+.PP
+.RS 4
+.nf
+.B "Section \*qInputClass\*q"
+.BI " Identifier \*q" name \*q
+.I " entries"
+.I " ..."
+.I " options"
+.I " ..."
+.B "EndSection"
+.fi
+.RE
+.PP
+The
+.B Identifier
+entry is required in all
+.B InputClass
+sections.
+All other entries are optional.
+.PP
+The
+.B Identifier
+entry specifies the unique name for this input class.
+The
+.B Driver
+entry specifies the name of the driver to use for this input device.
+After all classes have been examined, the
+.RI \*q inputdriver \*q
+module from the final
+.B Driver
+entry will be enabled when using the loadable server.
+.PP
+When an input device is automatically added, its characteristics are
+checked against all
+.B InputClass
+sections. Each section can contain optional entries to narrow the match
+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
+.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.
+.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.
+.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.
+.TP 7
+.BI "MatchIsKeyboard \*q" bool \*q
+.TP 7
+.BI "MatchIsPointer \*q" bool \*q
+.TP 7
+.BI "MatchIsJoystick \*q" bool \*q
+.TP 7
+.BI "MatchIsTablet \*q" bool \*q
+.TP 7
+.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
+section, any
+.B Option
+entries are applied to the device. See the
+.B InputDevice
+section above for a description of the various
+.B Option
+entries.
.SH "DEVICE SECTION"
The config file may have multiple
.B Device
diff --git a/hw/xfree86/parser/Configint.h b/hw/xfree86/parser/Configint.h
index cdc7be806..03509b397 100644
--- a/hw/xfree86/parser/Configint.h
+++ b/hw/xfree86/parser/Configint.h
@@ -148,6 +148,8 @@ else\
"The %s keyword requires a number to follow it."
#define POSITIVE_INT_MSG \
"The %s keyword requires a positive integer to follow it."
+#define BOOL_MSG \
+"The %s keyword requires a boolean to follow it."
#define ZAXISMAPPING_MSG \
"The ZAxisMapping keyword requires 2 positive numbers or X or Y to follow it."
#define AUTOREPEAT_MSG \
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
new file mode 100644
index 000000000..1c9816012
--- /dev/null
+++ b/hw/xfree86/parser/InputClass.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2009 Dan Nicholson
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* View/edit this file with tab stops set to 4 */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static
+xf86ConfigSymTabRec InputClassTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {DRIVER, "driver"},
+ {MATCH_PRODUCT, "matchproduct"},
+ {MATCH_VENDOR, "matchvendor"},
+ {MATCH_DEVICE_PATH, "matchdevicepath"},
+ {MATCH_IS_KEYBOARD, "matchiskeyboard"},
+ {MATCH_IS_POINTER, "matchispointer"},
+ {MATCH_IS_JOYSTICK, "matchisjoystick"},
+ {MATCH_IS_TABLET, "matchistablet"},
+ {MATCH_IS_TOUCHPAD, "matchistouchpad"},
+ {MATCH_IS_TOUCHSCREEN, "matchistouchscreen"},
+ {-1, ""},
+};
+
+#define CLEANUP xf86freeInputClassList
+
+XF86ConfInputClassPtr
+xf86parseInputClassSection(void)
+{
+ int has_ident = FALSE;
+ int token;
+
+ parsePrologue(XF86ConfInputClassPtr, XF86ConfInputClassRec)
+
+ while ((token = xf86getToken(InputClassTab)) != ENDSECTION) {
+ switch (token) {
+ case COMMENT:
+ ptr->comment = xf86addComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error(MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case DRIVER:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "Driver");
+ if (strcmp(val.str, "keyboard") == 0)
+ ptr->driver = "kbd";
+ else
+ ptr->driver = val.str;
+ break;
+ case OPTION:
+ ptr->option_lst = xf86parseOption(ptr->option_lst);
+ break;
+ case MATCH_PRODUCT:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchProduct");
+ ptr->match_product = val.str;
+ break;
+ case MATCH_VENDOR:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchVendor");
+ ptr->match_vendor = val.str;
+ break;
+ case MATCH_DEVICE_PATH:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchDevicePath");
+ ptr->match_device = val.str;
+ break;
+ case MATCH_IS_KEYBOARD:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchIsKeyboard");
+ ptr->is_keyboard.set = xf86getBoolValue(&ptr->is_keyboard.val,
+ val.str);
+ if (!ptr->is_keyboard.set)
+ Error(BOOL_MSG, "MatchIsKeyboard");
+ break;
+ case MATCH_IS_POINTER:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchIsPointer");
+ ptr->is_pointer.set = xf86getBoolValue(&ptr->is_pointer.val,
+ val.str);
+ if (!ptr->is_pointer.set)
+ Error(BOOL_MSG, "MatchIsPointer");
+ break;
+ case MATCH_IS_JOYSTICK:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchIsJoystick");
+ ptr->is_joystick.set = xf86getBoolValue(&ptr->is_joystick.val,
+ val.str);
+ if (!ptr->is_joystick.set)
+ Error(BOOL_MSG, "MatchIsJoystick");
+ break;
+ case MATCH_IS_TABLET:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchIsTablet");
+ ptr->is_tablet.set = xf86getBoolValue(&ptr->is_tablet.val,
+ val.str);
+ if (!ptr->is_tablet.set)
+ Error(BOOL_MSG, "MatchIsTablet");
+ break;
+ case MATCH_IS_TOUCHPAD:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchIsTouchpad");
+ ptr->is_touchpad.set = xf86getBoolValue(&ptr->is_touchpad.val,
+ val.str);
+ if (!ptr->is_touchpad.set)
+ Error(BOOL_MSG, "MatchIsTouchpad");
+ break;
+ case MATCH_IS_TOUCHSCREEN:
+ if (xf86getSubToken(&(ptr->comment)) != STRING)
+ Error(QUOTE_MSG, "MatchIsTouchscreen");
+ ptr->is_touchscreen.set = xf86getBoolValue(&ptr->is_touchscreen.val,
+ val.str);
+ if (!ptr->is_touchscreen.set)
+ Error(BOOL_MSG, "MatchIsTouchscreen");
+ break;
+ case EOF_TOKEN:
+ Error(UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error(INVALID_KEYWORD_MSG, xf86tokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error(NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ printf("InputClass section parsed\n");
+#endif
+
+ return ptr;
+}
+
+void
+xf86printInputClassSection (FILE * cf, XF86ConfInputClassPtr ptr)
+{
+ while (ptr) {
+ fprintf(cf, "Section \"InputClass\"\n");
+ if (ptr->comment)
+ fprintf(cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf(cf, "\tIdentifier \"%s\"\n", ptr->identifier);
+ if (ptr->driver)
+ fprintf(cf, "\tDriver \"%s\"\n", ptr->driver);
+ if (ptr->match_product)
+ fprintf(cf, "\tMatchProduct \"%s\"\n", ptr->match_product);
+ if (ptr->match_vendor)
+ fprintf(cf, "\tMatchVendor \"%s\"\n", ptr->match_vendor);
+ if (ptr->match_device)
+ fprintf(cf, "\tMatchDevicePath \"%s\"\n", ptr->match_device);
+ if (ptr->is_keyboard.set)
+ fprintf(cf, "\tIsKeyboard \"%s\"\n",
+ ptr->is_keyboard.val ? "yes" : "no");
+ if (ptr->is_pointer.set)
+ fprintf(cf, "\tIsPointer \"%s\"\n",
+ ptr->is_pointer.val ? "yes" : "no");
+ if (ptr->is_joystick.set)
+ fprintf(cf, "\tIsJoystick \"%s\"\n",
+ ptr->is_joystick.val ? "yes" : "no");
+ if (ptr->is_tablet.set)
+ fprintf(cf, "\tIsTablet \"%s\"\n",
+ ptr->is_tablet.val ? "yes" : "no");
+ if (ptr->is_touchpad.set)
+ fprintf(cf, "\tIsTouchpad \"%s\"\n",
+ ptr->is_touchpad.val ? "yes" : "no");
+ if (ptr->is_touchscreen.set)
+ fprintf(cf, "\tIsTouchscreen \"%s\"\n",
+ ptr->is_touchscreen.val ? "yes" : "no");
+ xf86printOptionList(cf, ptr->option_lst, 1);
+ fprintf(cf, "EndSection\n\n");
+ ptr = ptr->list.next;
+ }
+}
+
+void
+xf86freeInputClassList (XF86ConfInputClassPtr ptr)
+{
+ XF86ConfInputClassPtr prev;
+
+ while (ptr) {
+ TestFree(ptr->identifier);
+ TestFree(ptr->driver);
+ TestFree(ptr->match_product);
+ TestFree(ptr->match_vendor);
+ TestFree(ptr->match_device);
+ TestFree(ptr->comment);
+ xf86optionListFree(ptr->option_lst);
+
+ prev = ptr;
+ ptr = ptr->list.next;
+ free(prev);
+ }
+}
diff --git a/hw/xfree86/parser/Makefile.am b/hw/xfree86/parser/Makefile.am
index b8fab2835..49c191f2a 100644
--- a/hw/xfree86/parser/Makefile.am
+++ b/hw/xfree86/parser/Makefile.am
@@ -13,6 +13,7 @@ INTERNAL_SOURCES= \
Files.c \
Flags.c \
Input.c \
+ InputClass.c \
Layout.c \
Module.c \
Video.c \
diff --git a/hw/xfree86/parser/configProcs.h b/hw/xfree86/parser/configProcs.h
index 26ba40ebb..7d8a8e53a 100644
--- a/hw/xfree86/parser/configProcs.h
+++ b/hw/xfree86/parser/configProcs.h
@@ -48,6 +48,10 @@ XF86ConfInputPtr xf86parseInputSection(void);
void xf86printInputSection(FILE *f, XF86ConfInputPtr ptr);
void xf86freeInputList(XF86ConfInputPtr ptr);
int xf86validateInput (XF86ConfigPtr p);
+/* InputClass.c */
+XF86ConfInputClassPtr xf86parseInputClassSection(void);
+void xf86printInputClassSection(FILE *f, XF86ConfInputClassPtr ptr);
+void xf86freeInputClassList(XF86ConfInputClassPtr ptr);
/* Layout.c */
XF86ConfLayoutPtr xf86parseLayoutSection(void);
void xf86printLayoutSection(FILE *cf, XF86ConfLayoutPtr ptr);
diff --git a/hw/xfree86/parser/read.c b/hw/xfree86/parser/read.c
index e965d209e..1091be5e5 100644
--- a/hw/xfree86/parser/read.c
+++ b/hw/xfree86/parser/read.c
@@ -177,6 +177,14 @@ xf86readConfigFile (void)
HANDLE_LIST (conf_input_lst, xf86parseInputSection,
XF86ConfInputPtr);
}
+ else if (xf86nameCompare(val.str, "inputclass") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ HANDLE_LIST (conf_inputclass_lst,
+ xf86parseInputClassSection,
+ XF86ConfInputClassPtr);
+ }
else if (xf86nameCompare (val.str, "module") == 0)
{
free(val.str);
diff --git a/hw/xfree86/parser/scan.c b/hw/xfree86/parser/scan.c
index 9f1835085..b80fbfb8f 100644
--- a/hw/xfree86/parser/scan.c
+++ b/hw/xfree86/parser/scan.c
@@ -1186,3 +1186,33 @@ xf86addComment(char *cur, char *add)
return (cur);
}
+
+Bool
+xf86getBoolValue(Bool *val, const char *str)
+{
+ if (!val || !str)
+ return FALSE;
+ if (*str == '\0') {
+ *val = TRUE;
+ } else {
+ if (strcmp(str, "1") == 0)
+ *val = TRUE;
+ else if (strcmp(str, "on") == 0)
+ *val = TRUE;
+ else if (strcmp(str, "true") == 0)
+ *val = TRUE;
+ else if (strcmp(str, "yes") == 0)
+ *val = TRUE;
+ else if (strcmp(str, "0") == 0)
+ *val = FALSE;
+ else if (strcmp(str, "off") == 0)
+ *val = FALSE;
+ else if (strcmp(str, "false") == 0)
+ *val = FALSE;
+ else if (strcmp(str, "no") == 0)
+ *val = FALSE;
+ else
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/hw/xfree86/parser/write.c b/hw/xfree86/parser/write.c
index 3b77b9314..083203c05 100644
--- a/hw/xfree86/parser/write.c
+++ b/hw/xfree86/parser/write.c
@@ -117,6 +117,8 @@ doWriteConfigFile (const char *filename, XF86ConfigPtr cptr)
xf86printInputSection (cf, cptr->conf_input_lst);
+ xf86printInputClassSection (cf, cptr->conf_inputclass_lst);
+
xf86printVideoAdaptorSection (cf, cptr->conf_videoadaptor_lst);
xf86printModesSection (cf, cptr->conf_modes_lst);
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index 4675d02c7..5e8351fc4 100644
--- a/hw/xfree86/parser/xf86Parser.h
+++ b/hw/xfree86/parser/xf86Parser.h
@@ -64,6 +64,7 @@
#ifndef _xf86Parser_h_
#define _xf86Parser_h_
+#include <X11/Xdefs.h>
#include "xf86Optrec.h"
#define HAVE_PARSER_DECLS
@@ -330,6 +331,32 @@ typedef struct
}
XF86ConfInputrefRec, *XF86ConfInputrefPtr;
+typedef struct
+{
+ Bool set;
+ Bool val;
+}
+xf86TriState;
+
+typedef struct
+{
+ GenericListRec list;
+ char *identifier;
+ char *driver;
+ char *match_product;
+ char *match_vendor;
+ char *match_device;
+ xf86TriState is_keyboard;
+ xf86TriState is_pointer;
+ xf86TriState is_joystick;
+ xf86TriState is_tablet;
+ xf86TriState is_touchpad;
+ xf86TriState is_touchscreen;
+ XF86OptionPtr option_lst;
+ char *comment;
+}
+XF86ConfInputClassRec, *XF86ConfInputClassPtr;
+
/* Values for adj_where */
#define CONF_ADJ_OBSOLETE -1
#define CONF_ADJ_ABSOLUTE 0
@@ -438,6 +465,7 @@ typedef struct
XF86ConfDevicePtr conf_device_lst;
XF86ConfScreenPtr conf_screen_lst;
XF86ConfInputPtr conf_input_lst;
+ XF86ConfInputClassPtr conf_inputclass_lst;
XF86ConfLayoutPtr conf_layout_lst;
XF86ConfVendorPtr conf_vendor_lst;
XF86ConfDRIPtr conf_dri;
@@ -484,5 +512,6 @@ extern _X_EXPORT int xf86itemNotSublist(GenericListPtr list_1, GenericListPtr li
extern _X_EXPORT int xf86pathIsAbsolute(const char *path);
extern _X_EXPORT int xf86pathIsSafe(const char *path);
extern _X_EXPORT char *xf86addComment(char *cur, char *add);
+extern _X_EXPORT Bool xf86getBoolValue(Bool *val, const char *str);
#endif /* _xf86Parser_h_ */
diff --git a/hw/xfree86/parser/xf86tokens.h b/hw/xfree86/parser/xf86tokens.h
index 4c1d38c03..e3a9d716b 100644
--- a/hw/xfree86/parser/xf86tokens.h
+++ b/hw/xfree86/parser/xf86tokens.h
@@ -273,7 +273,18 @@ typedef enum {
/* DRI Tokens */
GROUP,
- BUFFERS
+ BUFFERS,
+
+ /* InputClass Tokens */
+ MATCH_PRODUCT,
+ MATCH_VENDOR,
+ MATCH_DEVICE_PATH,
+ MATCH_IS_KEYBOARD,
+ MATCH_IS_POINTER,
+ MATCH_IS_JOYSTICK,
+ MATCH_IS_TABLET,
+ MATCH_IS_TOUCHPAD,
+ MATCH_IS_TOUCHSCREEN
} ParserTokens;
#endif /* _xf86_tokens_h */
diff --git a/hw/xquartz/darwinXinput.c b/hw/xquartz/darwinXinput.c
index 8af9fc740..43aea6140 100644
--- a/hw/xquartz/darwinXinput.c
+++ b/hw/xquartz/darwinXinput.c
@@ -230,7 +230,8 @@ ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev,
*
*/
int
-NewInputDeviceRequest(InputOption *options, DeviceIntPtr *pdev)
+NewInputDeviceRequest(InputOption *options, InputAttributes *attrs,
+ DeviceIntPtr *pdev)
{
DEBUG_LOG("NewInputDeviceRequest(%p, %p)\n", options, pdev);
return BadValue;
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 109637115..ab04414f1 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -231,6 +231,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#undef HAVE_FNMATCH_H
+
/* Have /dev/urandom */
#undef HAVE_URANDOM
diff --git a/include/input.h b/include/input.h
index afcc006f8..7a6242d08 100644
--- a/include/input.h
+++ b/include/input.h
@@ -52,6 +52,7 @@ SOFTWARE.
#include "screenint.h"
#include <X11/Xmd.h>
#include <X11/Xproto.h>
+#include <stdint.h>
#include "window.h" /* for WindowPtr */
#include "xkbrules.h"
#include "events.h"
@@ -210,6 +211,20 @@ typedef struct _InputOption {
struct _InputOption *next;
} InputOption;
+typedef struct _InputAttributes {
+ char *product;
+ char *vendor;
+ char *device;
+ uint32_t flags;
+} InputAttributes;
+
+#define ATTR_KEYBOARD (1<<0)
+#define ATTR_POINTER (1<<1)
+#define ATTR_JOYSTICK (1<<2)
+#define ATTR_TABLET (1<<3)
+#define ATTR_TOUCHPAD (1<<4)
+#define ATTR_TOUCHSCREEN (1<<5)
+
/* Key has been run through all input processing and events sent to clients. */
#define KEY_PROCESSED 1
/* Key has not been fully processed, no events have been sent. */
@@ -514,6 +529,7 @@ void FixUpEventFromWindow(DeviceIntPtr pDev,
/* Implemented by the DDX. */
extern _X_EXPORT int NewInputDeviceRequest(
InputOption *options,
+ InputAttributes *attrs,
DeviceIntPtr *dev);
extern _X_EXPORT void DeleteInputDeviceRequest(
DeviceIntPtr dev);