aboutsummaryrefslogtreecommitdiff
path: root/src/evdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evdev.c')
-rw-r--r--src/evdev.c781
1 files changed, 220 insertions, 561 deletions
diff --git a/src/evdev.c b/src/evdev.c
index aa1eb5d..ed15134 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1,4 +1,34 @@
/*
+ * Copyright © 2006 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)
+ */
+/*
* Copyright © 2004 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
@@ -31,99 +61,32 @@
#include <X11/XF86keysym.h>
#include <X11/extensions/XIproto.h>
+#include <string.h>
+
/* The libc wrapper just blows... linux/input.h must be included
* before xf86_ansic.h and xf86_libc.h so we avoid defining ioctl
* twice. */
+#include "evdev.h"
-#include <linux/input.h>
-
-#include <misc.h>
#include <xf86.h>
-#include <xf86str.h>
-#include <xf86_OSproc.h>
-#include <xf86_ansic.h>
-#include <xf86_libc.h>
-#include <xf86Xinput.h>
-#include <exevents.h>
-#include <mipointer.h>
#include <xf86Module.h>
-/* 2.4 compatibility */
-#ifndef EVIOCGRAB
-#define EVIOCGRAB _IOW('E', 0x90, int)
-#endif
-
-#ifndef BTN_TASK
-#define BTN_TASK 0x117
-#endif
-
-#ifndef EV_SYN
-#define EV_SYN EV_RST
-#endif
-/* end compat */
-
-#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
-
-typedef struct {
- int kernel24;
-} EvdevRec, *EvdevPtr;
-
-static int wheel_up_button = 4;
-static int wheel_down_button = 5;
-static int wheel_left_button = 6;
-static int wheel_right_button = 7;
-static void
-PostButtonClicks(InputInfoPtr pInfo, int button, int count)
-{
- int i;
+#include <xf86_OSproc.h>
- for (i = 0; i < count; i++) {
- xf86PostButtonEvent(pInfo->dev, 0, button, 1, 0, 0);
- xf86PostButtonEvent(pInfo->dev, 0, button, 0, 0, 0);
- }
-}
+/*
+ * FIXME: This should most definitely not be here.
+ * But I need it, even if it _is_ private.
+ */
-static void
-PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
-{
- /* 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);
-}
+void xf86ActivateDevice(InputInfoPtr pInfo);
static void
EvdevReadInput(InputInfoPtr pInfo)
{
struct input_event ev;
int len, value;
- int dx, dy;
-
- dx = 0;
- dy = 0;
while (xf86WaitForInput (pInfo->fd, 0) > 0) {
len = read(pInfo->fd, &ev, sizeof ev);
@@ -139,573 +102,269 @@ EvdevReadInput(InputInfoPtr pInfo)
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;
+ EvdevRelProcess (pInfo, &ev);
+ break;
case EV_ABS:
+ EvdevAbsProcess (pInfo, &ev);
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;
-
- default:
- PostKbdEvent(pInfo, &ev, value);
- }
- break;
+ if ((ev.code >= BTN_MISC) && (ev.code < KEY_OK))
+ EvdevBtnProcess (pInfo, &ev);
+ else
+ EvdevKeyProcess (pInfo, &ev);
+ break;
case EV_SYN:
+ if (ev.code == SYN_REPORT) {
+ EvdevRelSyn (pInfo);
+ EvdevAbsSyn (pInfo);
+ /* EvdevBtnSyn (pInfo); */
+ /* EvdevKeySyn (pInfo); */
+ }
break;
}
}
-
- if (dx != 0 || dy != 0)
- xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
}
-#define TestBit(bit, array) (array[(bit) / 8] & (1 << ((bit) % 8)))
-
static void
-EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
+EvdevSigioReadInput (int fd, void *data)
{
- /* 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,
- /* 0x6f */ NoSymbol, NoSymbol, /* KEY_MACRO */
- /* 0x70 */ NoSymbol, NoSymbol,
- /* 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,
-};
-
-static void
-EvdevKbdBell(int percent, DeviceIntPtr dev, pointer ctrl, int unused)
-{
- /* hat */
-}
-
-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
-EvdevAddKeyClass(DeviceIntPtr device)
-{
- InputInfoPtr pInfo;
- 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;
-
- if (!InitKeyClassDeviceStruct(device, &keySyms, modMap))
- return !Success;
-
- if (!InitFocusClassDeviceStruct(device))
- return !Success;
-
- if (!InitKbdFeedbackClassDeviceStruct(device, EvdevKbdBell, EvdevKbdCtrl))
- return !Success;
-
- pInfo->flags |= XI86_KEYBOARD_CAPABLE;
-
- return Success;
-}
-
-static int
-EvdevAddRelClass(DeviceIntPtr device)
-{
- InputInfoPtr pInfo;
-
- pInfo = device->public.devicePrivate;
-
- if (!InitValuatorClassDeviceStruct(device, 2,
- miPointerGetMotionEvents,
- miPointerGetMotionBufferSize(), 0))
- 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;
-
- return Success;
+ EvdevReadInput ((InputInfoPtr) data);
}
static int
-EvdevAddButtonClass(DeviceIntPtr device)
+EvdevProc(DeviceIntPtr device, int what)
{
- CARD8 map[32];
- InputInfoPtr pInfo;
- int i;
+ InputInfoPtr pInfo = device->public.devicePrivate;
+ evdevDevicePtr pEvdev = pInfo->private;
- pInfo = device->public.devicePrivate;
+ switch (what)
+ {
+ case DEVICE_INIT:
+ if (pEvdev->state.abs_axes)
+ EvdevAbsInit (device);
+ if (pEvdev->state.rel_axes)
+ EvdevRelInit (device);
+ if (pEvdev->state.buttons)
+ EvdevBtnInit (device);
+ if (pEvdev->state.keys)
+ EvdevKeyInit (device);
+ xf86Msg(X_INFO, "%s: Init\n", pInfo->name);
+ break;
- /* FIXME: count number of actual buttons */
+ case DEVICE_ON:
+ xf86Msg(X_INFO, "%s: On\n", pInfo->name);
+ if (device->public.on)
+ break;
- for (i = 0; i < ArrayLength(map); i++)
- map[i] = i;
+ if ((pInfo->fd = evdevGetFDForDevice (pEvdev)) == -1) {
+ xf86Msg(X_ERROR, "%s: cannot open input device.\n", pInfo->name);
- /* 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;
+ if (pEvdev->phys)
+ xfree(pEvdev->phys);
+ pEvdev->phys = NULL;
- if (!InitButtonClassDeviceStruct(device, ArrayLength(map), map))
- return !Success;
+ if (pEvdev->device)
+ xfree(pEvdev->device);
+ pEvdev->device = NULL;
- pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
+ return BadRequest;
+ }
- return Success;
-}
+ 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));
-static int
-EvdevInit(DeviceIntPtr device)
-{
- InputInfoPtr pInfo;
+ xf86FlushInput (pInfo->fd);
+ if (!xf86InstallSIGIOHandler (pInfo->fd, EvdevSigioReadInput, pInfo))
+ AddEnabledDevice (pInfo->fd);
- pInfo = device->public.devicePrivate;
+ device->public.on = TRUE;
- /* FIXME: This doesn't add buttons for keyboards with
- * scrollwheels. */
+ if (pEvdev->state.abs_axes)
+ EvdevAbsOn (device);
+ if (pEvdev->state.rel_axes)
+ EvdevRelOn (device);
+ if (pEvdev->state.buttons)
+ EvdevBtnOn (device);
+ if (pEvdev->state.keys)
+ EvdevKeyOn (device);
+ break;
- if (pInfo->flags & XI86_KEYBOARD_CAPABLE) {
- EvdevAddKeyClass(device);
- }
+ 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);
+
+ if (pEvdev->state.abs_axes)
+ EvdevAbsOff (device);
+ if (pEvdev->state.rel_axes)
+ EvdevRelOff (device);
+ if (pEvdev->state.buttons)
+ EvdevBtnOff (device);
+ if (pEvdev->state.keys)
+ EvdevKeyOff (device);
+ }
- if (pInfo->flags & XI86_POINTER_CAPABLE) {
- EvdevAddButtonClass(device);
- EvdevAddRelClass(device);
+ device->public.on = FALSE;
+ break;
}
return Success;
}
static int
-EvdevProc(DeviceIntPtr device, int what)
+EvdevSwitchMode (ClientPtr client, DeviceIntPtr device, int mode)
{
- InputInfoPtr pInfo;
- EvdevPtr pEvdev;
+ InputInfoPtr pInfo = device->public.devicePrivate;
+ evdevDevicePtr pEvdev = pInfo->private;
+ evdevStatePtr state = &pEvdev->state;
- pInfo = device->public.devicePrivate;
- pEvdev = pInfo->private;
-
- switch (what)
+ switch (mode)
{
- case DEVICE_INIT:
- return EvdevInit(device);
-
- 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;
+ case Absolute:
+ case Relative:
+ if (state->abs_axes)
+ state->mode = mode;
+ else
+ return !Success;
+ break;
+ case SendCoreEvents:
+ case DontSendCoreEvents:
+ xf86XInputSetSendCoreEvents (pInfo, (mode == SendCoreEvents));
+ break;
+ default:
+ return !Success;
}
return Success;
}
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)
+EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
{
- if (first == 0 && num == 2) {
- *x = v0;
- *y = v1;
- return TRUE;
- }
- else
- return FALSE;
-}
+ InputInfoPtr pInfo;
+ char name[512] = {0};
-static int
-EvdevProbe(InputInfoPtr pInfo)
-{
- char key_bitmask[(KEY_MAX + 7) / 8];
- char rel_bitmask[(REL_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 (!(pInfo = xf86AllocateInput(driver->drv, 0)))
+ return 0;
- 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;
- }
+ /* Initialise the InputInfoRec. */
+ strncat (name, driver->dev->identifier, sizeof(name));
+ strncat (name, "-", sizeof(name));
+ strncat (name, device->phys, sizeof(name));
+ pInfo->name = xstrdup(name);
+ pInfo->flags = 0;
+ pInfo->type_name = "UNKNOWN";
+ pInfo->device_control = EvdevProc;
+ pInfo->read_input = EvdevReadInput;
+ pInfo->switch_mode = EvdevSwitchMode;
+ pInfo->motion_history_proc = xf86GetMotionEvents;
+ pInfo->conf_idev = driver->dev;
- 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;
- }
+ pInfo->private = device;
- has_axes = FALSE;
- has_buttons = FALSE;
- has_keys = FALSE;
+ device->callback = EvdevProc;
+ device->pInfo = pInfo;
- if (TestBit(REL_X, rel_bitmask) && TestBit(REL_Y, rel_bitmask)) {
- xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name);
- has_axes = TRUE;
- }
-
+ xf86CollectInputOptions(pInfo, NULL, NULL);
+ xf86ProcessCommonOptions(pInfo, pInfo->options);
- if (TestBit(BTN_LEFT, key_bitmask)) {
- xf86Msg(X_INFO, "%s: Found mouse buttons\n", pInfo->name);
- has_buttons = TRUE;
+ if ((pInfo->fd = evdevGetFDForDevice (device)) == -1) {
+ xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
+ pInfo->private = NULL;
+ xf86DeleteInput (pInfo, 0);
+ return 0;
}
- for (i = 0; i < BTN_MISC; i++)
- if (TestBit(i, key_bitmask))
- break;
-
- if (i < BTN_MISC) {
- xf86Msg(X_INFO, "%s: Found keys\n", pInfo->name);
- has_keys = TRUE;
+ if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
+ xf86Msg(X_INFO, "%s: Unable to grab device (%s). Cowardly refusing to check use as keyboard.\n", pInfo->name, strerror(errno));
+ device->state.can_grab = 0;
+ } else {
+ device->state.can_grab = 1;
+ ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
}
- 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;
+ /* XXX: Note, the order of these is important. */
+ EvdevAbsNew (pInfo);
+ EvdevRelNew (pInfo);
+ EvdevBtnNew (pInfo);
+ if (device->state.can_grab)
+ EvdevKeyNew (pInfo);
+
+ close (pInfo->fd);
+ pInfo->fd = -1;
+
+ pInfo->flags |= XI86_OPEN_ON_INIT;
+ if (!(pInfo->flags & XI86_CONFIGURED)) {
+ xf86Msg(X_ERROR, "%s: Don't know how to use device.\n", pInfo->name);
+ pInfo->private = NULL;
+ xf86DeleteInput (pInfo, 0);
+ return 0;
}
- 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 (driver->configured) {
+ xf86ActivateDevice (pInfo);
- if ((pInfo->flags & XI86_CONFIGURED) == 0) {
- xf86Msg(X_WARNING, "%s: Don't know how to use device\n",
- pInfo->name);
- return 1;
+ pInfo->dev->inited = (device->callback(device->pInfo->dev, DEVICE_INIT) == Success);
+ EnableDevice (pInfo->dev);
}
- return 0;
+ return 1;
}
static InputInfoPtr
-EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+EvdevCorePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
{
- InputInfoPtr pInfo;
- MessageType deviceFrom = X_CONFIG;
- const char *device;
- EvdevPtr pEvdev;
+ evdevDriverPtr pEvdev;
- if (!(pInfo = xf86AllocateInput(drv, 0)))
- return NULL;
+ if (!(pEvdev = Xcalloc(sizeof(*pEvdev))))
+ 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->motion_history_proc = xf86GetMotionEvents;
- 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;
+ pEvdev->name = xf86CheckStrOption(dev->commonOptions, "Name", NULL);
+ pEvdev->phys = xf86CheckStrOption(dev->commonOptions, "Phys", NULL);
+ pEvdev->device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
+ xf86Msg(X_ERROR, "%s: name: %s, phys: %s, device: %s.\n", dev->identifier,
+ pEvdev->name, pEvdev->phys, pEvdev->device);
- xf86CollectInputOptions(pInfo, NULL, NULL);
- xf86ProcessCommonOptions(pInfo, pInfo->options);
+ pEvdev->callback = EvdevNew;
+
+ pEvdev->dev = dev;
+ pEvdev->drv = drv;
- device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
- if (!device) {
- xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name);
+ if (!pEvdev->name && !pEvdev->phys && !pEvdev->device) {
+ xf86Msg(X_ERROR, "%s: No device identifiers specified.\n", dev->identifier);
xfree(pEvdev);
- return pInfo;
+ 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);
+ if (!evdevStart (drv)) {
+ xf86Msg(X_ERROR, "%s: cannot start evdev brain.\n", dev->identifier);
xfree(pEvdev);
- return pInfo;
+ return NULL;
}
- if (EvdevProbe(pInfo))
- xfree(pEvdev);
+ evdevNewDriver (pEvdev);
+
+ if (pEvdev->devices && pEvdev->devices->pInfo)
+ return pEvdev->devices->pInfo;
- return pInfo;
+ return NULL;
}
_X_EXPORT InputDriverRec EVDEV = {
1,
"evdev",
NULL,
- EvdevPreInit,
+ EvdevCorePreInit,
NULL,
NULL,
0