diff options
author | Adam Jackson <ajax@redhat.com> | 2008-03-08 20:18:02 -0500 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2008-03-08 20:27:02 -0500 |
commit | 9773dac6238b64cab1d42b2231097b23058c44ee (patch) | |
tree | 1dd2e11623ed072932bb7a368c05048367ec2cc1 | |
parent | Updated manpage to reflect current state (diff) | |
parent | Force maximum keycode to be 255 (diff) | |
download | xf86-input-evdev-9773dac6238b64cab1d42b2231097b23058c44ee.tar.gz xf86-input-evdev-9773dac6238b64cab1d42b2231097b23058c44ee.tar.bz2 xf86-input-evdev-9773dac6238b64cab1d42b2231097b23058c44ee.zip |
Merge branch 'evdev-2.0-branch'
This resets to before the ad-hoc input hotplug state, ports that to
current server ABI, adds input hotplug integration, and re-adds support
for absolute coordinate events and XKB. Several other small fixes were
cherry-picked from the new 1.2 branch.
-rw-r--r-- | .cvsignore (renamed from .gitignore) | 6 | ||||
-rw-r--r-- | ChangeLog | 47 | ||||
-rw-r--r-- | Makefile.am | 11 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | man/.cvsignore (renamed from man/.gitignore) | 1 | ||||
-rw-r--r-- | man/evdev.man | 189 | ||||
-rw-r--r-- | src/.cvsignore (renamed from src/.gitignore) | 0 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/evdev.c | 1344 | ||||
-rw-r--r-- | src/evdev.h | 272 | ||||
-rw-r--r-- | src/evdev_axes.c | 943 | ||||
-rw-r--r-- | src/evdev_btn.c | 465 | ||||
-rw-r--r-- | src/evdev_key.c | 567 |
13 files changed, 1001 insertions, 2852 deletions
@@ -1,13 +1,9 @@ Makefile Makefile.in -ChangeLog -xf86-input-evdev-*.tar.bz2 -xf86-input-evdev-*.tar.gz *.la *.lo aclocal.m4 autom4te.cache -compile config.guess config.h config.h.in @@ -21,5 +17,3 @@ libtool ltmain.sh missing stamp-h1 -.*.swp -*~ diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..2c448ae --- /dev/null +++ b/ChangeLog @@ -0,0 +1,47 @@ +2006-01-09 David Nusinow,,, <set EMAIL_ADDRESS environment variable> + + * man/Makefile.am: + * man/evdev.man: + Bugzilla #968 <https://bugs.freedesktop.org/show_bug.cgi?id=968> + Patch #4301 <https://bugs.freedesktop.org/attachment.cgi?id=4301> + Add evdev manpage + +2005-12-20 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update package version for X11R7 release. + +2005-12-14 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update package version number for final X11R7 release candidate. + +2005-12-06 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * man/Makefile.am: + Change *man_SOURCES ==> *man_PRE to fix autotools warnings. + +2005-12-03 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update package version number for X11R7 RC3 release. + +2005-12-01 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Remove extraneous AC_MSG_RESULT. + +2005-11-29 Adam Jackson <ajax@freedesktop.org> + + * configure.ac: + Only build dlloader modules by default. + +2005-11-09 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update package version number for X11R7 RC2 release. + +2005-11-01 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update pkgcheck dependencies to work with separate build roots. diff --git a/Makefile.am b/Makefile.am index b04f7aa..7052905 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,14 +20,3 @@ AUTOMAKE_OPTIONS = foreign SUBDIRS = src man - -EXTRA_DIST=ChangeLog - -CLEANFILES=ChangeLog - -.PHONY: ChangeLog - -ChangeLog: - (GIT_DIR=$(top_srcdir)/.git git-log > .changelog.tmp && mv .changelog.tmp ChangeLog; rm -f .changelog.tmp) || (touch ChangeLog; echo 'git directory not found: installing possibly empty changelog.' >&2) - -dist-hook: ChangeLog diff --git a/configure.ac b/configure.ac index 26006a0..7c8b681 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.57) AC_INIT([xf86-input-evdev], - 1.2.0, + 1.99.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xf86-input-evdev) @@ -71,8 +71,7 @@ inputdir=${moduledir}/input AC_SUBST(inputdir) # Checks for extensions -#XORG_DRIVER_CHECK_EXT(RANDR, randrproto) -XORG_DRIVER_CHECK_EXT(XKB, kbproto) +XORG_DRIVER_CHECK_EXT(RANDR, randrproto) XORG_DRIVER_CHECK_EXT(XINPUT, inputproto) # Checks for pkg-config packages diff --git a/man/.gitignore b/man/.cvsignore index c060ea5..282522d 100644 --- a/man/.gitignore +++ b/man/.cvsignore @@ -1,3 +1,2 @@ Makefile Makefile.in -evdev.4 diff --git a/man/evdev.man b/man/evdev.man index 72d780b..2ad5552 100644 --- a/man/evdev.man +++ b/man/evdev.man @@ -14,7 +14,7 @@ evdev \- Generic Linux input driver .fi .SH DESCRIPTION .B evdev -is an __xservername__ input driver for Linux's generic event devices. It +is an __xservername__ input driver for Linux\'s generic event devices. It therefore supports all input devices that the kernel knows about, including most mice and keyboards. .PP @@ -22,7 +22,9 @@ The .B evdev driver can serve as both a pointer and a keyboard input device, and may be used as both the core keyboard and the core pointer. Multiple input devices -are supported by multiple instances of this driver. +are supported by multiple instances of this driver, with one Load +directive for evdev in the Module section of your __xconfigfile__ for each +input device that will use this driver. .PP .SH SUPPORTED HARDWARE In general, any input device that the kernel has a driver for can be accessed @@ -35,182 +37,17 @@ Please refer to __xconfigfile__(__filemansuffix__) for general configuration details and for options that can be used with all input drivers. This section only covers configuration details specific to this driver. .PP -.SH BASIC CONFIGURATIONS -Most users of this driver will probably be quite happy with the following for -all keyboards and mice: -.PP -.nf -.B "Section \*qInputDevice\*q" -.BI " Identifier \*q" keyboard \*q -.B " Driver \*qevdev\*q" -.BI " Option \*qDevice\*q \*q" "/dev/input/by-path/..." \*q -\ \ ... -.B EndSection -.fi -.PP -.SH ADVANCED OPTIONS -.SS DEVICE SPECIFICATION -.TP 7 -.BI "Option \*qPath\*q \*q" string \*q -.TP 7 -.BI "Option \*qDevice\*q \*q" string \*q -Specifies the device node through which the device can be accessed. -You might want to use the more persistent symlinks provided in /dev/input/by-id -or /dev/input/by-path. -.fi -This parameter is mandatory. -.TP 7 -.BI "Option \*qMode\*q \*q" mode \*q -This selects the default mode for the device. -.fi -Valid values are \*qabsolute\*q and \*qrelative\*q. -.fi -This can be set at run time per actual device with the xinput utility. -.PP -.SS RELATIVE AXIS CONFIGURATION -The relative axis portion of this driver handle all reported relative axes. -.fi -The axes are named X, Y, Z, RX, RY, RZ, HWHEEL, DIAL, WHEEL, MISC, 10, 11, -12, 13, 14, and 15. -.fi -The axes are reported to X as valuators, with the default mapping of axes -to valuators being the first axes found to the first valuator, the second -found to the second valuator, and so on, so that if you have axes X, Y, -HWHEEL, and WHEEL, you would have X=0, Y=1, HWHEEL=2, WHEEL=3. -.fi -If the driver is reporting core events, valuators 0 and 1 are always mapped -to x and y coordinates, respectively. -.fi The following driver .B Options -control the relative axis portion of the driver: -.TP 7 -.BI "Option \*qRel" "%s" "MapTo\*q \*q" string \*q -This remaps the axis specified by -.I "%s" -to -.IR string . -See Section -.B "AXIS MAPPING" -for valid values. +are supported: .TP 7 -.BI "Option \*qRel" "%s" "Options\*q \*q" "string" \*q -This sets some options for the relative axis specified by -.IR %s . -Valid value -is \*qinvert\*q. -.fi -<documentation needed> -.PP -.SS ABSOLUTE AXIS CONFIGURATION -The absolute axis portion of this driver handles all reported absolute axes. -.fi -The axes are named X, Y, Z, RX, RY, RZ, THROTTLE, RUDDER, WHEEL, GAS, BRAKE, -<11\-15>, HAT0X, HAT0Y, HAT1X, HAT1Y, HAT2X, HAT2Y, HAT3X, HAT3Y, PRESSURE, -TILT_X, TILT_Y, TOOL_WIDTH, VOLUME, <29\-39>, MISC, <41\-62>. -.fi -The axes are reported to X as valuators, with the default mapping of axes -to valuators being the first axes found to the first valuator, the second -found to the second valuator, and so on, so that if you have axes X, Y, -TILT_X, and TILT_Y, you would have X=0, Y=1, TILT_X=2, TILT_Y=3. -.fi -If the driver is reporting core events, valuators 0 and 1 are always mapped -to x and y coordinates, respectively. -.fi -The following driver -.B Options -control the absolute axis portion of the driver: -.TP 7 -.BI "Option \*qAbs" "%s" "MapTo\*q \*q" string \*q -This remaps the axis specified by -.I "%s" -to -.IR string . -See Section -.B "AXIS MAPPING" -for valid values. -.TP 7 -.BI "Option \*qAbs" "%s" "Options\*q \*q" string \*q -This sets some options for the absolute axis specified by -.IR "%s" . -.fi -Valid values are \*qinvert\*q, \*quse_touch\*q, \*qmode_auto\*q, -\*qmode_rel\*q. -.fi -<documentation needed> -.TP 7 -.BI "Option \*qAbsoluteTouch\*q \*q" string \*q -<documentation needed> -.fi -Default: DIGI_Touch -.PP -.SS AXIS MAPPING -The following axis mappings are recognized: -.TP 7 -.BI "\*qRelAxis " <axis> \*q -Map the axis to the specified -.I <axis> -in relative mode. This can be either a number or a name. -.TP 7 -.BI "\*qAbsAxis " "<axis> <min> <max>" \*q -Maps the axis to the specified -.I <axis> -in absolute mode. This can be either a number or a name. -.TP 7 -.BI "\*qButton " "<button>" \*q -Maps the button to the button specified with -.IR <button> . -This can be either a button number or a name. -.TP 7 -.BI "\*qButtons " "<button+> <button->" \*q -Maps the positive axis to the button specified with -.I <button+> -and the negative axis to the button specified with -.IR <button-> . -These can be either button numbers or names. -.PP -.SS BUTTON CONFIGURATION -At the moment, the button portion of this driver only handles buttons -reported as mouse buttons, that is from BTN_MOUSE to BTN_JOYSTICK \- 1. -.fi -At this time there are no configuration options for buttons. -.SS KEYBOARD CONFIGURATION -The keyboard portion of this driver handles all keys reported and requires -XKB support. -.fi -The following driver -.B Options -control the relative axis portion of the driver: -.TP 7 -.BI "Option \*qXkbRules\*q \*q" rules \*q -specifies which XKB rules file to use for interpreting the -.BR XkbModel , -.BR XkbLayout , -.BR XkbVariant , -and -.B XkbOptions -settings. Default: \*qxorg\*q for most platforms, but \*qxfree98\*q for the -Japanese PC-98 platforms. -.TP 7 -.BI "Option \*qXkbModel\*q \*q" modelname \*q -specifies the XKB keyboard model name. Default: \*qevdev\*q. -.TP 7 -.BI "Option \*qXkbLayout\*q \*q" layoutname \*q -specifies the XKB keyboard layout name. This is usually the country or -language type of the keyboard. Default: \*qus\*q. -.TP 7 -.BI "Option \*qXkbVariant\*q \*q" variants \*q -specifies the XKB keyboard variant components. These can be used to -enhance the keyboard layout details. Default: not set. -.TP 7 -.BI "Option \*qXkbOptions\*q \*q" options \*q -specifies the XKB keyboard option components. These can be used to -enhance the keyboard behaviour. Default: not set. - -.PP +.BI "Option \*qDevice\*q \*q" string \*q +Specifies the device through which the device can be accessed. This will +generally be of the form \*q/dev/input/eventX\*q, where X is some integer. +The mapping from device node to hardware is system-dependent. This option is +mandatory, and there is no default setting. .SH AUTHORS -Zephaniah E. Hull. -.fi -Kristian H\(/ogsberg. +Kristian Høgsberg. .SH "SEE ALSO" -__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__). +__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__), +README.mouse. diff --git a/src/.gitignore b/src/.cvsignore index 9730646..9730646 100644 --- a/src/.gitignore +++ b/src/.cvsignore diff --git a/src/Makefile.am b/src/Makefile.am index 0fb7ffd..2221bbc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,6 @@ # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la @DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version -@DRIVER_NAME@_drv_la_CFLAGS = -Wall @DRIVER_NAME@_drv_ladir = @inputdir@ -@DRIVER_NAME@_drv_la_SOURCES = evdev.c evdev.h evdev_axes.c evdev_btn.c evdev_key.c +@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c diff --git a/src/evdev.c b/src/evdev.c index 38f80ef..61c6dca 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1,35 +1,28 @@ /* - * Copyright © 2006-2007 Zephaniah E. Hull - * Copyright © 2004 Red Hat, Inc. + * Copyright © 2004-2008 Red Hat, Inc. * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Soft- - * ware"), to deal in the Software without restriction, including without - * limitation the rights to use, copy, modify, merge, publish, distribute, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, provided that the above copyright - * notice(s) and this permission notice appear in all copies of the Soft- - * ware and that both the above copyright notice(s) and this permission - * notice appear in supporting documentation. + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Red Hat + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. Red + * Hat makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- - * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY - * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN - * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- - * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- - * MANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder shall - * not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization of - * the copyright holder. + * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: - * Zephaniah E. Hull (warp@aehallh.com), - * Kristian Høgsberg (krh@redhat.com) + * Kristian Høgsberg (krh@redhat.com) + * Adam Jackson (ajax@redhat.com) */ #ifdef HAVE_CONFIG_H @@ -40,506 +33,1045 @@ #include <X11/XF86keysym.h> #include <X11/extensions/XIproto.h> -#include "evdev.h" +#include <linux/input.h> +#include <misc.h> #include <xf86.h> - -#include <xf86Module.h> -#include <mipointer.h> -#include <xf86_OSlib.h> - - +#include <xf86str.h> #include <xf86_OSproc.h> +#include <xf86Xinput.h> +#include <exevents.h> +#include <mipointer.h> -static int EvdevProc(DeviceIntPtr device, int what); +#if defined(XKB) +/* XXX VERY WRONG. this is a client side header. */ +#include <X11/extensions/XKBstr.h> +#endif -/** - * Obtain various information using ioctls on the given socket. This - * information is used to determine if a device has axis, buttons or keys. - * - * @return TRUE on success or FALSE on error. - */ -static Bool -evdevGetBits (int fd, evdevBitsPtr bits) -{ -#define get_bitmask(fd, which, where) \ - if (ioctl(fd, EVIOCGBIT(which, sizeof (where)), where) < 0) { \ - xf86Msg(X_ERROR, "ioctl EVIOCGBIT %s failed: %s\n", #which, strerror(errno)); \ - return FALSE; \ - } +#include <xf86Module.h> - get_bitmask (fd, 0, bits->ev); - get_bitmask (fd, EV_KEY, bits->key); - get_bitmask (fd, EV_REL, bits->rel); - get_bitmask (fd, EV_ABS, bits->abs); - get_bitmask (fd, EV_MSC, bits->msc); - get_bitmask (fd, EV_LED, bits->led); - get_bitmask (fd, EV_SND, bits->snd); - get_bitmask (fd, EV_FF, bits->ff); +#include <errno.h> +#include <fcntl.h> -#undef get_bitmask +/* 2.4 compatibility */ +#ifndef EVIOCGRAB +#define EVIOCGRAB _IOW('E', 0x90, int) +#endif - return TRUE; -} +#ifndef BTN_TASK +#define BTN_TASK 0x117 +#endif -/* - * Evdev option handling stuff. - * - * We should probably move this all off to it's own file, but for now it lives - * hereish. - */ +#ifndef EV_SYN +#define EV_SYN EV_RST +#endif +/* end compat */ + +#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0]))) + +/* evdev flags */ +#define EVDEV_KEYBOARD_EVENTS (1 << 0) +#define EVDEV_BUTTON_EVENTS (1 << 1) +#define EVDEV_RELATIVE_EVENTS (1 << 2) +#define EVDEV_ABSOLUTE_EVENTS (1 << 3) +#define EVDEV_TOUCHPAD (1 << 4) + +#define MIN_KEYCODE 8 +#define GLYPHS_PER_KEY 2 +#define AltMask Mod1Mask +#define NumLockMask Mod2Mask +#define AltLangMask Mod3Mask +#define KanaMask Mod4Mask +#define ScrollLockMask Mod5Mask + +#define CAPSFLAG 1 +#define NUMFLAG 2 +#define SCROLLFLAG 4 +#define MODEFLAG 8 +#define COMPOSEFLAG 16 + +typedef struct { + int kernel24; + int screen; + int min_x, min_y, max_x, max_y; + int abs_x, abs_y, old_x, old_y; + int flags; + int tool; + + /* XKB stuff has to be per-device rather than per-driver */ + int noXkb; +#ifdef XKB + char *xkb_rules; + char *xkb_model; + char *xkb_layout; + char *xkb_variant; + char *xkb_options; + XkbComponentNamesRec xkbnames; +#endif +} EvdevRec, *EvdevPtr; + +typedef enum { + OPTION_XKB_DISABLE, + OPTION_XKB_RULES, + OPTION_XKB_MODEL, + OPTION_XKB_LAYOUT, + OPTION_XKB_VARIANT, + OPTION_XKB_OPTIONS +} EvdevOpts; + +static const OptionInfoRec EvdevOptions[] = { + { OPTION_XKB_DISABLE, "XkbDisable", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_XKB_RULES, "XkbRules", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_MODEL, "XkbModel", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_LAYOUT, "XkbLayout", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_VARIANT, "XkbVariant", OPTV_STRING, {0}, FALSE }, + { OPTION_XKB_OPTIONS, "XkbOptions", OPTV_STRING, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; -evdev_map_parsers_t evdev_map_parsers[] = { - { - .name = "RelAxis", - .func = EvdevParseMapToRelAxis, - }, - { - .name = "AbsAxis", - .func = EvdevParseMapToAbsAxis, - }, - { - .name = "Button", - .func = EvdevParseMapToButton, - }, - { - .name = "Buttons", - .func = EvdevParseMapToButtons, - }, - { - .name = NULL, - .func = NULL, - } +static const char *evdevDefaults[] = { + "XkbRules", "xfree86", + "XkbModel", "evdev", + "XkbLayout", "us", + NULL }; -Bool -EvdevParseMapOption (InputInfoRec *pInfo, char *option, char *def, void **map_data, evdev_map_func_f *map_func) +static void +SetXkbOption(InputInfoPtr pInfo, char *name, char **option) { - evdev_option_token_t *tokens; - const char *s; - int i; - - s = xf86SetStrOption(pInfo->options, option, def); - tokens = EvdevTokenize (s, " ="); - if (tokens->next) { - for (i = 0; evdev_map_parsers[i].name; i++) { - if (!strcasecmp (tokens->str, evdev_map_parsers[i].name)) { - if (!evdev_map_parsers[i].func (pInfo, option, tokens->next, map_data, map_func)) { - xf86Msg (X_ERROR, "%s: Unable to parse '%s' as a map specifier.\n", pInfo->name, s); - EvdevFreeTokens (tokens); - return 0; - } - return 1; - } - } - - if (!evdev_map_parsers[i].name) - xf86Msg (X_ERROR, "%s: Unable to find parser for '%s' as a map specifier.\n", pInfo->name, s); - } else { - xf86Msg (X_ERROR, "%s: Unable to parse '%s' as a map specifier string.\n", pInfo->name, s); + char *s; + + if ((s = xf86SetStrOption(pInfo->options, name, NULL))) { + if (!s[0]) { + xfree(s); + *option = NULL; + } else { + *option = s; + xf86Msg(X_CONFIG, "%s: %s: \"%s\"\n", pInfo->name, name, s); + } } - EvdevFreeTokens (tokens); - return 0; } -evdev_option_token_t * -EvdevTokenize (const char *option, const char *tokens) -{ - evdev_option_token_t *head = NULL, *token = NULL, *prev = NULL; - const char *ctmp; - const char *first; - char *tmp = NULL; - int len; - - first = strchr (option, tokens[0]); - - while (1) { - if (first) - len = first - option; - else { - len = strlen(option); - if (!len) - break; - } - - if (!len) { - option++; - first = strchr (option, tokens[0]); - continue; - } - - token = calloc (1, sizeof(evdev_option_token_t)); - if (!head) - head = token; - if (prev) - prev->next = token; - - prev = token; - - tmp = calloc(1, len + 1); - strncpy (tmp, option, len); +static int wheel_up_button = 4; +static int wheel_down_button = 5; +static int wheel_left_button = 6; +static int wheel_right_button = 7; - if (tokens[1]) { - ctmp = strchr (tmp, tokens[1]); - if (ctmp) { - token->chain = EvdevTokenize (ctmp+1, tokens + 1); - } else - token->str = tmp; - } else - token->str = tmp; - - if (!first) - break; +static void +PostButtonClicks(InputInfoPtr pInfo, int button, int count) +{ + int i; - option = first + 1; - first = strchr (option, tokens[0]); + for (i = 0; i < count; i++) { + xf86PostButtonEvent(pInfo->dev, 0, button, 1, 0, 0); + xf86PostButtonEvent(pInfo->dev, 0, button, 0, 0, 0); } - - return head; } -void -EvdevFreeTokens (evdev_option_token_t *token) +static void +PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) { - evdev_option_token_t *next; - - while (token) { - if (token->chain) - EvdevFreeTokens (token->chain); - free (token->str); - next = token->next; - free (token); - token = next; - } + /* filter repeat events for chording keys */ + if (value == 2 && + (ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL || + ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT || + ev->code == KEY_LEFTALT || ev->code == KEY_RIGHTALT || + ev->code == KEY_LEFTMETA || ev->code == KEY_RIGHTMETA || + ev->code == KEY_CAPSLOCK || ev->code == KEY_NUMLOCK || + ev->code == KEY_SCROLLLOCK)) /* XXX windows keys? */ + return; + + xf86PostKeyboardEvent(pInfo->dev, ev->code + MIN_KEYCODE, value); } - - static void EvdevReadInput(InputInfoPtr pInfo) { struct input_event ev; - int len; + int len, value; + int dx, dy; + unsigned int abs; + Bool do_touchpad_motion = FALSE; + EvdevPtr pEvdev = pInfo->private; + + dx = 0; + dy = 0; + abs = 0; while (xf86WaitForInput (pInfo->fd, 0) > 0) { - len = read(pInfo->fd, &ev, sizeof(ev)); - if (len != sizeof(ev)) { + len = read(pInfo->fd, &ev, sizeof ev); + if (len != sizeof ev) { /* The kernel promises that we always only read a complete * event, so len != sizeof ev is an error. */ - xf86Msg(X_ERROR, "Read error: %s (%d, %d != %zd)\n", - strerror(errno), errno, len, sizeof (ev)); - if (len < 0) - { - xf86DisableDevice(pInfo->dev, TRUE); - return; - } + xf86Msg(X_ERROR, "Read error: %s\n", strerror(errno)); break; } - switch (ev.type) { - case EV_REL: - EvdevAxesRelProcess (pInfo, &ev); - break; + /* Get the signed value, earlier kernels had this as unsigned */ + value = ev.value; - case EV_ABS: - EvdevAxesAbsProcess (pInfo, &ev); + switch (ev.type) { + case EV_REL: + switch (ev.code) { + case REL_X: + dx += value; + break; + + case REL_Y: + dy += value; + break; + + case REL_WHEEL: + if (value > 0) + PostButtonClicks(pInfo, wheel_up_button, value); + if (value < 0) + PostButtonClicks(pInfo, wheel_down_button, -value); + break; + + case REL_HWHEEL: + if (value > 0) + PostButtonClicks(pInfo, wheel_right_button, value); + if (value < 0) + PostButtonClicks(pInfo, wheel_left_button, -value); + break; + } break; - case EV_KEY: - if ((ev.code >= BTN_MISC) && (ev.code < KEY_OK)) - EvdevBtnProcess (pInfo, &ev); - else - EvdevKeyProcess (pInfo, &ev); + case EV_ABS: + switch (ev.code) { + case ABS_X: + pEvdev->abs_x = value; + abs = 1; + break; + case ABS_Y: + pEvdev->abs_y = value; + abs = 1; + break; + } break; + case EV_KEY: + switch (ev.code) { + case BTN_LEFT: + case BTN_RIGHT: + case BTN_MIDDLE: + xf86PostButtonEvent(pInfo->dev, 0, ev.code - BTN_LEFT + 1, + value, 0, 0); + break; + + case BTN_SIDE: + case BTN_EXTRA: + case BTN_FORWARD: + case BTN_BACK: + case BTN_TASK: + xf86PostButtonEvent(pInfo->dev, 0, ev.code - BTN_LEFT + 5, + value, 0, 0); + break; + + case BTN_TOUCH: + case BTN_TOOL_PEN: + case BTN_TOOL_RUBBER: + case BTN_TOOL_BRUSH: + case BTN_TOOL_PENCIL: + case BTN_TOOL_AIRBRUSH: + case BTN_TOOL_FINGER: + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + pEvdev->tool = value ? ev.code : 0; + break; + + default: + if (ev.code > BTN_TASK && ev.code < KEY_OK) + break; + + PostKbdEvent(pInfo, &ev, value); + break; + } + break; + case EV_SYN: - if (ev.code == SYN_REPORT) { - EvdevAxesSynRep (pInfo); - /* EvdevBtnSynRep (pInfo); */ - /* EvdevKeySynRep (pInfo); */ - } else if (ev.code == SYN_CONFIG) { - EvdevAxesSynCfg (pInfo); - /* EvdevBtnSynCfg (pInfo); */ - /* EvdevKeySynCfg (pInfo); */ - } break; } } + + /* convert to relative motion for touchpads */ + if (pEvdev->flags & EVDEV_TOUCHPAD) { + abs = 0; + if (pEvdev->tool) { /* meaning, touch is active */ + if (pEvdev->old_x != -1) + dx = pEvdev->abs_x - pEvdev->old_x; + if (pEvdev->old_x != -1) + dy = pEvdev->abs_y - pEvdev->old_y; + pEvdev->old_x = pEvdev->abs_x; + pEvdev->old_y = pEvdev->abs_y; + } else { + pEvdev->old_x = pEvdev->old_y = -1; + } + } + + if (dx != 0 || dy != 0) + xf86PostMotionEvent(pInfo->dev, FALSE, 0, 2, dx, dy); + + /* + * Some devices only generate valid abs coords when BTN_DIGI is + * pressed. On wacom tablets, this means that the pen is in + * proximity of the tablet. After the pen is removed, BTN_DIGI is + * released, and a (0, 0) absolute event is generated. Checking + * pEvdev->digi here, lets us ignore that event. pEvdev is + * initialized to 1 so devices that doesn't use this scheme still + * just works. + */ + if (abs && pEvdev->tool) { + xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, + pEvdev->abs_x, pEvdev->abs_y); + } +} + +#define TestBit(bit, array) (array[(bit) / 8] & (1 << ((bit) % 8))) + +static void +EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl) +{ + /* Nothing to do, dix handles all settings */ +} + +/* FIXME: this map works with evdev keyboards, but all the xkb maps + * probably don't. The easiest is to remap the event keycodes. */ + +static KeySym map[] = { + /* 0x00 */ NoSymbol, NoSymbol, + /* 0x01 */ XK_Escape, NoSymbol, + /* 0x02 */ XK_1, XK_exclam, + /* 0x03 */ XK_2, XK_at, + /* 0x04 */ XK_3, XK_numbersign, + /* 0x05 */ XK_4, XK_dollar, + /* 0x06 */ XK_5, XK_percent, + /* 0x07 */ XK_6, XK_asciicircum, + /* 0x08 */ XK_7, XK_ampersand, + /* 0x09 */ XK_8, XK_asterisk, + /* 0x0a */ XK_9, XK_parenleft, + /* 0x0b */ XK_0, XK_parenright, + /* 0x0c */ XK_minus, XK_underscore, + /* 0x0d */ XK_equal, XK_plus, + /* 0x0e */ XK_BackSpace, NoSymbol, + /* 0x0f */ XK_Tab, XK_ISO_Left_Tab, + /* 0x10 */ XK_Q, NoSymbol, + /* 0x11 */ XK_W, NoSymbol, + /* 0x12 */ XK_E, NoSymbol, + /* 0x13 */ XK_R, NoSymbol, + /* 0x14 */ XK_T, NoSymbol, + /* 0x15 */ XK_Y, NoSymbol, + /* 0x16 */ XK_U, NoSymbol, + /* 0x17 */ XK_I, NoSymbol, + /* 0x18 */ XK_O, NoSymbol, + /* 0x19 */ XK_P, NoSymbol, + /* 0x1a */ XK_bracketleft, XK_braceleft, + /* 0x1b */ XK_bracketright,XK_braceright, + /* 0x1c */ XK_Return, NoSymbol, + /* 0x1d */ XK_Control_L, NoSymbol, + /* 0x1e */ XK_A, NoSymbol, + /* 0x1f */ XK_S, NoSymbol, + /* 0x20 */ XK_D, NoSymbol, + /* 0x21 */ XK_F, NoSymbol, + /* 0x22 */ XK_G, NoSymbol, + /* 0x23 */ XK_H, NoSymbol, + /* 0x24 */ XK_J, NoSymbol, + /* 0x25 */ XK_K, NoSymbol, + /* 0x26 */ XK_L, NoSymbol, + /* 0x27 */ XK_semicolon, XK_colon, + /* 0x28 */ XK_quoteright, XK_quotedbl, + /* 0x29 */ XK_quoteleft, XK_asciitilde, + /* 0x2a */ XK_Shift_L, NoSymbol, + /* 0x2b */ XK_backslash, XK_bar, + /* 0x2c */ XK_Z, NoSymbol, + /* 0x2d */ XK_X, NoSymbol, + /* 0x2e */ XK_C, NoSymbol, + /* 0x2f */ XK_V, NoSymbol, + /* 0x30 */ XK_B, NoSymbol, + /* 0x31 */ XK_N, NoSymbol, + /* 0x32 */ XK_M, NoSymbol, + /* 0x33 */ XK_comma, XK_less, + /* 0x34 */ XK_period, XK_greater, + /* 0x35 */ XK_slash, XK_question, + /* 0x36 */ XK_Shift_R, NoSymbol, + /* 0x37 */ XK_KP_Multiply, NoSymbol, + /* 0x38 */ XK_Alt_L, XK_Meta_L, + /* 0x39 */ XK_space, NoSymbol, + /* 0x3a */ XK_Caps_Lock, NoSymbol, + /* 0x3b */ XK_F1, NoSymbol, + /* 0x3c */ XK_F2, NoSymbol, + /* 0x3d */ XK_F3, NoSymbol, + /* 0x3e */ XK_F4, NoSymbol, + /* 0x3f */ XK_F5, NoSymbol, + /* 0x40 */ XK_F6, NoSymbol, + /* 0x41 */ XK_F7, NoSymbol, + /* 0x42 */ XK_F8, NoSymbol, + /* 0x43 */ XK_F9, NoSymbol, + /* 0x44 */ XK_F10, NoSymbol, + /* 0x45 */ XK_Num_Lock, NoSymbol, + /* 0x46 */ XK_Scroll_Lock, NoSymbol, + /* These KP keys should have the KP_7 keysyms in the numlock + * modifer... ? */ + /* 0x47 */ XK_KP_Home, XK_KP_7, + /* 0x48 */ XK_KP_Up, XK_KP_8, + /* 0x49 */ XK_KP_Prior, XK_KP_9, + /* 0x4a */ XK_KP_Subtract, NoSymbol, + /* 0x4b */ XK_KP_Left, XK_KP_4, + /* 0x4c */ XK_KP_Begin, XK_KP_5, + /* 0x4d */ XK_KP_Right, XK_KP_6, + /* 0x4e */ XK_KP_Add, NoSymbol, + /* 0x4f */ XK_KP_End, XK_KP_1, + /* 0x50 */ XK_KP_Down, XK_KP_2, + /* 0x51 */ XK_KP_Next, XK_KP_3, + /* 0x52 */ XK_KP_Insert, XK_KP_0, + /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, + /* 0x54 */ NoSymbol, NoSymbol, + /* 0x55 */ XK_F13, NoSymbol, + /* 0x56 */ XK_less, XK_greater, + /* 0x57 */ XK_F11, NoSymbol, + /* 0x58 */ XK_F12, NoSymbol, + /* 0x59 */ XK_F14, NoSymbol, + /* 0x5a */ XK_F15, NoSymbol, + /* 0x5b */ XK_F16, NoSymbol, + /* 0x5c */ XK_F17, NoSymbol, + /* 0x5d */ XK_F18, NoSymbol, + /* 0x5e */ XK_F19, NoSymbol, + /* 0x5f */ XK_F20, NoSymbol, + /* 0x60 */ XK_KP_Enter, NoSymbol, + /* 0x61 */ XK_Control_R, NoSymbol, + /* 0x62 */ XK_KP_Divide, NoSymbol, + /* 0x63 */ XK_Print, XK_Sys_Req, + /* 0x64 */ XK_Alt_R, XK_Meta_R, + /* 0x65 */ NoSymbol, NoSymbol, /* KEY_LINEFEED */ + /* 0x66 */ XK_Home, NoSymbol, + /* 0x67 */ XK_Up, NoSymbol, + /* 0x68 */ XK_Prior, NoSymbol, + /* 0x69 */ XK_Left, NoSymbol, + /* 0x6a */ XK_Right, NoSymbol, + /* 0x6b */ XK_End, NoSymbol, + /* 0x6c */ XK_Down, NoSymbol, + /* 0x6d */ XK_Next, NoSymbol, + /* 0x6e */ XK_Insert, NoSymbol, + /* 0x6f */ XK_Delete, NoSymbol, + /* 0x70 */ NoSymbol, NoSymbol, /* KEY_MACRO */ + /* 0x71 */ NoSymbol, NoSymbol, + /* 0x72 */ NoSymbol, NoSymbol, + /* 0x73 */ NoSymbol, NoSymbol, + /* 0x74 */ NoSymbol, NoSymbol, + /* 0x75 */ XK_KP_Equal, NoSymbol, + /* 0x76 */ NoSymbol, NoSymbol, + /* 0x77 */ NoSymbol, NoSymbol, + /* 0x78 */ XK_F21, NoSymbol, + /* 0x79 */ XK_F22, NoSymbol, + /* 0x7a */ XK_F23, NoSymbol, + /* 0x7b */ XK_F24, NoSymbol, + /* 0x7c */ XK_KP_Separator, NoSymbol, + /* 0x7d */ XK_Meta_L, NoSymbol, + /* 0x7e */ XK_Meta_R, NoSymbol, + /* 0x7f */ XK_Multi_key, NoSymbol, + /* 0x80 */ NoSymbol, NoSymbol, + /* 0x81 */ NoSymbol, NoSymbol, + /* 0x82 */ NoSymbol, NoSymbol, + /* 0x83 */ NoSymbol, NoSymbol, + /* 0x84 */ NoSymbol, NoSymbol, + /* 0x85 */ NoSymbol, NoSymbol, + /* 0x86 */ NoSymbol, NoSymbol, + /* 0x87 */ NoSymbol, NoSymbol, + /* 0x88 */ NoSymbol, NoSymbol, + /* 0x89 */ NoSymbol, NoSymbol, + /* 0x8a */ NoSymbol, NoSymbol, + /* 0x8b */ NoSymbol, NoSymbol, + /* 0x8c */ NoSymbol, NoSymbol, + /* 0x8d */ NoSymbol, NoSymbol, + /* 0x8e */ NoSymbol, NoSymbol, + /* 0x8f */ NoSymbol, NoSymbol, + /* 0x90 */ NoSymbol, NoSymbol, + /* 0x91 */ NoSymbol, NoSymbol, + /* 0x92 */ NoSymbol, NoSymbol, + /* 0x93 */ NoSymbol, NoSymbol, + /* 0x94 */ NoSymbol, NoSymbol, + /* 0x95 */ NoSymbol, NoSymbol, + /* 0x96 */ NoSymbol, NoSymbol, + /* 0x97 */ NoSymbol, NoSymbol, + /* 0x98 */ NoSymbol, NoSymbol, + /* 0x99 */ NoSymbol, NoSymbol, + /* 0x9a */ NoSymbol, NoSymbol, + /* 0x9b */ NoSymbol, NoSymbol, + /* 0x9c */ NoSymbol, NoSymbol, + /* 0x9d */ NoSymbol, NoSymbol, + /* 0x9e */ NoSymbol, NoSymbol, + /* 0x9f */ NoSymbol, NoSymbol, + /* 0xa0 */ NoSymbol, NoSymbol, + /* 0xa1 */ NoSymbol, NoSymbol, + /* 0xa2 */ NoSymbol, NoSymbol, + /* 0xa3 */ NoSymbol, NoSymbol, + /* 0xa4 */ NoSymbol, NoSymbol, + /* 0xa5 */ NoSymbol, NoSymbol, + /* 0xa6 */ NoSymbol, NoSymbol, + /* 0xa7 */ NoSymbol, NoSymbol, + /* 0xa8 */ NoSymbol, NoSymbol, + /* 0xa9 */ NoSymbol, NoSymbol, + /* 0xaa */ NoSymbol, NoSymbol, + /* 0xab */ NoSymbol, NoSymbol, + /* 0xac */ NoSymbol, NoSymbol, + /* 0xad */ NoSymbol, NoSymbol, + /* 0xae */ NoSymbol, NoSymbol, + /* 0xaf */ NoSymbol, NoSymbol, + /* 0xb0 */ NoSymbol, NoSymbol, + /* 0xb1 */ NoSymbol, NoSymbol, + /* 0xb2 */ NoSymbol, NoSymbol, + /* 0xb3 */ NoSymbol, NoSymbol, + /* 0xb4 */ NoSymbol, NoSymbol, + /* 0xb5 */ NoSymbol, NoSymbol, + /* 0xb6 */ NoSymbol, NoSymbol, + /* 0xb7 */ NoSymbol, NoSymbol, + /* 0xb8 */ NoSymbol, NoSymbol, + /* 0xb9 */ NoSymbol, NoSymbol, + /* 0xba */ NoSymbol, NoSymbol, + /* 0xbb */ NoSymbol, NoSymbol, + /* 0xbc */ NoSymbol, NoSymbol, + /* 0xbd */ NoSymbol, NoSymbol, + /* 0xbe */ NoSymbol, NoSymbol, + /* 0xbf */ NoSymbol, NoSymbol, + /* 0xc0 */ NoSymbol, NoSymbol, + /* 0xc1 */ NoSymbol, NoSymbol, + /* 0xc2 */ NoSymbol, NoSymbol, + /* 0xc3 */ NoSymbol, NoSymbol, + /* 0xc4 */ NoSymbol, NoSymbol, + /* 0xc5 */ NoSymbol, NoSymbol, + /* 0xc6 */ NoSymbol, NoSymbol, + /* 0xc7 */ NoSymbol, NoSymbol, + /* 0xc8 */ NoSymbol, NoSymbol, + /* 0xc9 */ NoSymbol, NoSymbol, + /* 0xca */ NoSymbol, NoSymbol, + /* 0xcb */ NoSymbol, NoSymbol, + /* 0xcc */ NoSymbol, NoSymbol, + /* 0xcd */ NoSymbol, NoSymbol, + /* 0xce */ NoSymbol, NoSymbol, + /* 0xcf */ NoSymbol, NoSymbol, + /* 0xd0 */ NoSymbol, NoSymbol, + /* 0xd1 */ NoSymbol, NoSymbol, + /* 0xd2 */ NoSymbol, NoSymbol, + /* 0xd3 */ NoSymbol, NoSymbol, + /* 0xd4 */ NoSymbol, NoSymbol, + /* 0xd5 */ NoSymbol, NoSymbol, + /* 0xd6 */ NoSymbol, NoSymbol, + /* 0xd7 */ NoSymbol, NoSymbol, + /* 0xd8 */ NoSymbol, NoSymbol, + /* 0xd9 */ NoSymbol, NoSymbol, + /* 0xda */ NoSymbol, NoSymbol, + /* 0xdb */ NoSymbol, NoSymbol, + /* 0xdc */ NoSymbol, NoSymbol, + /* 0xdd */ NoSymbol, NoSymbol, + /* 0xde */ NoSymbol, NoSymbol, + /* 0xdf */ NoSymbol, NoSymbol, + /* 0xe0 */ NoSymbol, NoSymbol, + /* 0xe1 */ NoSymbol, NoSymbol, + /* 0xe2 */ NoSymbol, NoSymbol, + /* 0xe3 */ NoSymbol, NoSymbol, + /* 0xe4 */ NoSymbol, NoSymbol, + /* 0xe5 */ NoSymbol, NoSymbol, + /* 0xe6 */ NoSymbol, NoSymbol, + /* 0xe7 */ NoSymbol, NoSymbol, + /* 0xe8 */ NoSymbol, NoSymbol, + /* 0xe9 */ NoSymbol, NoSymbol, + /* 0xea */ NoSymbol, NoSymbol, + /* 0xeb */ NoSymbol, NoSymbol, + /* 0xec */ NoSymbol, NoSymbol, + /* 0xed */ NoSymbol, NoSymbol, + /* 0xee */ NoSymbol, NoSymbol, + /* 0xef */ NoSymbol, NoSymbol, + /* 0xf0 */ NoSymbol, NoSymbol, + /* 0xf1 */ NoSymbol, NoSymbol, + /* 0xf2 */ NoSymbol, NoSymbol, + /* 0xf3 */ NoSymbol, NoSymbol, + /* 0xf4 */ NoSymbol, NoSymbol, + /* 0xf5 */ NoSymbol, NoSymbol, + /* 0xf6 */ NoSymbol, NoSymbol, + /* 0xf7 */ NoSymbol, NoSymbol, +}; + +static void +EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl) +{ + static struct { int xbit, code; } bits[] = { + { CAPSFLAG, LED_CAPSL }, + { NUMFLAG, LED_NUML }, + { SCROLLFLAG, LED_SCROLLL }, + { MODEFLAG, LED_KANA }, + { COMPOSEFLAG, LED_COMPOSE } + }; + + InputInfoPtr pInfo; + struct input_event ev[ArrayLength(bits)]; + int i; + + pInfo = device->public.devicePrivate; + for (i = 0; i < ArrayLength(bits); i++) { + ev[i].type = EV_LED; + ev[i].code = bits[i].code; + ev[i].value = (ctrl->leds & bits[i].xbit) > 0; + } + + write(pInfo->fd, ev, sizeof ev); } static int -EvdevProc(DeviceIntPtr device, int what) +EvdevAddKeyClass(DeviceIntPtr device) { - InputInfoPtr pInfo = device->public.devicePrivate; - evdevDevicePtr pEvdev = pInfo->private; + InputInfoPtr pInfo; + KeySymsRec keySyms; + CARD8 modMap[MAP_LENGTH]; + KeySym sym; + int i, j; + EvdevPtr pEvdev; + + static struct { KeySym keysym; CARD8 mask; } modifiers[] = { + { XK_Shift_L, ShiftMask }, + { XK_Shift_R, ShiftMask }, + { XK_Control_L, ControlMask }, + { XK_Control_R, ControlMask }, + { XK_Caps_Lock, LockMask }, + { XK_Alt_L, AltMask }, + { XK_Alt_R, AltMask }, + { XK_Num_Lock, NumLockMask }, + { XK_Scroll_Lock, ScrollLockMask }, + { XK_Mode_switch, AltLangMask } + }; + + /* TODO: + * Ctrl-Alt-Backspace and other Ctrl-Alt-stuff should work + * Get keyboard repeat under control (right now caps lock repeats!) + */ + + pInfo = device->public.devicePrivate; + pEvdev = pInfo->private; + + /* Compute the modifier map */ + memset(modMap, 0, sizeof modMap); + + for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) { + sym = map[i * GLYPHS_PER_KEY]; + for (j = 0; j < ArrayLength(modifiers); j++) { + if (modifiers[j].keysym == sym) + modMap[i + MIN_KEYCODE] = modifiers[j].mask; + } + } - if (!pEvdev->device) - return BadRequest; + keySyms.map = map; + keySyms.mapWidth = GLYPHS_PER_KEY; + keySyms.minKeyCode = MIN_KEYCODE; + keySyms.maxKeyCode = MIN_KEYCODE + ArrayLength(map) / GLYPHS_PER_KEY - 1; - switch (what) +#ifdef XKB + if (pEvdev->noXkb) +#endif { - case DEVICE_INIT: - if (pEvdev->state.axes) - EvdevAxesInit (device); - if (pEvdev->state.btn) - EvdevBtnInit (device); - if (pEvdev->state.key) - EvdevKeyInit (device); - xf86Msg(X_INFO, "%s: Init\n", pInfo->name); - break; + xf86Msg(X_CONFIG, "XKB: disabled\n"); + if (!InitKeyboardDeviceStruct((DevicePtr)device, &keySyms, modMap, + NULL, EvdevKbdCtrl)) + return !Success; + } +#ifdef XKB + else + { + SetXkbOption(pInfo, "XkbRules", &pEvdev->xkb_rules); + SetXkbOption(pInfo, "XkbModel", &pEvdev->xkb_model); + SetXkbOption(pInfo, "XkbLayout", &pEvdev->xkb_layout); + SetXkbOption(pInfo, "XkbVariant", &pEvdev->xkb_variant); + SetXkbOption(pInfo, "XkbOptions", &pEvdev->xkb_options); + + if (pEvdev->xkbnames.keymap) + pEvdev->xkb_rules = NULL; + + XkbSetRulesDflts(pEvdev->xkb_rules, pEvdev->xkb_model, + pEvdev->xkb_layout, pEvdev->xkb_variant, + pEvdev->xkb_options); + if (!XkbInitKeyboardDeviceStruct(device, &pEvdev->xkbnames, + &keySyms, modMap, NULL, + EvdevKbdCtrl)) + return !Success; + } +#endif - case DEVICE_ON: - xf86Msg(X_INFO, "%s: On\n", pInfo->name); - if (device->public.on) - break; + pInfo->flags |= XI86_KEYBOARD_CAPABLE; - SYSCALL(pInfo->fd = open (pEvdev->device, O_RDWR | O_NONBLOCK)); - if (pInfo->fd == -1) { - xf86Msg(X_ERROR, "%s: cannot open input device.\n", pInfo->name); + return Success; +} - if (pEvdev->device) - xfree(pEvdev->device); - pEvdev->device = NULL; +static int +EvdevAddAbsClass(DeviceIntPtr device) +{ + InputInfoPtr pInfo; + EvdevPtr pEvdev; + struct input_absinfo absinfo_x, absinfo_y; - return BadRequest; - } + pInfo = device->public.devicePrivate; + pEvdev = pInfo->private; - if (pEvdev->state.can_grab) - if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) - xf86Msg(X_ERROR, "%s: Unable to grab device (%s).\n", pInfo->name, strerror(errno)); + if (ioctl(pInfo->fd, + EVIOCGABS(ABS_X), &absinfo_x) < 0) { + xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno)); + return !Success; + } - xf86FlushInput (pInfo->fd); + if (ioctl(pInfo->fd, + EVIOCGABS(ABS_Y), &absinfo_y) < 0) { + xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno)); + return !Success; + } - xf86AddEnabledDevice(pInfo); + pEvdev->min_x = absinfo_x.minimum; + pEvdev->max_x = absinfo_x.maximum; + pEvdev->min_y = absinfo_y.minimum; + pEvdev->max_y = absinfo_y.maximum; - device->public.on = TRUE; + if (!InitValuatorClassDeviceStruct(device, 2, GetMotionHistory, + GetMotionHistorySize(), Absolute)) + return !Success; - if (pEvdev->state.axes) - EvdevAxesOn (device); - if (pEvdev->state.btn) - EvdevBtnOn (device); - if (pEvdev->state.key) - EvdevKeyOn (device); - break; + /* X valuator */ + xf86InitValuatorAxisStruct(device, 0, pEvdev->min_x, pEvdev->max_x, + 10000, 0, 10000); + xf86InitValuatorDefaults(device, 0); - case DEVICE_CLOSE: - case DEVICE_OFF: - xf86Msg(X_INFO, "%s: Off\n", pInfo->name); - if (pInfo->fd != -1) { - if (pEvdev->state.can_grab) - ioctl(pInfo->fd, EVIOCGRAB, (void *)0); - - RemoveEnabledDevice (pInfo->fd); - xf86RemoveSIGIOHandler (pInfo->fd); - close (pInfo->fd); - pInfo->fd = -1; - - if (pEvdev->state.axes) - EvdevAxesOff (device); - if (pEvdev->state.btn) - EvdevBtnOff (device); - if (pEvdev->state.key) - EvdevKeyOff (device); - } + /* Y valuator */ + xf86InitValuatorAxisStruct(device, 1, pEvdev->min_y, pEvdev->max_y, + 10000, 0, 10000); + xf86InitValuatorDefaults(device, 1); + xf86MotionHistoryAllocate(pInfo); - device->public.on = FALSE; - break; - } + if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) + return !Success; + + pInfo->flags |= XI86_POINTER_CAPABLE; return Success; } static int -EvdevSwitchMode (ClientPtr client, DeviceIntPtr device, int mode) +EvdevAddRelClass(DeviceIntPtr device) { - InputInfoPtr pInfo = device->public.devicePrivate; - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; + InputInfoPtr pInfo; - switch (mode) - { - case Absolute: - case Relative: - xf86Msg(X_INFO, "%s: Switching mode to %d.\n", pInfo->name, mode); - if (!state->abs) - return !Success; - break; - default: - return !Success; - } + pInfo = device->public.devicePrivate; + + if (!InitValuatorClassDeviceStruct(device, 2, GetMotionHistory, + GetMotionHistorySize(), Relative)) + return !Success; + + /* X valuator */ + xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1); + xf86InitValuatorDefaults(device, 0); + + /* Y valuator */ + xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1); + xf86InitValuatorDefaults(device, 1); + xf86MotionHistoryAllocate(pInfo); + + if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) + return !Success; + + pInfo->flags |= XI86_POINTER_CAPABLE; + + xf86MotionHistoryAllocate(pInfo); return Success; } -InputInfoPtr -EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags) +static int +EvdevAddButtonClass(DeviceIntPtr device) { + CARD8 map[32]; InputInfoPtr pInfo; - evdevDevicePtr pEvdev; + int i; - if (!(pInfo = xf86AllocateInput(drv, 0))) - return NULL; + pInfo = device->public.devicePrivate; - pEvdev = Xcalloc (sizeof (evdevDeviceRec)); - if (!pEvdev) { - pInfo->private = NULL; - xf86DeleteInput (pInfo, 0); - return NULL; - } + /* FIXME: count number of actual buttons */ - /* Initialise the InputInfoRec. */ - pInfo->name = xstrdup(dev->identifier); - pInfo->flags = 0; - pInfo->type_name = "UNKNOWN"; - pInfo->device_control = EvdevProc; - pInfo->read_input = EvdevReadInput; - pInfo->switch_mode = EvdevSwitchMode; - pInfo->conf_idev = dev; + for (i = 0; i < ArrayLength(map); i++) + map[i] = i; - pInfo->private = pEvdev; + /* Linux reports BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, which should map + * to buttons 1, 2 and 3, so swap 2 and 3 in the map */ + map[2] = 3; + map[3] = 2; - pEvdev->device = xf86CheckStrOption(dev->commonOptions, "path", NULL); - if (!pEvdev->device) - pEvdev->device = xf86CheckStrOption(dev->commonOptions, "Device", NULL); - if (!pEvdev->device) { - xf86Msg(X_ERROR, "%s: No Device specified.\n", pInfo->name); - pInfo->private = NULL; - xfree(pEvdev); - xf86DeleteInput (pInfo, 0); - return NULL; - } + if (!InitButtonClassDeviceStruct(device, ArrayLength(map), map)) + return !Success; - xf86CollectInputOptions(pInfo, NULL, NULL); - xf86ProcessCommonOptions(pInfo, pInfo->options); + return Success; +} - SYSCALL(pInfo->fd = open (pEvdev->device, O_RDWR | O_NONBLOCK)); - if (pInfo->fd == -1) { - xf86Msg(X_ERROR, "%s: cannot open device '%s': %s\n", - pInfo->name, pEvdev->device, strerror(errno)); - pInfo->private = NULL; - xfree(pEvdev); - xf86DeleteInput (pInfo, 0); - return NULL; - } +static int +EvdevInit(DeviceIntPtr device) +{ + InputInfoPtr pInfo; + EvdevPtr pEvdev; - if (!evdevGetBits (pInfo->fd, &pEvdev->bits)) { - xf86Msg(X_ERROR, "%s: cannot load bits\n", pInfo->name); - pInfo->private = NULL; - close (pInfo->fd); - xfree(pEvdev); - xf86DeleteInput (pInfo, 0); - return NULL; - } + pInfo = device->public.devicePrivate; + pEvdev = pInfo->private; - if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) { - xf86Msg(X_INFO, "%s: Unable to grab pEvdev (%s). Cowardly refusing to check use as keyboard.\n", pInfo->name, strerror(errno)); - pEvdev->state.can_grab = 0; - } else { - pEvdev->state.can_grab = 1; - ioctl(pInfo->fd, EVIOCGRAB, (void *)0); - } + /* FIXME: This doesn't add buttons for keyboards with scrollwheels. */ + if (pEvdev->flags & EVDEV_KEYBOARD_EVENTS) + EvdevAddKeyClass(device); + if (pEvdev->flags & EVDEV_BUTTON_EVENTS) + EvdevAddButtonClass(device); + if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) + EvdevAddRelClass(device); + if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) + EvdevAddAbsClass(device); - /* XXX: Note, the order of these is (maybe) still important. */ - EvdevBtnNew0 (pInfo); - EvdevAxesNew0 (pInfo); + return Success; +} - EvdevAxesNew1 (pInfo); - EvdevBtnNew1 (pInfo); +static int +EvdevProc(DeviceIntPtr device, int what) +{ + InputInfoPtr pInfo; + EvdevPtr pEvdev; - if (pEvdev->state.can_grab) - EvdevKeyNew (pInfo); + pInfo = device->public.devicePrivate; + pEvdev = pInfo->private; - close (pInfo->fd); - pInfo->fd = -1; + switch (what) + { + case DEVICE_INIT: + return EvdevInit(device); - pInfo->flags |= XI86_OPEN_ON_INIT; - if (!(pInfo->flags & XI86_CONFIGURED)) { - xf86Msg(X_ERROR, "%s: Don't know how to use pEvdev.\n", pInfo->name); - pInfo->private = NULL; - close (pInfo->fd); - xfree(pEvdev); - xf86DeleteInput (pInfo, 0); - return NULL; + case DEVICE_ON: + if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) + xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name, + strerror(errno)); + xf86AddEnabledDevice(pInfo); + device->public.on = TRUE; + break; + + case DEVICE_OFF: + if (!pEvdev->kernel24 && ioctl(pInfo->fd, EVIOCGRAB, (void *)0)) + xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name, + strerror(errno)); + xf86RemoveEnabledDevice(pInfo); + device->public.on = FALSE; + break; + + case DEVICE_CLOSE: + xf86Msg(X_INFO, "%s: Close\n", pInfo->name); + break; } - return pInfo; + return Success; } -static void -EvdevUnInit (InputDriverRec *drv, InputInfoRec *pInfo, int flags) +static Bool +EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2, + int v3, int v4, int v5, int *x, int *y) { - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - - if (pEvdev->device) { - xfree (pEvdev->device); - pEvdev->device = NULL; + EvdevPtr pEvdev = pInfo->private; + int screenWidth = screenInfo.screens[pEvdev->screen]->width; + int screenHeight = screenInfo.screens[pEvdev->screen]->height; + + if (first != 0 || num != 2) + return FALSE; + + /* on absolute touchpads, don't warp on initial touch */ + if (pEvdev->flags & EVDEV_TOUCHPAD) { + *x = v0; + *y = v0; + return TRUE; } - if (state->btn) { - xfree (state->btn); - state->btn = NULL; + *x = (v0 - pEvdev->min_x) * screenWidth / (pEvdev->max_x - pEvdev->min_x); + *y = (v1 - pEvdev->min_y) * screenHeight / (pEvdev->max_y - pEvdev->min_y); + + return TRUE; +} + +static int +EvdevProbe(InputInfoPtr pInfo) +{ + char key_bitmask[(KEY_MAX + 7) / 8]; + char rel_bitmask[(REL_MAX + 7) / 8]; + char abs_bitmask[(ABS_MAX + 7) / 8]; + int i, has_axes, has_buttons, has_keys; + EvdevPtr pEvdev = pInfo->private; + + if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1) && errno == EINVAL) { + /* keyboards are unsafe in 2.4 */ + pEvdev->kernel24 = 1; + } else { + ioctl(pInfo->fd, EVIOCGRAB, (void *)0); } - if (state->abs) { - xfree (state->abs); - state->abs = NULL; + if (ioctl(pInfo->fd, + EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) < 0) { + xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno)); + return 1; } - if (state->rel) { - xfree (state->rel); - state->rel = NULL; + if (ioctl(pInfo->fd, + EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) { + xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno)); + return 1; } - if (state->axes) { - xfree (state->axes); - state->axes = NULL; + if (ioctl(pInfo->fd, + EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) { + xf86Msg(X_ERROR, "ioctl EVIOCGBIT failed: %s\n", strerror(errno)); + return 1; } - if (state->key) { - evdevKeyRec *key = state->key; + has_axes = FALSE; + has_buttons = FALSE; + has_keys = FALSE; - if (key->xkb_rules) { - xfree (key->xkb_rules); - key->xkb_rules = NULL; + if (TestBit(REL_X, rel_bitmask) && TestBit(REL_Y, rel_bitmask)) { + xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name); + pEvdev->flags |= EVDEV_RELATIVE_EVENTS; + has_axes = TRUE; + } + + if (TestBit(ABS_X, abs_bitmask) && TestBit(REL_Y, abs_bitmask)) { + xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name); + pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS; + if (TestBit(BTN_TOUCH, key_bitmask)) { + xf86Msg(X_INFO, "%s: Found absolute touchpad\n", pInfo->name); + pEvdev->flags |= EVDEV_TOUCHPAD; + pEvdev->old_x = pEvdev->old_y = -1; } + has_axes = TRUE; + } - if (key->xkb_model) { - xfree (key->xkb_model); - key->xkb_model = NULL; - } + if (TestBit(BTN_LEFT, key_bitmask)) { + xf86Msg(X_INFO, "%s: Found mouse buttons\n", pInfo->name); + pEvdev->flags |= EVDEV_BUTTON_EVENTS; + has_buttons = TRUE; + } - if (key->xkb_layout) { - xfree (key->xkb_layout); - key->xkb_layout = NULL; - } + for (i = 0; i < BTN_MISC; i++) + if (TestBit(i, key_bitmask)) + break; - if (key->xkb_variant) { - xfree (key->xkb_variant); - key->xkb_variant = NULL; - } + if (i < BTN_MISC) { + xf86Msg(X_INFO, "%s: Found keys\n", pInfo->name); + pEvdev->flags |= EVDEV_KEYBOARD_EVENTS; + has_keys = TRUE; + } - if (key->xkb_options) { - xfree (key->xkb_options); - key->xkb_options = NULL; - } + if (has_axes && has_buttons) { + xf86Msg(X_INFO, "%s: Configuring as mouse\n", pInfo->name); + pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS | + XI86_CONFIGURED; + pInfo->type_name = XI_MOUSE; + } - xfree (state->key); - state->key = NULL; + if (has_keys) { + if (pEvdev->kernel24) { + xf86Msg(X_INFO, "%s: Kernel < 2.6 is too old, ignoring keyboard\n", + pInfo->name); + } else { + xf86Msg(X_INFO, "%s: Configuring as keyboard\n", pInfo->name); + pInfo->flags |= XI86_KEYBOARD_CAPABLE | XI86_CONFIGURED; + pInfo->type_name = XI_KEYBOARD; + } } + if ((pInfo->flags & XI86_CONFIGURED) == 0) { + xf86Msg(X_WARNING, "%s: Don't know how to use device\n", + pInfo->name); + return 1; + } - xf86DeleteInput (pInfo, 0); + return 0; } +static InputInfoPtr +EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags) +{ + InputInfoPtr pInfo; + MessageType deviceFrom = X_CONFIG; + const char *device; + EvdevPtr pEvdev; + + if (!(pInfo = xf86AllocateInput(drv, 0))) + return NULL; + + /* Initialise the InputInfoRec. */ + pInfo->name = dev->identifier; + pInfo->flags = 0; + pInfo->type_name = "UNKNOWN"; + pInfo->device_control = EvdevProc; + pInfo->read_input = EvdevReadInput; + pInfo->history_size = 0; + pInfo->control_proc = NULL; + pInfo->close_proc = NULL; + pInfo->switch_mode = NULL; + pInfo->conversion_proc = EvdevConvert; + pInfo->reverse_conversion_proc = NULL; + pInfo->dev = NULL; + pInfo->private_flags = 0; + pInfo->always_core_feedback = 0; + pInfo->conf_idev = dev; + + if (!(pEvdev = xcalloc(sizeof(*pEvdev), 1))) + return pInfo; + pInfo->private = pEvdev; + + if (!(pEvdev = xcalloc(sizeof(EvdevRec), 1))) + return pInfo; + + pInfo->private = pEvdev; + + xf86CollectInputOptions(pInfo, evdevDefaults, NULL); + xf86ProcessCommonOptions(pInfo, pInfo->options); + + pEvdev->screen = xf86SetIntOption(pInfo->options, "ScreenNumber", 0); + /* + * We initialize pEvdev->tool to 1 so that device that doesn't use + * proximity will still report events. + */ + pEvdev->tool = 1; + + device = xf86CheckStrOption(dev->commonOptions, "Path", NULL); + if (!device) + device = xf86CheckStrOption(dev->commonOptions, "Device", NULL); + if (!device) { + xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name); + xf86DeleteInput(pInfo, 0); + return NULL; + } + + xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device); + do { + pInfo->fd = open(device, O_RDWR, 0); + } + while (pInfo->fd < 0 && errno == EINTR); + + if (pInfo->fd < 0) { + xf86Msg(X_ERROR, "Unable to open evdev device \"%s\".\n", device); + xf86DeleteInput(pInfo, 0); + return NULL; + } + + pEvdev->noXkb = noXkbExtension; + /* parse the XKB options during kbd setup */ + + if (EvdevProbe(pInfo)) { + xf86DeleteInput(pInfo, 0); + return NULL; + } + + return pInfo; +} _X_EXPORT InputDriverRec EVDEV = { 1, "evdev", NULL, EvdevPreInit, - EvdevUnInit, + NULL, NULL, 0 }; @@ -565,8 +1097,8 @@ static XF86ModuleVersionInfo EvdevVersionRec = MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, - XORG_VERSION_CURRENT, - PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, + 0, /* Missing from SDK: XORG_VERSION_CURRENT, */ + 1, 0, 0, ABI_CLASS_XINPUT, ABI_XINPUT_VERSION, MOD_CLASS_XINPUT, diff --git a/src/evdev.h b/src/evdev.h deleted file mode 100644 index 2cdc5bc..0000000 --- a/src/evdev.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright © 2006-2007 Zephaniah E. Hull - * Copyright © 2004 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Soft- - * ware"), to deal in the Software without restriction, including without - * limitation the rights to use, copy, modify, merge, publish, distribute, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, provided that the above copyright - * notice(s) and this permission notice appear in all copies of the Soft- - * ware and that both the above copyright notice(s) and this permission - * notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- - * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY - * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN - * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- - * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- - * MANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder shall - * not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization of - * the copyright holder. - * - * Authors: - * Zephaniah E. Hull (warp@aehallh.com) - * Kristian Høgsberg (krh@redhat.com) - */ - -#ifndef __EVDEV_H -#define __EVDEV_H - -#define _XF86_ANSIC_H -#define XF86_LIBC_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <linux/input.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <xf86Xinput.h> - -#ifndef BITS_PER_LONG -#define BITS_PER_LONG (sizeof(unsigned long) * 8) -#endif - -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define LONG(x) ((x)/BITS_PER_LONG) -#define MASK(x) (1UL << ((x) & (BITS_PER_LONG - 1))) - -#ifndef test_bit -#define test_bit(bit, array) (!!(array[LONG(bit)] & MASK(bit))) -#endif -#ifndef set_bit -#define set_bit(bit, array) (array[LONG(bit)] |= MASK(bit)) -#endif -#ifndef clear_bit -#define clear_bit(bit, array) (array[LONG(bit)] &= ~MASK(bit)) -#endif - - -#include <X11/extensions/XKB.h> -#include <X11/extensions/XKBstr.h> - -/* - * At the moment, ABS_MAX is larger then REL_MAX. - * As they are the only two providors of axes, ABS_MAX is it. - */ -#define AXES_MAX ABS_MAX - - -#define BTN_MAX 96 - -struct _evdevDevice; - -/* - * FIXME: The mode option here is a kludge. - * It can be 0 (rel mode), 1 (abs mode), or -1 (input side has no clue). - * - * Worse, it arguably shouldn't even be the sender that decides here. - * And only the Axes targets and sources care at all right now. - */ -typedef void (*evdev_map_func_f)(InputInfoPtr pInfo, int value, int mode, void *map_data); - -typedef struct { - unsigned long ev[NBITS(EV_MAX)]; - unsigned long key[NBITS(KEY_MAX)]; - unsigned long rel[NBITS(REL_MAX)]; - unsigned long abs[NBITS(ABS_MAX)]; - unsigned long msc[NBITS(MSC_MAX)]; - unsigned long led[NBITS(LED_MAX)]; - unsigned long snd[NBITS(SND_MAX)]; - unsigned long ff[NBITS(FF_MAX)]; -} evdevBitsRec, *evdevBitsPtr; - -#define EV_BTN_B_PRESENT (1<<0) - -typedef struct { - int real_buttons; - int buttons; - int b_flags[BTN_MAX]; - void *b_map_data[BTN_MAX]; - evdev_map_func_f b_map[BTN_MAX]; - void (*callback[BTN_MAX])(InputInfoPtr pInfo, int button, int value); -} evdevBtnRec, *evdevBtnPtr; - -#define EV_ABS_V_PRESENT (1<<0) -#define EV_ABS_V_M_AUTO (1<<1) -#define EV_ABS_V_M_REL (1<<2) -#define EV_ABS_V_INVERT (1<<3) -#define EV_ABS_V_RESET (1<<4) -#define EV_ABS_V_USE_TOUCH (1<<5) - -#define EV_ABS_USE_TOUCH (1<<0) -#define EV_ABS_TOUCH (1<<1) -#define EV_ABS_UPDATED (1<<2) - -typedef struct { - int flags; - int axes; - int v[ABS_MAX]; - int v_flags[ABS_MAX]; - void *v_map_data[ABS_MAX]; - evdev_map_func_f v_map[ABS_MAX]; -} evdevAbsRec, *evdevAbsPtr; - -#define EV_REL_V_PRESENT (1<<0) -#define EV_REL_V_INVERT (1<<1) -#define EV_REL_UPDATED (1<<0) - -typedef struct { - int flags; - int v_flags[REL_MAX]; - int v[REL_MAX]; - int axes; - void *v_map_data[REL_MAX]; - evdev_map_func_f v_map[REL_MAX]; -} evdevRelRec, *evdevRelPtr; - -#define EV_AXES_V_M_ABS (1<<0) -#define EV_AXES_V_M_REL (1<<1) -#define EV_AXES_V_PRESENT (1<<2) -#define EV_AXES_V_UPDATED (1<<3) - -#define EV_AXES_V_M_MASK (EV_AXES_V_M_ABS | EV_AXES_V_M_REL) - -#define EV_AXES_UPDATED (1<<0) - -typedef struct { - int axes; - int flags; - int v_flags[AXES_MAX]; - int v_min[AXES_MAX]; - int v_max[AXES_MAX]; - int v[AXES_MAX]; - int rotation; - float rot_sin, rot_cos; - int x, y; -} evdevAxesRec, *evdevAxesPtr; - -typedef struct { - char *xkb_rules; - char *xkb_model; - char *xkb_layout; - char *xkb_variant; - char *xkb_options; - XkbComponentNamesRec xkbnames; -} evdevKeyRec, *evdevKeyPtr; - -typedef struct _evdevState { - Bool can_grab; - Bool sync; - - evdevBtnPtr btn; - evdevAbsPtr abs; - evdevRelPtr rel; - evdevKeyPtr key; - evdevAxesPtr axes; -} evdevStateRec, *evdevStatePtr; - -typedef struct _evdevDevice { - const char *device; - - evdevBitsRec bits; - - evdevStateRec state; -} evdevDeviceRec, *evdevDevicePtr; - -int EvdevBtnInit (DeviceIntPtr device); -int EvdevBtnOn (DeviceIntPtr device); -int EvdevBtnOff (DeviceIntPtr device); -int EvdevBtnNew0(InputInfoPtr pInfo); -int EvdevBtnNew1(InputInfoPtr pInfo); -void EvdevBtnProcess (InputInfoPtr pInfo, struct input_event *ev); -void EvdevBtnPostFakeClicks(InputInfoPtr pInfo, int button, int count); -int EvdevBtnFind (InputInfoPtr pInfo, const char *button); -int EvdevBtnExists (InputInfoPtr pInfo, int button); - -int EvdevAxesInit (DeviceIntPtr device); -int EvdevAxesOn (DeviceIntPtr device); -int EvdevAxesOff (DeviceIntPtr device); -int EvdevAxesNew0(InputInfoPtr pInfo); -int EvdevAxesNew1(InputInfoPtr pInfo); -void EvdevAxesAbsProcess (InputInfoPtr pInfo, struct input_event *ev); -void EvdevAxesRelProcess (InputInfoPtr pInfo, struct input_event *ev); -void EvdevAxesSynRep (InputInfoPtr pInfo); -void EvdevAxesSynCfg (InputInfoPtr pInfo); - -int EvdevKeyInit (DeviceIntPtr device); -int EvdevKeyNew (InputInfoPtr pInfo); -int EvdevKeyOn (DeviceIntPtr device); -int EvdevKeyOff (DeviceIntPtr device); -void EvdevKeyProcess (InputInfoPtr pInfo, struct input_event *ev); - - -/* - * Option handling stuff. - */ - -typedef struct evdev_option_token_s { - const char *str; - struct evdev_option_token_s *chain; - struct evdev_option_token_s *next; -} evdev_option_token_t; - -typedef Bool (*evdev_parse_opt_func_f)(InputInfoPtr pInfo, const char *name, evdev_option_token_t *token, int *flags); -typedef Bool (*evdev_parse_map_func_f)(InputInfoPtr pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func); - -evdev_option_token_t *EvdevTokenize (const char *option, const char *tokens); -void EvdevFreeTokens (evdev_option_token_t *token); -Bool EvdevParseMapToRelAxis (InputInfoPtr pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func); -Bool EvdevParseMapToAbsAxis (InputInfoPtr pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func); -Bool -EvdevParseMapToButton (InputInfoRec *pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func); -Bool -EvdevParseMapToButtons (InputInfoRec *pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func); - -typedef struct { - char *name; - evdev_parse_map_func_f func; -} evdev_map_parsers_t; - -extern evdev_map_parsers_t evdev_map_parsers[]; -Bool EvdevParseMapOption (InputInfoRec *pInfo, char *option, char *def, void **map_data, evdev_map_func_f *map_func); - -#endif /* __EVDEV_H */ diff --git a/src/evdev_axes.c b/src/evdev_axes.c deleted file mode 100644 index 5d196ab..0000000 --- a/src/evdev_axes.c +++ /dev/null @@ -1,943 +0,0 @@ -/* - * Copyright © 2006-2007 Zephaniah E. Hull - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Soft- - * ware"), to deal in the Software without restriction, including without - * limitation the rights to use, copy, modify, merge, publish, distribute, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, provided that the above copyright - * notice(s) and this permission notice appear in all copies of the Soft- - * ware and that both the above copyright notice(s) and this permission - * notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- - * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY - * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN - * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- - * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- - * MANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder shall - * not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization of - * the copyright holder. - * - * Author: Zephaniah E. Hull (warp@aehallh.com) - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <X11/keysym.h> -#include <X11/XF86keysym.h> -#include <X11/extensions/XIproto.h> - -#include <string.h> - -#include "evdev.h" - -#include <xf86.h> - -#include <xf86Module.h> -#include <mipointer.h> - - -#include <xf86_OSproc.h> - -#undef DEBUG - -static char *rel_axis_names[] = { - "X", - "Y", - "Z", - "RX", - "RY", - "RZ", - "HWHEEL", - "DIAL", - "WHEEL", - "MISC", - "10", - "11", - "12", - "13", - "14", - "15", - NULL -}; - -static char *abs_axis_names[] = { - "X", - "Y", - "Z", - "RX", - "RY", - "RZ", - "THROTTLE", - "RUDDER", - "WHEEL", - "GAS", - "BRAKE", - "11", - "12", - "13", - "14", - "15", - "HAT0X", - "HAT0Y", - "HAT1X", - "HAT1Y", - "HAT2X", - "HAT2Y", - "HAT3X", - "HAT3Y", - "PRESSURE", - "TILT_X", - "TILT_Y", - "TOOL_WIDTH", - "VOLUME", - "29", - "30", - "31", - "32", - "33", - "34", - "35", - "36", - "37", - "38", - "39", - "MISC", - "41", - "42", - "43", - "44", - "45", - "46", - "47", - "48", - "49", - "50", - "51", - "52", - "53", - "54", - "55", - "56", - "57", - "58", - "59", - "60", - "61", - "62", - NULL -}; - -static void EvdevAxesTouchCallback (InputInfoPtr pInfo, int button, int value); - -void -EvdevAxesMapAxis (InputInfoPtr pInfo, int value, int mode, void *map_data) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevAxesPtr axes = state->axes; - long map = (long) map_data; - - if (map >= AXES_MAX || !axes || !(axes->v_flags[map] & (EV_AXES_V_M_ABS | EV_AXES_V_M_REL))) - return; - - axes->v[map] = value; - if (mode == 0) { - axes->v_flags[map] &= ~EV_AXES_V_M_ABS; - axes->v_flags[map] |= EV_AXES_V_M_REL; - } else if (mode == 1) { - axes->v_flags[map] &= ~EV_AXES_V_M_REL; - axes->v_flags[map] |= EV_AXES_V_M_ABS; - } - axes->v_flags[map] |= EV_AXES_V_UPDATED; - axes->flags |= EV_AXES_UPDATED; -} - -static Bool -EvdevParseRelOptions (InputInfoPtr pInfo, const char *name, evdev_option_token_t *option, int *flags) -{ - if (!option) - return 0; - - for (; option; option = option->next) { - if (!strcasecmp (option->str, "invert")) - *flags |= EV_REL_V_INVERT; - else - xf86Msg(X_ERROR, "%s: %s unknown relative option '%s'.\n", pInfo->name, name, option->str); - - } - *flags |= EV_REL_V_PRESENT; - - return 1; -} - -static Bool -EvdevParseAbsOptions (InputInfoPtr pInfo, const char *name, evdev_option_token_t *option, int *flags) -{ - if (!option) - return 0; - - for (; option; option = option->next) { - if (!strcasecmp (option->str, "invert")) - *flags |= EV_ABS_V_INVERT; - else if (!strcasecmp (option->str, "use_touch")) - *flags |= EV_ABS_V_USE_TOUCH; - else if (!strcasecmp (option->str, "mode_auto")) - *flags |= EV_ABS_V_M_AUTO; - else if (!strcasecmp (option->str, "mode_rel")) - *flags |= EV_ABS_V_M_REL; - else - xf86Msg(X_ERROR, "%s: %s unknown absolute option '%s'.\n", pInfo->name, name, option->str); - - } - *flags |= EV_ABS_V_PRESENT; - - return 1; -} - -Bool -EvdevParseMapToRelAxis (InputInfoPtr pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevAxesPtr axes = state->axes; - long i; - - errno = 0; - i = strtol (option->str, NULL, 0); - if (errno) { - for (i = 0; rel_axis_names[i]; i++) { - if (!strcmp (option->str, rel_axis_names[i])) - break; - } - if (!rel_axis_names[i]) - return 0; - } - if ((i < 0) || (i > AXES_MAX)) - return 0; - - if (axes->v_flags[i] & EV_AXES_V_PRESENT) - return 0; - - axes->v_flags[i] = EV_AXES_V_M_REL | EV_AXES_V_PRESENT; - - *map_data = (void *) i; - *map_func = EvdevAxesMapAxis; - - return 1; -} - -Bool -EvdevParseMapToAbsAxis (InputInfoPtr pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevAxesPtr axes = state->axes; - long i; - - errno = 0; - i = strtol (option->str, NULL, 0); - if (errno) { - for (i = 0; abs_axis_names[i]; i++) { - if (!strcmp (option->str, abs_axis_names[i])) - break; - } - if (!abs_axis_names[i]) { - xf86Msg (X_ERROR, "%s: %s: No axis named '%s'.\n", pInfo->name, name, option->str); - return 0; - } - } - if ((i < 0) || (i > AXES_MAX)) { - xf86Msg (X_ERROR, "%s: %s: Axis %ld out of range.\n", pInfo->name, name, i); - return 0; - } - - if (axes->v_flags[i] & EV_AXES_V_PRESENT) { - xf86Msg (X_ERROR, "%s: %s: Axis %ld already claimed.\n", pInfo->name, name, i); - return 0; - } - - option = option->next; - if (!option) { - xf86Msg (X_ERROR, "%s: %s: No min.\n", pInfo->name, name); - return 0; - } - - errno = 0; - axes->v_min[i] = strtol (option->str, NULL, 0); - if (errno) { - xf86Msg (X_ERROR, "%s: %s: Unable to parse '%s' as min. (%s)\n", pInfo->name, name, option->str, strerror(errno)); - return 0; - } - - option = option->next; - if (!option) { - xf86Msg (X_ERROR, "%s: %s: No max.\n", pInfo->name, name); - return 0; - } - - errno = 0; - axes->v_max[i] = strtol (option->str, NULL, 0); - if (errno) { - xf86Msg (X_ERROR, "%s: %s: Unable to parse '%s' as max. (%s)\n", pInfo->name, name, option->str, strerror(errno)); - return 0; - } - - axes->v_flags[i] = EV_AXES_V_M_ABS | EV_AXES_V_PRESENT; - - *map_data = (void *) i; - *map_func = EvdevAxesMapAxis; - - return 1; -} - -static Bool -EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2, - int v3, int v4, int v5, int *x, int *y) -{ - if (first == 0) { - *x = v0; - *y = v1; - return TRUE; - } else - return FALSE; -} - - -/* - * Rotation and rep code, this is a mess and much of it needs to live in mi/ - * after a cleanup. - */ -static void -EvdevAxesDoRotation (InputInfoPtr pInfo) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevAxesPtr axes = state->axes; - DeviceIntPtr dev = pInfo->dev; - AbsoluteClassRec *dabs = dev->absolute; - - /* - * Rotation. - * Cache the sine and cosine results so we're not doing it every time. - */ - if (dabs->rotation != axes->rotation || (axes->rot_cos == axes->rot_sin)) { - axes->rotation = dabs->rotation % 360; - axes->rot_cos = cos ( ((float) axes->rotation) * (M_PI/180)); - axes->rot_sin = sin ( ((float) axes->rotation) * (M_PI/180)); - } - - if (axes->rotation) { - float x = axes->v[0], y = axes->v[1]; - axes->v[0] = (x * axes->rot_cos) - (y * axes->rot_sin); - axes->v[1] = (y * axes->rot_cos) + (x * axes->rot_sin); - - axes->v_flags[0] |= EV_AXES_V_UPDATED; - axes->v_flags[1] |= EV_AXES_V_UPDATED; -#if DEBUG - xf86Msg(X_ERROR, "%s %d (%s): rotation=%d, cos=%f, sin=%f, x=%f, y=%f, v[0]=%d, v[1]=%d\n", __FILE__, __LINE__, __FUNCTION__, - axes->rotation, axes->rot_cos, axes->rot_sin, x, y, axes->v[0], axes->v[1]); -#endif - } -} - -/* - * Cx - raw data from touch screen - * Sxhigh - scaled highest dimension - * (remember, this is of rows - 1 because of 0 origin) - * Sxlow - scaled lowest dimension - * Rxhigh - highest raw value from touch screen calibration - * Rxlow - lowest raw value from touch screen calibration - * - * This function is the same for X or Y coordinates. - * You may have to reverse the high and low values to compensate for - * different orgins on the touch screen vs X. - */ - -_X_EXPORT int -EvdevScaleAxis(int Cx, - int Sxlow, - int Sxhigh, - int Rxlow, - int Rxhigh) -{ - int X; - int dSx = Sxhigh - Sxlow; - int dRx = Rxhigh - Rxlow; - - /* This is +, because Cx is negitive, so we're really subtracting. */ - if (Cx < 0) - Cx = Rxhigh + Cx; - - dSx = Sxhigh - Sxlow; - if (dRx) { - X = ((dSx * (Cx - Rxlow)) / dRx) + Sxlow; - } - else { - X = 0; - ErrorF ("Divide by Zero in evdevScaleAxis"); - } - - if (X < Sxlow) - X = Sxlow; - if (X > Sxhigh) - X = Sxhigh; - - return (X); -} - -void -EvdevAxesSynRep (InputInfoPtr pInfo) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevAxesPtr axes = state->axes; - DeviceIntPtr dev = pInfo->dev; - AbsoluteClassRec *dabs = dev->absolute; - - int i, start, run, mode; - - if (!axes || !(axes->flags & EV_AXES_UPDATED)) - return; - - start = 0; - mode = 0; - run = 0; - - /* - * This handles most, but not all, of the ABS_CALIB and ABS_AREA - * additions to XInput 1.0. - * - * Note, we do this if both X and Y are set to absolute, or a more - * limited subset if both X and Y are relative, we don't do anything - * if we lack X or Y, or if they are not both set to both be ABS or REL. - */ - if (axes->axes >= 2 && dabs) { - if ((axes->v_flags[0] & EV_AXES_V_M_ABS) && - (axes->v_flags[1] & EV_AXES_V_M_ABS) && - ((axes->v_flags[0] & EV_AXES_V_UPDATED) || - (axes->v_flags[1] & EV_AXES_V_UPDATED)) - ) { - int width, height, min_x, max_x, min_y, max_y; - - if (axes->v_flags[0] & EV_AXES_V_UPDATED) axes->x = axes->v[0]; - else axes->v[0] = axes->x; - if (axes->v_flags[1] & EV_AXES_V_UPDATED) axes->y = axes->v[1]; - else axes->v[1] = axes->y; - - if (dabs->width > 0) - width = dabs->width; - else - width = screenInfo.screens[dabs->screen]->width; - - if (dabs->height > 0) - height = dabs->height; - else - height = screenInfo.screens[dabs->screen]->height; - - if (dabs->flip_x) - axes->v[0] = dabs->max_x - axes->v[0]; - if (dabs->flip_y) - axes->v[1] = dabs->max_y - axes->v[1]; - - /* - * In some cases we need to swap width and height. - * This depends on the rotation. - */ - if ( (axes->rotation >= 45 && axes->rotation < 135) || - (axes->rotation >= 225 && axes->rotation < 315)) { - min_x = dabs->min_y; - max_x = dabs->max_y; - min_y = dabs->min_x; - max_y = dabs->max_x; - } else { - min_x = dabs->min_x; - max_x = dabs->max_x; - min_y = dabs->min_y; - max_y = dabs->max_y; - } - - EvdevAxesDoRotation (pInfo); - - axes->v[0] = EvdevScaleAxis (axes->v[0], 0, width, min_x, max_x); - axes->v[1] = EvdevScaleAxis (axes->v[1], 0, height, min_y, max_y); - - axes->v[0] += dabs->offset_x; - axes->v[1] += dabs->offset_y; - - xf86XInputSetScreen (pInfo, dabs->screen, axes->v[0], axes->v[1]); - } else if ((axes->v_flags[0] & EV_AXES_V_M_REL) && - (axes->v_flags[1] & EV_AXES_V_M_REL) && - ((axes->v_flags[0] & EV_AXES_V_UPDATED) || - (axes->v_flags[1] & EV_AXES_V_UPDATED)) - ) { - - if (axes->v_flags[0] & EV_AXES_V_UPDATED) axes->x = axes->v[0]; - else axes->v[0] = axes->x; - if (axes->v_flags[1] & EV_AXES_V_UPDATED) axes->y = axes->v[1]; - else axes->v[1] = axes->y; - - if (dabs->flip_x) - axes->v[0] = -axes->v[0]; - if (dabs->flip_y) - axes->v[1] = -axes->v[1]; - - EvdevAxesDoRotation (pInfo); - } - } - -#if DEBUG - xf86Msg(X_ERROR, "%s %d (%s): v[0]=%d%s%s, v[1]=%d%s%s, v[2]=%d%s%s\n", __FILE__, __LINE__, __FUNCTION__, - axes->v[0], - axes->v_flags[0] & EV_AXES_V_M_ABS ? "!" : "", - axes->v_flags[0] & EV_AXES_V_UPDATED ? "*" : "", - axes->v[1], - axes->v_flags[1] & EV_AXES_V_M_ABS ? "!" : "", - axes->v_flags[1] & EV_AXES_V_UPDATED ? "*" : "", - axes->v[2], - axes->v_flags[2] & EV_AXES_V_M_ABS ? "!" : "", - axes->v_flags[2] & EV_AXES_V_UPDATED ? "*" : ""); -#endif - for (i = 0; i < axes->axes; i++) { - if (axes->v_flags[i] & EV_AXES_V_UPDATED) { - if (run) { - if (mode != (axes->v_flags[i] & EV_AXES_V_M_MASK)) { - mode = (mode == EV_AXES_V_M_ABS); -#if DEBUG - xf86Msg(X_ERROR, "%s %d (%s): mode=%d, start=%d, i - start=%d\n", __FILE__, __LINE__, __FUNCTION__, - mode, start, i - start); -#endif - xf86PostMotionEventP (pInfo->dev, mode, start, i - start, axes->v + start); - start = i; - mode = axes->v_flags[i] & EV_AXES_V_M_MASK; - } - } else { - start = i; - mode = axes->v_flags[i] & EV_AXES_V_M_MASK; - } - run = 1; - axes->v_flags[i] &= ~EV_AXES_V_UPDATED; - } else if (run) { - mode = (mode == EV_AXES_V_M_ABS); - xf86PostMotionEventP (pInfo->dev, mode, start, i - start, axes->v + start); - run = 0; - } - } - if (run) { - mode = (mode == EV_AXES_V_M_ABS); - xf86PostMotionEventP (pInfo->dev, mode, start, i - start, axes->v + start); - } -} -/* - * End rotation and rep code, this is a mess and much of it needs to live in mi/ - * after a cleanup. - */ - - -void -EvdevAxesSynCfg (InputInfoPtr pInfo) -{ -/* EvdevAxesAbsSynCfg (pInfo);*/ -/* EvdevAxesRelSynCfg (pInfo);*/ -} - -void -EvdevAxesAbsProcess (InputInfoPtr pInfo, struct input_event *ev) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevAbsRec *abs = state->abs; - int value, v_flags, is_rel; - - if (ev->code >= ABS_MAX || !abs->v_map[ev->code]) - return; - - value = ev->value; - v_flags = abs->v_flags[ev->code]; - - if ((v_flags & EV_ABS_V_USE_TOUCH) && !(state->abs->flags & EV_ABS_TOUCH)) - return; - -#if 0 - if (v_flags & EV_ABS_V_INVERT) - value = -value; -#endif - - if (v_flags & EV_ABS_V_M_REL) - is_rel = 1; - else if ((v_flags & EV_ABS_V_M_AUTO) && pInfo->dev->valuator->mode == Relative) - is_rel = 1; - else - is_rel = 0; - - if (is_rel) { - if ((v_flags & EV_ABS_V_RESET) && value != abs->v[ev->code]) { - abs->v_flags[ev->code] &= ~EV_ABS_V_RESET; - } else - abs->v_map[ev->code](pInfo, value - abs->v[ev->code], 0, abs->v_map_data[ev->code]); - - abs->v[ev->code] = value; - } else - abs->v_map[ev->code](pInfo, value, 1, abs->v_map_data[ev->code]); - -} - -void -EvdevAxesRelProcess (InputInfoPtr pInfo, struct input_event *ev) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevRelRec *rel = state->rel; - int value, v_flags; - - if (ev->code >= REL_MAX || !rel->v_map[ev->code]) - return; - - value = ev->value; - v_flags = rel->v_flags[ev->code]; - - if (v_flags & EV_REL_V_INVERT) - value = -value; - - rel->v_map[ev->code](pInfo, value, 0, rel->v_map_data[ev->code]); -} - -int -EvdevAxesOn (DeviceIntPtr device) -{ - return Success; -} - -int -EvdevAxesOff (DeviceIntPtr device) -{ - return Success; -} - -static int -EvdevAxisAbsNew(InputInfoPtr pInfo) -{ - evdevDeviceRec *pEvdev = pInfo->private; - evdevStateRec *state = &pEvdev->state; - evdevAbsRec *abs; - struct input_absinfo absinfo; - char option[128], value[128]; - const char *s; - int i, j, real_axes; - evdev_option_token_t *tokens; - - real_axes = 0; - for (i = 0; i < ABS_MAX; i++) - if (test_bit (i, pEvdev->bits.abs)) - real_axes++; - - if (!real_axes) - return !Success; - - state->abs = abs = Xcalloc (sizeof (evdevAbsRec)); - - xf86Msg(X_INFO, "%s: Found %d absolute axes.\n", pInfo->name, real_axes); - xf86Msg(X_INFO, "%s: Configuring as pointer.\n", pInfo->name); - pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS | - XI86_CONFIGURED; - pInfo->type_name = XI_MOUSE; - pInfo->conversion_proc = EvdevConvert; - - for (i = 0, j = 0; i < ABS_MAX; i++) { - if (!test_bit (i, pEvdev->bits.abs)) - continue; - - if (ioctl (pInfo->fd, EVIOCGABS(i), &absinfo) < 0) { - xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno)); - return !Success; - } - - snprintf(option, sizeof(option), "Abs%sMapTo", abs_axis_names[i]); - snprintf(value, sizeof(value), "AbsAxis %d %d %d", j, absinfo.minimum, absinfo.maximum); - - EvdevParseMapOption (pInfo, option, value, &abs->v_map_data[i], &abs->v_map[i]); - - snprintf(option, sizeof(option), "Abs%sOptions", abs_axis_names[i]); - if (i == ABS_X || i == ABS_Y) - s = xf86SetStrOption(pInfo->options, option, "use_touch mode_auto"); - else - s = xf86SetStrOption(pInfo->options, option, ""); - if (s[0]) { - tokens = EvdevTokenize (s, " "); - if (!EvdevParseAbsOptions (pInfo, option, tokens, &abs->v_flags[i])) - xf86Msg (X_ERROR, "%s: Unable to parse '%s' as absolute options.\n", pInfo->name, s); - EvdevFreeTokens (tokens); - } - abs->v_flags[i] |= EV_ABS_V_PRESENT; - - j++; - } - - state->abs->axes = real_axes; - - return Success; -} - -static int -EvdevAxisAbsNew1(InputInfoPtr pInfo) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - char *s; - - if (!state->abs) - return !Success; - - xf86Msg(X_CONFIG, "%s: Configuring %d absolute axes.\n", pInfo->name, - state->abs->axes); - - { - int btn; - int i; - - s = xf86SetStrOption(pInfo->options, "AbsoluteTouch", "DIGI_Touch"); - btn = EvdevBtnFind (pInfo, s); - if (btn != -1) { - if (EvdevBtnExists (pInfo, btn)) { - state->abs->flags |= EV_ABS_USE_TOUCH; - xf86Msg(X_ERROR, "%s: Button: %d.\n", pInfo->name, btn); - xf86Msg(X_ERROR, "%s: state->btn: %p.\n", pInfo->name, state->btn); - state->btn->callback[btn] = &EvdevAxesTouchCallback; - } else { - - /* - * If the device does not have a touch button, then clear - * EV_ABS_V_USE_TOUCH which we may have set for the X and Y - * axes in EvdevAxisAbsNew. - */ - for (i = 0; i < ABS_MAX; i++) { - if ((i == ABS_X || i == ABS_Y) && - state->abs->v_flags[i] & EV_ABS_V_PRESENT) { - state->abs->v_flags[i] &= ~EV_ABS_V_USE_TOUCH; - } - } - xf86Msg(X_ERROR, "%s: AbsoluteTouch: '%s' does not exist.\n", pInfo->name, s); - } - } else { - xf86Msg(X_ERROR, "%s: AbsoluteTouch: '%s' is not a valid button name.\n", pInfo->name, s); - } - } - - return Success; -} - -static int -EvdevAxisRelNew(InputInfoPtr pInfo) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevRelPtr rel; - char *s, option[128], value[128]; - int i, j, real_axes; - evdev_option_token_t *tokens; - - real_axes = 0; - for (i = 0; i < REL_MAX; i++) - if (test_bit (i, pEvdev->bits.rel)) - real_axes++; - - if (!real_axes && (!state->abs || state->abs->axes < 2)) - return !Success; - - state->rel = rel = Xcalloc (sizeof (evdevRelRec)); - - xf86Msg(X_INFO, "%s: Found %d relative axes.\n", pInfo->name, - real_axes); - xf86Msg(X_INFO, "%s: Configuring as pointer.\n", pInfo->name); - pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS | - XI86_CONFIGURED; - pInfo->type_name = XI_MOUSE; - pInfo->conversion_proc = EvdevConvert; - - for (i = 0, j = 0; i < REL_MAX; i++) { - if (!test_bit (i, pEvdev->bits.rel)) - continue; - - snprintf(option, sizeof(option), "Rel%sMapTo", rel_axis_names[i]); - if (i == REL_WHEEL || i == REL_Z) - snprintf(value, sizeof(value), "Buttons 4 5 1"); - else if (i == REL_HWHEEL) - snprintf(value, sizeof(value), "Buttons 6 7 1"); - else - snprintf(value, sizeof(value), "RelAxis %d", j); - - EvdevParseMapOption (pInfo, option, value, &rel->v_map_data[i], &rel->v_map[i]); - - snprintf(option, sizeof(option), "Rel%sOptions", rel_axis_names[i]); - s = xf86SetStrOption(pInfo->options, option, ""); - if (s[0]) { - tokens = EvdevTokenize (s, " "); - if (!EvdevParseRelOptions (pInfo, option, tokens, &rel->v_flags[i])) - xf86Msg (X_ERROR, "%s: Unable to parse '%s' as relative options.\n", pInfo->name, s); - EvdevFreeTokens (tokens); - } - rel->v_flags[i] |= EV_REL_V_PRESENT; - - - j++; - } - - return Success; -} - -int -EvdevAxesNew0 (InputInfoPtr pInfo) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - int ret = Success; - - state->axes = Xcalloc (sizeof (evdevAxesRec)); - if (EvdevAxisAbsNew(pInfo) != Success) - ret = !Success; - if (EvdevAxisRelNew(pInfo) != Success) - ret = !Success; - if (!state->abs && !state->rel) { - Xfree (state->axes); - state->axes = NULL; - } - - return ret; -} - -int -EvdevAxesNew1 (InputInfoPtr pInfo) -{ - evdevDeviceRec *pEvdev = pInfo->private; - evdevStateRec *state = &pEvdev->state; - evdevAxesRec *axes = state->axes; - int i, ret = Success; - - if (!state->axes) - return ret; - - for (i = 0; i < AXES_MAX; i++) - if (axes->v_flags[i] & EV_AXES_V_PRESENT) - axes->axes = i + 1; - - if (EvdevAxisAbsNew1(pInfo) != Success) - ret = !Success; - if (!state->abs && !state->rel) { - Xfree (state->axes); - state->axes = NULL; - } - - return ret; -} - - -static void -EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl) -{ - /* Nothing to do, dix handles all settings */ -} - -int -EvdevAxesInit (DeviceIntPtr device) -{ - InputInfoPtr pInfo = device->public.devicePrivate; - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - evdevAxesRec *axes = state->axes; - AbsoluteClassRec *dev_abs; - int i; - const char *s; - - if (!axes || !axes->axes) - return Success; - - xf86Msg(X_CONFIG, "%s: %d valuators.\n", pInfo->name, - axes->axes); - - if (!InitValuatorClassDeviceStruct(device, axes->axes, - GetMotionHistory, - GetMotionHistorySize(), - 0)) - return !Success; - - - /* - * This has to go in Init, because until now there is no valuator struct - * allocated. - */ - s = xf86SetStrOption(pInfo->options, "Mode", "Absolute"); - if (!strcasecmp(s, "Absolute")) { - pInfo->dev->valuator->mode = Absolute; - xf86Msg(X_CONFIG, "%s: Configuring in %s mode.\n", pInfo->name, s); - } else if (!strcasecmp(s, "Relative")) { - pInfo->dev->valuator->mode = Relative; - xf86Msg(X_CONFIG, "%s: Configuring in %s mode.\n", pInfo->name, s); - } else { - pInfo->dev->valuator->mode = Absolute; - xf86Msg(X_CONFIG, "%s: Unknown Mode: %s.\n", pInfo->name, s); - } - - /* - * Yes, we want to do this for relative devices too. - * Some of the settings are useful for both. - */ - if ((axes->v_flags[0] & EV_AXES_V_PRESENT) && - (axes->v_flags[1] & EV_AXES_V_PRESENT) && - InitAbsoluteClassDeviceStruct (device)) { - dev_abs = device->absolute; - if (axes->v_min[0] != axes->v_max[1] && axes->v_min[1] != axes->v_max[1]) { - device->absolute->min_x = axes->v_min[0]; - device->absolute->max_x = axes->v_max[0]; - device->absolute->min_y = axes->v_min[1]; - device->absolute->max_y = axes->v_max[1]; - } - } - - for (i = 0; i < axes->axes; i++) { - xf86InitValuatorAxisStruct(device, i, -1, -1, 1, 1, 1); - - xf86InitValuatorDefaults(device, i); - } - - if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) - return !Success; - - return Success; -} - -static void -EvdevAxesTouchCallback (InputInfoPtr pInfo, int button, int value) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - int i; - -#if DEBUG - xf86Msg(X_INFO, "%s: Touch callback; %d.\n", pInfo->name, value); -#endif - if (state->abs->flags & EV_ABS_USE_TOUCH) { - if (value) { - state->abs->flags |= EV_ABS_TOUCH; - for (i = 0; i < ABS_MAX; i++) - if (state->abs->v_flags[i] & EV_ABS_V_USE_TOUCH) - state->abs->v_flags[i] |= EV_ABS_V_RESET; - } else - state->abs->flags &= ~EV_ABS_TOUCH; - } -} diff --git a/src/evdev_btn.c b/src/evdev_btn.c deleted file mode 100644 index 340be82..0000000 --- a/src/evdev_btn.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright © 2006-2007 Zephaniah E. Hull - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Soft- - * ware"), to deal in the Software without restriction, including without - * limitation the rights to use, copy, modify, merge, publish, distribute, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, provided that the above copyright - * notice(s) and this permission notice appear in all copies of the Soft- - * ware and that both the above copyright notice(s) and this permission - * notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- - * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY - * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN - * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- - * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- - * MANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder shall - * not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization of - * the copyright holder. - * - * Author: Zephaniah E. Hull (warp@aehallh.com) - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "evdev.h" - -#include <X11/keysym.h> -#include <X11/XF86keysym.h> -#include <X11/extensions/XIproto.h> - -#include <linux/input.h> - -#include <misc.h> -#include <xf86.h> -#include <xf86str.h> -#include <xf86_OSproc.h> -#include <xf86Xinput.h> -#include <exevents.h> -#include <mipointer.h> - -#include <xf86Module.h> - -static char *button_names[] = { - "MISC_0", - "MISC_1", - "MISC_2", - "MISC_3", - "MISC_4", - "MISC_5", - "MISC_6", - "MISC_7", - "MISC_8", - "MISC_9", - "MISC_10", - "MISC_11", - "MISC_12", - "MISC_13", - "MISC_14", - "MISC_15", - "MOUSE_LEFT", - "MOUSE_RIGHT", - "MOUSE_MIDDLE", - "MOUSE_SIDE", - "MOUSE_EXTRA", - "MOUSE_FORWARD", - "MOUSE_BACK", - "MOUSE_TASK", - "MOUSE_8", - "MOUSE_9", - "MOUSE_10", - "MOUSE_12", - "MOUSE_13", - "MOUSE_14", - "MOUSE_15", - "JOY_TRIGGER", - "JOY_THUMB", - "JOY_THUMB2", - "JOY_TOP", - "JOY_TOP2", - "JOY_PINKIE", - "JOY_BASE", - "JOY_BASE2", - "JOY_BASE3", - "JOY_BASE4", - "JOY_BASE5", - "JOY_BASE6", - "JOY_12", - "JOY_13", - "JOY_14", - "JOY_DEAD", - "GAME_A", - "GAME_B", - "GAME_C", - "GAME_X", - "GAME_Y", - "GAME_Z", - "GAME_TL", - "GAME_TR", - "GAME_TL2", - "GAME_TR2", - "GAME_SELECT", - "GAME_START", - "GAME_MODE", - "GAME_THUMBL", - "GAME_THUMBR", - "GAME_15", - "DIGI_TOOL_PEN", - "DIGI_TOOL_RUBBER", - "DIGI_TOOL_BRUSH", - "DIGI_TOOL_PENCIL", - "DIGI_TOOL_AIRBRUSH", - "DIGI_TOOL_FINGER", - "DIGI_TOOL_MOUSE", - "DIGI_TOOL_LENS", - "DIGI_8", - "DIGI_9", - "DIGI_TOUCH", - "DIGI_STYLUS", - "DIGI_STYLUS2", - "DIGI_TOOL_DOUBLETAP", - "DIGI_TOOL_TRIPLETAP", - "DIGI_15", - "WHEEL_GEAR_UP", - "WHEEL_GEAR_DOWN", - "WHEEL_2", - "WHEEL_3", - "WHEEL_4", - "WHEEL_5", - "WHEEL_6", - "WHEEL_7", - "WHEEL_8", - "WHEEL_9", - "WHEEL_10", - "WHEEL_11", - "WHEEL_12", - "WHEEL_13", - "WHEEL_14", - "WHEEL_15", - NULL -}; - -void -EvdevBtnPostFakeClicks(InputInfoRec *pInfo, int button, int count) -{ - int i; - - for (i = 0; i < count; i++) { - xf86PostButtonEvent(pInfo->dev, 0, button, 1, 0, 0); - xf86PostButtonEvent(pInfo->dev, 0, button, 0, 0, 0); - } -} - -static void -EvdevMapButton (InputInfoRec *pInfo, int value, int mode, void *map_data) -{ - long button = (long) map_data; - - xf86PostButtonEvent (pInfo->dev, 0, button, value, 0, 0); -} - -Bool -EvdevParseMapToButton (InputInfoRec *pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func) -{ - evdevDeviceRec *pEvdev = pInfo->private; - evdevStateRec *state = &pEvdev->state; - evdevBtnRec *btn = state->btn; - int button; - - errno = 0; - button = strtol (option->str, NULL, 0); - if (errno) - button = EvdevBtnFind (pInfo, option->str); - if ((button < 0) || (button > BTN_MAX)) { - xf86Msg (X_ERROR, "%s: %s: Button %d out of range.\n", pInfo->name, name, button); - return 0; - } - - if (btn->b_flags[button] & EV_BTN_B_PRESENT) { - xf86Msg (X_ERROR, "%s: %s: Button %d already claimed.\n", pInfo->name, name, button); - return 0; - } - - btn->b_flags[button] = EV_BTN_B_PRESENT; - - *map_data = (void *) button; - *map_func = EvdevMapButton; - - return 1; -} - -typedef struct { - int button_plus; - int button_minus; - int step; - int count; -} MapButtons_t; - -static void -EvdevMapButtons (InputInfoRec *pInfo, int value, int mode, void *map_data) -{ - MapButtons_t *map = map_data; - int i; - - if (!map) - return; - - map->count += value; - i = map->count / map->step; - if (i) { - map->count -= i * map->step; - if (i > 0) - EvdevBtnPostFakeClicks (pInfo, map->button_plus, i); - else - EvdevBtnPostFakeClicks (pInfo, map->button_minus, -i); - } -} - -Bool -EvdevParseMapToButtons (InputInfoRec *pInfo, - const char *name, - evdev_option_token_t *option, - void **map_data, evdev_map_func_f *map_func) -{ - evdevDeviceRec *pEvdev = pInfo->private; - evdevStateRec *state = &pEvdev->state; - evdevBtnRec *btn = state->btn; - int btn_plus, btn_minus; - MapButtons_t *map; - - errno = 0; - btn_plus = strtol (option->str, NULL, 0); - if (errno) - btn_plus = EvdevBtnFind (pInfo, option->str); - if ((btn_plus < 0) || (btn_plus > BTN_MAX)) { - xf86Msg (X_ERROR, "%s: %s: Button %d out of range.\n", pInfo->name, name, btn_plus); - return 0; - } - - if (btn->b_flags[btn_plus] & EV_BTN_B_PRESENT) { - xf86Msg (X_ERROR, "%s: %s: Button %d already claimed.\n", pInfo->name, name, btn_plus); - return 0; - } - - option = option->next; - if (!option) { - xf86Msg (X_ERROR, "%s: %s: No button minus.\n", pInfo->name, name); - return 0; - } - - errno = 0; - btn_minus = strtol (option->str, NULL, 0); - if (errno) - btn_minus = EvdevBtnFind (pInfo, option->str); - if ((btn_minus < 0) || (btn_minus > BTN_MAX)) { - xf86Msg (X_ERROR, "%s: %s: Button %d out of range.\n", pInfo->name, name, btn_minus); - return 0; - } - - if (btn->b_flags[btn_minus] & EV_BTN_B_PRESENT) { - xf86Msg (X_ERROR, "%s: %s: Button %d already claimed.\n", pInfo->name, name, btn_minus); - return 0; - } - errno = 0; - - btn->b_flags[btn_plus] = EV_BTN_B_PRESENT; - btn->b_flags[btn_minus] = EV_BTN_B_PRESENT; - - map = calloc(1, sizeof (MapButtons_t)); - map->button_plus = btn_plus; - map->button_minus = btn_minus; - map->step = 1; - - *map_data = (void *) map; - *map_func = EvdevMapButtons; - - return 1; -} - -int -EvdevBtnInit (DeviceIntRec *device) -{ - InputInfoRec *pInfo = device->public.devicePrivate; - evdevDeviceRec *pEvdev = pInfo->private; - CARD8 *map; - int i; - - if (!pEvdev->state.btn) - return Success; - - map = Xcalloc (sizeof (CARD8) * (pEvdev->state.btn->buttons + 1)); - - for (i = 0; i <= pEvdev->state.btn->buttons; i++) - map[i] = i; - - xf86Msg(X_CONFIG, "%s: Registering %d buttons.\n", pInfo->name, - pEvdev->state.btn->buttons); - if (!InitButtonClassDeviceStruct (device, pEvdev->state.btn->buttons, map)) { - pEvdev->state.btn->buttons = 0; - - return !Success; - } - - Xfree (map); - - return Success; -} - -int -EvdevBtnOn (DeviceIntRec *device) -{ - return Success; -} - -int -EvdevBtnOff (DeviceIntRec *device) -{ - return Success; -} - - -int -EvdevBtnNew0(InputInfoRec *pInfo) -{ - evdevDeviceRec *pEvdev = pInfo->private; - evdevStateRec *state = &pEvdev->state; - - state->btn = Xcalloc (sizeof (evdevBtnRec)); - - return Success; -} - -int -EvdevBtnNew1(InputInfoRec *pInfo) -{ - evdevDeviceRec *pEvdev = pInfo->private; - evdevStateRec *state = &pEvdev->state; - evdevBtnRec *btn = state->btn; - char option[128], value[128]; - int i, b, j, target; - - if (!btn) - return !Success; - - for (i = 0; i < BTN_MAX; i++) { - b = i + BTN_MISC; - if (!test_bit (b, pEvdev->bits.key)) - continue; - - btn->real_buttons++; - - snprintf(option, sizeof(option), "Button%sMapTo", button_names[i]); - - if (b >= BTN_DIGI && b < BTN_WHEEL) - target = -1; - else if (b == BTN_RIGHT) - target = 3; - else if (b == BTN_MIDDLE) - target = 2; - else if (b >= BTN_MOUSE && b < BTN_JOYSTICK) - target = 1 + i - (BTN_MOUSE - BTN_MISC); - else if (b >= BTN_MISC && b < BTN_MOUSE) - target = 1 + i + (BTN_MOUSE - BTN_MISC); - else - target = 1 + i; - - if (btn->b_flags[target] & EV_BTN_B_PRESENT) { - for (j = target; j < BTN_MAX; j++) - if (!(btn->b_flags[j] & EV_BTN_B_PRESENT)) { - target = j; - break; - } - } - - if (target > 0) - snprintf (value, sizeof (value), "Button %d", target); - else - snprintf (value, sizeof (value), "null"); - - EvdevParseMapOption (pInfo, option, value, &btn->b_map_data[i], &btn->b_map[i]); - } - - if (state->btn->real_buttons) - xf86Msg(X_INFO, "%s: Found %d mouse buttons\n", pInfo->name, state->btn->real_buttons); - - for (i = 0; i < BTN_MAX; i++) - if (btn->b_flags[i] & EV_BTN_B_PRESENT) - btn->buttons = i + 1; - - if (state->btn->buttons) - xf86Msg(X_INFO, "%s: Configured %d mouse buttons.\n", pInfo->name, state->btn->buttons); - else { - Xfree (state->btn); - state->btn = NULL; - return !Success; - } - - pInfo->flags |= XI86_SEND_DRAG_EVENTS | XI86_CONFIGURED; - /* - * FIXME: Mouse may not be accurate. - * Check buttons to see if we're actually a joystick or something. - */ - pInfo->type_name = XI_MOUSE; - - return Success; -} - -void -EvdevBtnProcess (InputInfoRec *pInfo, struct input_event *ev) -{ - evdevDeviceRec *pEvdev = pInfo->private; - evdevStateRec *state = &pEvdev->state; - int button; - - if (!state->btn) - return; - - button = ev->code; - - button -= BTN_MISC; - - if (state->btn->callback[button]) - state->btn->callback[button](pInfo, button, ev->value); - - if (state->btn->b_map[button]) - state->btn->b_map[button](pInfo, ev->value, -1, state->btn->b_map_data[button]); -} - -int -EvdevBtnFind (InputInfoRec *pInfo, const char *button) -{ - int i; - - for (i = 0; button_names[i]; i++) - if (!strcasecmp(button, button_names[i])) - return i + 1; - - return -1; -} - -int -EvdevBtnExists (InputInfoRec *pInfo, int button) -{ - evdevDeviceRec *pEvdev = pInfo->private; - - xf86Msg(X_INFO, "%s: Checking button %s (%d)\n", pInfo->name, button_names[button], button); - - button += BTN_MISC; - - xf86Msg(X_INFO, "%s: Checking bit %d\n", pInfo->name, button); - return test_bit(button, pEvdev->bits.key); -} diff --git a/src/evdev_key.c b/src/evdev_key.c deleted file mode 100644 index dcbe48e..0000000 --- a/src/evdev_key.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Copyright © 2006-2007 Zephaniah E. Hull - * Copyright © 2004 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Soft- - * ware"), to deal in the Software without restriction, including without - * limitation the rights to use, copy, modify, merge, publish, distribute, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, provided that the above copyright - * notice(s) and this permission notice appear in all copies of the Soft- - * ware and that both the above copyright notice(s) and this permission - * notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- - * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY - * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN - * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- - * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- - * MANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder shall - * not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization of - * the copyright holder. - * - * Authors: - * Zephaniah E. Hull (warp@aehallh.com), - * Kristian Høgsberg (krh@redhat.com) - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "evdev.h" - -#include <X11/keysym.h> -#include <X11/XF86keysym.h> -#include <X11/extensions/XIproto.h> - -#include <linux/input.h> - -#include <misc.h> -#include <xf86.h> -#include <xf86str.h> -#include <xf86_OSproc.h> -#include <xf86Xinput.h> -#include <exevents.h> -#include <mipointer.h> - -#include <xf86Module.h> - -#include <X11/extensions/XKB.h> -#include <X11/extensions/XKBstr.h> -#include <X11/extensions/XKBsrv.h> - - -#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0]))) - -#define MIN_KEYCODE 8 -#define GLYPHS_PER_KEY 2 -#define AltMask Mod1Mask -#define NumLockMask Mod2Mask -#define AltLangMask Mod3Mask -#define KanaMask Mod4Mask -#define ScrollLockMask Mod5Mask - -#define CAPSFLAG 1 -#define NUMFLAG 2 -#define SCROLLFLAG 4 -#define MODEFLAG 8 -#define COMPOSEFLAG 16 - -/* Exported by xorg-server, xkb/xkbAccessX.c */ -extern int XkbDfltRepeatDelay; -extern int XkbDfltRepeatInterval; - -/* FIXME: this map works with evdev keyboards, but all the xkb maps - * probably don't. The easiest is to remap the event keycodes. */ - -static KeySym map[] = { - /* 0x00 */ NoSymbol, NoSymbol, - /* 0x01 */ XK_Escape, NoSymbol, - /* 0x02 */ XK_1, XK_exclam, - /* 0x03 */ XK_2, XK_at, - /* 0x04 */ XK_3, XK_numbersign, - /* 0x05 */ XK_4, XK_dollar, - /* 0x06 */ XK_5, XK_percent, - /* 0x07 */ XK_6, XK_asciicircum, - /* 0x08 */ XK_7, XK_ampersand, - /* 0x09 */ XK_8, XK_asterisk, - /* 0x0a */ XK_9, XK_parenleft, - /* 0x0b */ XK_0, XK_parenright, - /* 0x0c */ XK_minus, XK_underscore, - /* 0x0d */ XK_equal, XK_plus, - /* 0x0e */ XK_BackSpace, NoSymbol, - /* 0x0f */ XK_Tab, XK_ISO_Left_Tab, - /* 0x10 */ XK_Q, NoSymbol, - /* 0x11 */ XK_W, NoSymbol, - /* 0x12 */ XK_E, NoSymbol, - /* 0x13 */ XK_R, NoSymbol, - /* 0x14 */ XK_T, NoSymbol, - /* 0x15 */ XK_Y, NoSymbol, - /* 0x16 */ XK_U, NoSymbol, - /* 0x17 */ XK_I, NoSymbol, - /* 0x18 */ XK_O, NoSymbol, - /* 0x19 */ XK_P, NoSymbol, - /* 0x1a */ XK_bracketleft, XK_braceleft, - /* 0x1b */ XK_bracketright,XK_braceright, - /* 0x1c */ XK_Return, NoSymbol, - /* 0x1d */ XK_Control_L, NoSymbol, - /* 0x1e */ XK_A, NoSymbol, - /* 0x1f */ XK_S, NoSymbol, - /* 0x20 */ XK_D, NoSymbol, - /* 0x21 */ XK_F, NoSymbol, - /* 0x22 */ XK_G, NoSymbol, - /* 0x23 */ XK_H, NoSymbol, - /* 0x24 */ XK_J, NoSymbol, - /* 0x25 */ XK_K, NoSymbol, - /* 0x26 */ XK_L, NoSymbol, - /* 0x27 */ XK_semicolon, XK_colon, - /* 0x28 */ XK_quoteright, XK_quotedbl, - /* 0x29 */ XK_quoteleft, XK_asciitilde, - /* 0x2a */ XK_Shift_L, NoSymbol, - /* 0x2b */ XK_backslash, XK_bar, - /* 0x2c */ XK_Z, NoSymbol, - /* 0x2d */ XK_X, NoSymbol, - /* 0x2e */ XK_C, NoSymbol, - /* 0x2f */ XK_V, NoSymbol, - /* 0x30 */ XK_B, NoSymbol, - /* 0x31 */ XK_N, NoSymbol, - /* 0x32 */ XK_M, NoSymbol, - /* 0x33 */ XK_comma, XK_less, - /* 0x34 */ XK_period, XK_greater, - /* 0x35 */ XK_slash, XK_question, - /* 0x36 */ XK_Shift_R, NoSymbol, - /* 0x37 */ XK_KP_Multiply, NoSymbol, - /* 0x38 */ XK_Alt_L, XK_Meta_L, - /* 0x39 */ XK_space, NoSymbol, - /* 0x3a */ XK_Caps_Lock, NoSymbol, - /* 0x3b */ XK_F1, NoSymbol, - /* 0x3c */ XK_F2, NoSymbol, - /* 0x3d */ XK_F3, NoSymbol, - /* 0x3e */ XK_F4, NoSymbol, - /* 0x3f */ XK_F5, NoSymbol, - /* 0x40 */ XK_F6, NoSymbol, - /* 0x41 */ XK_F7, NoSymbol, - /* 0x42 */ XK_F8, NoSymbol, - /* 0x43 */ XK_F9, NoSymbol, - /* 0x44 */ XK_F10, NoSymbol, - /* 0x45 */ XK_Num_Lock, NoSymbol, - /* 0x46 */ XK_Scroll_Lock, NoSymbol, - /* These KP keys should have the KP_7 keysyms in the numlock - * modifer... ? */ - /* 0x47 */ XK_KP_Home, XK_KP_7, - /* 0x48 */ XK_KP_Up, XK_KP_8, - /* 0x49 */ XK_KP_Prior, XK_KP_9, - /* 0x4a */ XK_KP_Subtract, NoSymbol, - /* 0x4b */ XK_KP_Left, XK_KP_4, - /* 0x4c */ XK_KP_Begin, XK_KP_5, - /* 0x4d */ XK_KP_Right, XK_KP_6, - /* 0x4e */ XK_KP_Add, NoSymbol, - /* 0x4f */ XK_KP_End, XK_KP_1, - /* 0x50 */ XK_KP_Down, XK_KP_2, - /* 0x51 */ XK_KP_Next, XK_KP_3, - /* 0x52 */ XK_KP_Insert, XK_KP_0, - /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, - /* 0x54 */ NoSymbol, NoSymbol, - /* 0x55 */ XK_F13, NoSymbol, - /* 0x56 */ XK_less, XK_greater, - /* 0x57 */ XK_F11, NoSymbol, - /* 0x58 */ XK_F12, NoSymbol, - /* 0x59 */ XK_F14, NoSymbol, - /* 0x5a */ XK_F15, NoSymbol, - /* 0x5b */ XK_F16, NoSymbol, - /* 0x5c */ XK_F17, NoSymbol, - /* 0x5d */ XK_F18, NoSymbol, - /* 0x5e */ XK_F19, NoSymbol, - /* 0x5f */ XK_F20, NoSymbol, - /* 0x60 */ XK_KP_Enter, NoSymbol, - /* 0x61 */ XK_Control_R, NoSymbol, - /* 0x62 */ XK_KP_Divide, NoSymbol, - /* 0x63 */ XK_Print, XK_Sys_Req, - /* 0x64 */ XK_Alt_R, XK_Meta_R, - /* 0x65 */ NoSymbol, NoSymbol, /* KEY_LINEFEED */ - /* 0x66 */ XK_Home, NoSymbol, - /* 0x67 */ XK_Up, NoSymbol, - /* 0x68 */ XK_Prior, NoSymbol, - /* 0x69 */ XK_Left, NoSymbol, - /* 0x6a */ XK_Right, NoSymbol, - /* 0x6b */ XK_End, NoSymbol, - /* 0x6c */ XK_Down, NoSymbol, - /* 0x6d */ XK_Next, NoSymbol, - /* 0x6e */ XK_Insert, NoSymbol, - /* 0x6f */ XK_Delete, NoSymbol, - /* 0x70 */ NoSymbol, NoSymbol, /* KEY_MACRO */ - /* 0x71 */ NoSymbol, NoSymbol, - /* 0x72 */ NoSymbol, NoSymbol, - /* 0x73 */ NoSymbol, NoSymbol, - /* 0x74 */ NoSymbol, NoSymbol, - /* 0x75 */ XK_KP_Equal, NoSymbol, - /* 0x76 */ NoSymbol, NoSymbol, - /* 0x77 */ NoSymbol, NoSymbol, - /* 0x78 */ XK_F21, NoSymbol, - /* 0x79 */ XK_F22, NoSymbol, - /* 0x7a */ XK_F23, NoSymbol, - /* 0x7b */ XK_F24, NoSymbol, - /* 0x7c */ XK_KP_Separator, NoSymbol, - /* 0x7d */ XK_Meta_L, NoSymbol, - /* 0x7e */ XK_Meta_R, NoSymbol, - /* 0x7f */ XK_Multi_key, NoSymbol, - /* 0x80 */ NoSymbol, NoSymbol, - /* 0x81 */ NoSymbol, NoSymbol, - /* 0x82 */ NoSymbol, NoSymbol, - /* 0x83 */ NoSymbol, NoSymbol, - /* 0x84 */ NoSymbol, NoSymbol, - /* 0x85 */ NoSymbol, NoSymbol, - /* 0x86 */ NoSymbol, NoSymbol, - /* 0x87 */ NoSymbol, NoSymbol, - /* 0x88 */ NoSymbol, NoSymbol, - /* 0x89 */ NoSymbol, NoSymbol, - /* 0x8a */ NoSymbol, NoSymbol, - /* 0x8b */ NoSymbol, NoSymbol, - /* 0x8c */ NoSymbol, NoSymbol, - /* 0x8d */ NoSymbol, NoSymbol, - /* 0x8e */ NoSymbol, NoSymbol, - /* 0x8f */ NoSymbol, NoSymbol, - /* 0x90 */ NoSymbol, NoSymbol, - /* 0x91 */ NoSymbol, NoSymbol, - /* 0x92 */ NoSymbol, NoSymbol, - /* 0x93 */ NoSymbol, NoSymbol, - /* 0x94 */ NoSymbol, NoSymbol, - /* 0x95 */ NoSymbol, NoSymbol, - /* 0x96 */ NoSymbol, NoSymbol, - /* 0x97 */ NoSymbol, NoSymbol, - /* 0x98 */ NoSymbol, NoSymbol, - /* 0x99 */ NoSymbol, NoSymbol, - /* 0x9a */ NoSymbol, NoSymbol, - /* 0x9b */ NoSymbol, NoSymbol, - /* 0x9c */ NoSymbol, NoSymbol, - /* 0x9d */ NoSymbol, NoSymbol, - /* 0x9e */ NoSymbol, NoSymbol, - /* 0x9f */ NoSymbol, NoSymbol, - /* 0xa0 */ NoSymbol, NoSymbol, - /* 0xa1 */ NoSymbol, NoSymbol, - /* 0xa2 */ NoSymbol, NoSymbol, - /* 0xa3 */ NoSymbol, NoSymbol, - /* 0xa4 */ NoSymbol, NoSymbol, - /* 0xa5 */ NoSymbol, NoSymbol, - /* 0xa6 */ NoSymbol, NoSymbol, - /* 0xa7 */ NoSymbol, NoSymbol, - /* 0xa8 */ NoSymbol, NoSymbol, - /* 0xa9 */ NoSymbol, NoSymbol, - /* 0xaa */ NoSymbol, NoSymbol, - /* 0xab */ NoSymbol, NoSymbol, - /* 0xac */ NoSymbol, NoSymbol, - /* 0xad */ NoSymbol, NoSymbol, - /* 0xae */ NoSymbol, NoSymbol, - /* 0xaf */ NoSymbol, NoSymbol, - /* 0xb0 */ NoSymbol, NoSymbol, - /* 0xb1 */ NoSymbol, NoSymbol, - /* 0xb2 */ NoSymbol, NoSymbol, - /* 0xb3 */ NoSymbol, NoSymbol, - /* 0xb4 */ NoSymbol, NoSymbol, - /* 0xb5 */ NoSymbol, NoSymbol, - /* 0xb6 */ NoSymbol, NoSymbol, - /* 0xb7 */ NoSymbol, NoSymbol, - /* 0xb8 */ NoSymbol, NoSymbol, - /* 0xb9 */ NoSymbol, NoSymbol, - /* 0xba */ NoSymbol, NoSymbol, - /* 0xbb */ NoSymbol, NoSymbol, - /* 0xbc */ NoSymbol, NoSymbol, - /* 0xbd */ NoSymbol, NoSymbol, - /* 0xbe */ NoSymbol, NoSymbol, - /* 0xbf */ NoSymbol, NoSymbol, - /* 0xc0 */ NoSymbol, NoSymbol, - /* 0xc1 */ NoSymbol, NoSymbol, - /* 0xc2 */ NoSymbol, NoSymbol, - /* 0xc3 */ NoSymbol, NoSymbol, - /* 0xc4 */ NoSymbol, NoSymbol, - /* 0xc5 */ NoSymbol, NoSymbol, - /* 0xc6 */ NoSymbol, NoSymbol, - /* 0xc7 */ NoSymbol, NoSymbol, - /* 0xc8 */ NoSymbol, NoSymbol, - /* 0xc9 */ NoSymbol, NoSymbol, - /* 0xca */ NoSymbol, NoSymbol, - /* 0xcb */ NoSymbol, NoSymbol, - /* 0xcc */ NoSymbol, NoSymbol, - /* 0xcd */ NoSymbol, NoSymbol, - /* 0xce */ NoSymbol, NoSymbol, - /* 0xcf */ NoSymbol, NoSymbol, - /* 0xd0 */ NoSymbol, NoSymbol, - /* 0xd1 */ NoSymbol, NoSymbol, - /* 0xd2 */ NoSymbol, NoSymbol, - /* 0xd3 */ NoSymbol, NoSymbol, - /* 0xd4 */ NoSymbol, NoSymbol, - /* 0xd5 */ NoSymbol, NoSymbol, - /* 0xd6 */ NoSymbol, NoSymbol, - /* 0xd7 */ NoSymbol, NoSymbol, - /* 0xd8 */ NoSymbol, NoSymbol, - /* 0xd9 */ NoSymbol, NoSymbol, - /* 0xda */ NoSymbol, NoSymbol, - /* 0xdb */ NoSymbol, NoSymbol, - /* 0xdc */ NoSymbol, NoSymbol, - /* 0xdd */ NoSymbol, NoSymbol, - /* 0xde */ NoSymbol, NoSymbol, - /* 0xdf */ NoSymbol, NoSymbol, - /* 0xe0 */ NoSymbol, NoSymbol, - /* 0xe1 */ NoSymbol, NoSymbol, - /* 0xe2 */ NoSymbol, NoSymbol, - /* 0xe3 */ NoSymbol, NoSymbol, - /* 0xe4 */ NoSymbol, NoSymbol, - /* 0xe5 */ NoSymbol, NoSymbol, - /* 0xe6 */ NoSymbol, NoSymbol, - /* 0xe7 */ NoSymbol, NoSymbol, - /* 0xe8 */ NoSymbol, NoSymbol, - /* 0xe9 */ NoSymbol, NoSymbol, - /* 0xea */ NoSymbol, NoSymbol, - /* 0xeb */ NoSymbol, NoSymbol, - /* 0xec */ NoSymbol, NoSymbol, - /* 0xed */ NoSymbol, NoSymbol, - /* 0xee */ NoSymbol, NoSymbol, - /* 0xef */ NoSymbol, NoSymbol, - /* 0xf0 */ NoSymbol, NoSymbol, - /* 0xf1 */ NoSymbol, NoSymbol, - /* 0xf2 */ NoSymbol, NoSymbol, - /* 0xf3 */ NoSymbol, NoSymbol, - /* 0xf4 */ NoSymbol, NoSymbol, - /* 0xf5 */ NoSymbol, NoSymbol, - /* 0xf6 */ NoSymbol, NoSymbol, - /* 0xf7 */ NoSymbol, NoSymbol, -}; - -static void -EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl) -{ - static struct { int xbit, code; } bits[] = { - { CAPSFLAG, LED_CAPSL }, - { NUMFLAG, LED_NUML }, - { SCROLLFLAG, LED_SCROLLL }, - { MODEFLAG, LED_KANA }, - { COMPOSEFLAG, LED_COMPOSE } - }; - - InputInfoPtr pInfo; - struct input_event ev[ArrayLength(bits)]; - int i; - - pInfo = device->public.devicePrivate; - for (i = 0; i < ArrayLength(bits); i++) { - ev[i].type = EV_LED; - ev[i].code = bits[i].code; - ev[i].value = (ctrl->leds & bits[i].xbit) > 0; - } - write(pInfo->fd, ev, sizeof(ev)); -} - -int -EvdevKeyInit (DeviceIntPtr device) -{ - InputInfoPtr pInfo = device->public.devicePrivate; - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - KeySymsRec keySyms; - CARD8 modMap[MAP_LENGTH]; - KeySym sym; - int i, j; - - static struct { KeySym keysym; CARD8 mask; } modifiers[] = { - { XK_Shift_L, ShiftMask }, - { XK_Shift_R, ShiftMask }, - { XK_Control_L, ControlMask }, - { XK_Control_R, ControlMask }, - { XK_Caps_Lock, LockMask }, - { XK_Alt_L, AltMask }, - { XK_Alt_R, AltMask }, - { XK_Num_Lock, NumLockMask }, - { XK_Scroll_Lock, ScrollLockMask }, - { XK_Mode_switch, AltLangMask } - }; - - /* TODO: - * Ctrl-Alt-Backspace and other Ctrl-Alt-stuff should work - * XKB, let's try without the #ifdef nightmare - * Get keyboard repeat under control (right now caps lock repeats!) - */ - - pInfo = device->public.devicePrivate; - - /* Compute the modifier map */ - memset(modMap, 0, sizeof modMap); - - for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) { - sym = map[i * GLYPHS_PER_KEY]; - for (j = 0; j < ArrayLength(modifiers); j++) { - if (modifiers[j].keysym == sym) - modMap[i + MIN_KEYCODE] = modifiers[j].mask; - } - } - - keySyms.map = map; - keySyms.mapWidth = GLYPHS_PER_KEY; - keySyms.minKeyCode = MIN_KEYCODE; - keySyms.maxKeyCode = MIN_KEYCODE + ArrayLength(map) / GLYPHS_PER_KEY - 1; - - - XkbSetRulesDflts (state->key->xkb_rules, state->key->xkb_model, - state->key->xkb_layout, state->key->xkb_variant, - state->key->xkb_options); - - XkbInitKeyboardDeviceStruct (device, &state->key->xkbnames, &keySyms, modMap, - NULL, EvdevKbdCtrl); - - - if (device->key && - device->key->xkbInfo && - device->key->xkbInfo->desc && - device->key->xkbInfo->desc->ctrls) - { - XkbControlsPtr ctrls = device->key->xkbInfo->desc->ctrls; - ctrls->repeat_delay = XkbDfltRepeatDelay; - ctrls->repeat_interval = XkbDfltRepeatInterval; - } - - - return Success; -} - -static void -SetXkbOption(InputInfoPtr pInfo, char *name, char *value, char **option) -{ - char *s; - - if ((s = xf86SetStrOption(pInfo->options, name, value))) { - if (!s[0]) { - xfree(s); - *option = NULL; - } else { - *option = s; - } - } -} - -int -EvdevKeyNew (InputInfoPtr pInfo) -{ - evdevDevicePtr pEvdev = pInfo->private; - evdevStatePtr state = &pEvdev->state; - int i, keys = 0; - - for (i = 0; i <= 0xF7; i++) - if (test_bit (i, pEvdev->bits.key)) { - keys = 1; - break; - } - - if (!keys) - return !Success; - - state->key = Xcalloc (sizeof (evdevKeyRec)); - - pInfo->type_name = XI_KEYBOARD; - - pInfo->flags |= XI86_KEYBOARD_CAPABLE | XI86_CONFIGURED; - - SetXkbOption (pInfo, "xkb_rules", NULL, &state->key->xkb_rules); - if (!state->key->xkb_rules) - SetXkbOption (pInfo, "XkbRules", __XKBDEFRULES__, - &state->key->xkb_rules); - SetXkbOption (pInfo, "xkb_model", NULL, &state->key->xkb_model); - if (!state->key->xkb_model) - SetXkbOption (pInfo, "XkbModel", "evdev", &state->key->xkb_model); - SetXkbOption (pInfo, "xkb_layout", NULL, &state->key->xkb_layout); - if (!state->key->xkb_layout) - SetXkbOption (pInfo, "XkbLayout", "us", &state->key->xkb_layout); - SetXkbOption (pInfo, "xkb_variant", NULL, &state->key->xkb_variant); - if (!state->key->xkb_variant) - SetXkbOption (pInfo, "XkbVariant", NULL, &state->key->xkb_variant); - SetXkbOption (pInfo, "xkb_options", NULL, &state->key->xkb_options); - if (!state->key->xkb_options) - SetXkbOption (pInfo, "XkbOptions", NULL, &state->key->xkb_options); - - return Success; -} - -int -EvdevKeyOn (DeviceIntPtr device) -{ - return Success; -} - -int -EvdevKeyOff (DeviceIntPtr device) -{ - unsigned int i; - KeyClassRec *keyc = device->key; - KeySym *map = keyc->curKeySyms.map; - - /* - * A bit of a hack, vaguely stolen from xf86-input-keyboard. - * - * Don't leave any keys in the down state if we are getting turned - * off, as they are likely to be released before we are turned back - * on. - * (For example, if the user switches VTs, or if we are unplugged.) - */ - for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map; - i < keyc->curKeySyms.maxKeyCode; - i++, map += keyc->curKeySyms.mapWidth) - if ((keyc->down[i >> 3] & (1 << (i & 7)))) - { - switch (*map) { - /* Don't release the lock keys */ - case XK_Caps_Lock: - case XK_Shift_Lock: - case XK_Num_Lock: - case XK_Scroll_Lock: - case XK_Kana_Lock: - break; - default: - xf86PostKeyboardEvent(device, i, 0); - } - } - return Success; -} - -void -EvdevKeyProcess (InputInfoPtr pInfo, struct input_event *ev) -{ - int keycode = ev->code + MIN_KEYCODE; - - /* filter repeat events for chording keys */ - if (ev->value == 2) { - DeviceIntPtr device = pInfo->dev; - KeyClassRec *keyc = device->key; - KbdFeedbackClassRec *kbdfeed = device->kbdfeed; - - /* See xkb/ddxCtrls.c: XkbDDXUsesSoftRepeat - Xorg-server will only generate soft autorepeats, when - inverval/delay are NOT set to the default values of 40/660. - - We let the kernel autorepeat events pass, when we hit the - default value and the key is not a modifier. */ - if (device->key && - device->key->xkbInfo && - device->key->xkbInfo->desc && - device->key->xkbInfo->desc->ctrls) - { - if ((device->key->xkbInfo->desc->ctrls->repeat_interval != 40) || - (device->key->xkbInfo->desc->ctrls->repeat_delay != 660)) - return; - } - - int num = keycode >> 3; - int bit = 1 << (keycode & 7); - - if (keyc->modifierMap[keycode] || - !(kbdfeed->ctrl.autoRepeats[num] & bit)) - return; - } - - xf86PostKeyboardEvent(pInfo->dev, keycode, ev->value); -} |