2 * Copyright © 2004-2008 Red Hat, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of Red Hat
9 * not be used in advertising or publicity pertaining to distribution
10 * of the software without specific, written prior permission. Red
11 * Hat makes no representations about the suitability of this software
12 * for any purpose. It is provided "as is" without express or implied
15 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * Kristian Høgsberg (krh@redhat.com)
25 * Adam Jackson (ajax@redhat.com)
26 * Peter Hutterer (peter.hutterer@redhat.com)
27 * Oliver McFadden (oliver.mcfadden@nokia.com)
34 #include <X11/keysym.h>
42 #include <xf86Xinput.h>
44 #include <xorgVersion.h>
48 #ifdef _F_EVDEV_CONFINE_REGION_
49 #include <xorg/mipointrst.h>
51 #define MIPOINTER(dev) \
52 ((!IsMaster(dev) && !dev->master) ? \
53 (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
54 (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
56 #endif /* _F_EVDEV_CONFINE_REGION_ */
58 #ifdef HAVE_PROPERTIES
59 #include <X11/Xatom.h>
60 #include <evdev-properties.h>
61 #include <xserver-properties.h>
62 /* 1.6 has properties, but no labels */
63 #ifdef AXIS_LABEL_PROP
72 #include <inputstr.h> /* for MAX_DEVICES */
73 #define MAXDEVICES MAX_DEVICES
76 /* 2.4 compatibility */
78 #define EVIOCGRAB _IOW('E', 0x90, int)
82 #define BTN_TASK 0x117
90 #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
93 #define EVDEV_KEYBOARD_EVENTS (1 << 0)
94 #define EVDEV_BUTTON_EVENTS (1 << 1)
95 #define EVDEV_RELATIVE_EVENTS (1 << 2)
96 #define EVDEV_ABSOLUTE_EVENTS (1 << 3)
97 #define EVDEV_TOUCHPAD (1 << 4)
98 #define EVDEV_INITIALIZED (1 << 5) /* WheelInit etc. called already? */
99 #define EVDEV_TOUCHSCREEN (1 << 6)
100 #define EVDEV_CALIBRATED (1 << 7) /* run-time calibrated? */
101 #define EVDEV_TABLET (1 << 8) /* device looks like a tablet? */
102 #define EVDEV_UNIGNORE_ABSOLUTE (1 << 9) /* explicitly unignore abs axes */
103 #define EVDEV_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
104 #define EVDEV_RESOLUTION (1 << 12) /* device looks like a multi-touch screen? */
105 #ifdef _F_EVDEV_CONFINE_REGION_
106 #define EVDEV_CONFINE_REGION (1 << 13)
107 #endif /* _F_EVDEV_CONFINE_REGION_ */
109 #define MIN_KEYCODE 8
110 #define GLYPHS_PER_KEY 2
111 #define AltMask Mod1Mask
112 #define NumLockMask Mod2Mask
113 #define AltLangMask Mod3Mask
114 #define KanaMask Mod4Mask
115 #define ScrollLockMask Mod5Mask
121 #define COMPOSEFLAG 16
123 static const char *evdevDefaults[] = {
130 static int EvdevOn(DeviceIntPtr);
131 static int EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare);
132 static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
133 static void EvdevSwapAxes(EvdevPtr pEvdev);
134 static void EvdevSetResolution(InputInfoPtr pInfo, int num_resolution, int resolution[4]);
136 #ifdef HAVE_PROPERTIES
137 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
138 static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
139 static void EvdevInitProperty(DeviceIntPtr dev);
140 static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
141 XIPropertyValuePtr val, BOOL checkonly);
142 #ifdef _F_EVDEV_CONFINE_REGION_
143 Bool IsMaster(DeviceIntPtr dev);
144 DeviceIntPtr GetPairedDevice(DeviceIntPtr dev);
145 DeviceIntPtr GetMaster(DeviceIntPtr dev, int which);
146 DeviceIntPtr GetMasterPointerFromId(int deviceid);
147 static void EvdevHookPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, BoxPtr pHotBox, BoxPtr pTopLeftBox);
148 static void EvdevHookPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox);
149 static void EvdevSetCursorLimits(InputInfoPtr pInfo, int region[5], int isSet);
150 static void EvdevSetConfineRegion(InputInfoPtr pInfo, int num_item, int region[5]);
151 static Atom prop_confine_region = 0;
152 #endif /* _F_EVDEV_CONFINE_REGION_ */
153 static Atom prop_invert = 0;
154 static Atom prop_reopen = 0;
155 static Atom prop_calibration = 0;
156 static Atom prop_swap = 0;
157 static Atom prop_axis_label = 0;
158 static Atom prop_btn_label = 0;
161 /* All devices the evdev driver has allocated and knows about.
162 * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
163 * cannot be used by evdev, leaving us with a space of 2 at the end. */
164 static EvdevPtr evdev_devices[MAXDEVICES] = {NULL};
166 static size_t EvdevCountBits(unsigned long *array, size_t nlongs)
171 for (i = 0; i < nlongs; i++) {
172 unsigned long x = array[i];
184 EvdevGetMajorMinor(InputInfoPtr pInfo)
188 if (fstat(pInfo->fd, &st) == -1)
190 xf86Msg(X_ERROR, "%s: stat failed (%s). cannot check for duplicates.\n",
191 pInfo->name, strerror(errno));
199 * Return TRUE if one of the devices we know about has the same min/maj
203 EvdevIsDuplicate(InputInfoPtr pInfo)
205 EvdevPtr pEvdev = pInfo->private;
206 EvdevPtr* dev = evdev_devices;
212 if ((*dev) != pEvdev &&
214 (*dev)->min_maj == pEvdev->min_maj)
223 * Add to internal device list.
226 EvdevAddDevice(InputInfoPtr pInfo)
228 EvdevPtr pEvdev = pInfo->private;
229 EvdevPtr* dev = evdev_devices;
238 * Remove from internal device list.
241 EvdevRemoveDevice(InputInfoPtr pInfo)
243 EvdevPtr pEvdev = pInfo->private;
244 EvdevPtr *dev = evdev_devices;
252 memmove(dev, dev + 1,
253 sizeof(evdev_devices) - (count * sizeof(EvdevPtr)));
262 SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
266 if ((s = xf86SetStrOption(pInfo->options, name, NULL))) {
276 static int wheel_up_button = 4;
277 static int wheel_down_button = 5;
278 static int wheel_left_button = 6;
279 static int wheel_right_button = 7;
282 EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
284 int code = ev->code + MIN_KEYCODE;
285 static char warned[KEY_CNT];
286 EventQueuePtr pQueue;
287 EvdevPtr pEvdev = pInfo->private;
289 /* Filter all repeated events from device.
290 We'll do softrepeat in the server, but only since 1.6 */
292 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) <= 2
293 && (ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL ||
294 ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT ||
295 ev->code == KEY_LEFTALT || ev->code == KEY_RIGHTALT ||
296 ev->code == KEY_LEFTMETA || ev->code == KEY_RIGHTMETA ||
297 ev->code == KEY_CAPSLOCK || ev->code == KEY_NUMLOCK ||
298 ev->code == KEY_SCROLLLOCK) /* XXX windows keys? */
305 if (ev->code <= KEY_MAX && !warned[ev->code])
307 xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n",
308 pInfo->name, ev->code);
309 warned[ev->code] = 1;
312 /* The X server can't handle keycodes > 255. */
316 if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
318 xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name);
322 pQueue = &pEvdev->queue[pEvdev->num_queue];
323 pQueue->type = EV_QUEUE_KEY;
330 EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
332 EventQueuePtr pQueue;
333 EvdevPtr pEvdev = pInfo->private;
335 if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
337 xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name);
341 pQueue = &pEvdev->queue[pEvdev->num_queue];
342 pQueue->type = EV_QUEUE_BTN;
343 pQueue->key = button;
349 * Post button event right here, right now.
350 * Interface for MB emulation since these need to post immediately.
353 EvdevPostButtonEvent(InputInfoPtr pInfo, int button, int value)
355 xf86PostButtonEvent(pInfo->dev, 0, button, value, 0, 0);
359 EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
363 for (i = 0; i < count; i++) {
364 EvdevQueueButtonEvent(pInfo, button, 1);
365 EvdevQueueButtonEvent(pInfo, button, 0);
370 * Coming back from resume may leave us with a file descriptor that can be
371 * opened but fails on the first read (ENODEV).
372 * In this case, try to open the device until it becomes available or until
373 * the predefined count expires.
376 EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
378 InputInfoPtr pInfo = (InputInfoPtr)arg;
379 EvdevPtr pEvdev = pInfo->private;
382 pInfo->fd = open(pEvdev->device, O_RDWR | O_NONBLOCK, 0);
383 } while (pInfo->fd < 0 && errno == EINTR);
387 if (EvdevCacheCompare(pInfo, TRUE) == Success)
389 xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name,
390 pEvdev->reopen_attempts - pEvdev->reopen_left + 1);
394 xf86Msg(X_ERROR, "%s: Device has changed - disabling.\n",
396 xf86DisableDevice(pInfo->dev, FALSE);
399 pEvdev->min_maj = 0; /* don't hog the device */
401 pEvdev->reopen_left = 0;
405 pEvdev->reopen_left--;
407 if (!pEvdev->reopen_left)
409 xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n",
410 pInfo->name, pEvdev->reopen_attempts);
411 xf86DisableDevice(pInfo->dev, FALSE);
412 pEvdev->min_maj = 0; /* don't hog the device */
416 return 100; /* come back in 100 ms */
419 #define ABS_X_VALUE 0x1
420 #define ABS_Y_VALUE 0x2
421 #define ABS_VALUE 0x4
423 * Take the valuators and process them accordingly.
426 EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
430 EvdevPtr pEvdev = pInfo->private;
432 *num_v = *first_v = 0;
434 /* convert to relative motion for touchpads */
435 if (pEvdev->abs && (pEvdev->flags & EVDEV_TOUCHPAD)) {
436 if (pEvdev->tool) { /* meaning, touch is active */
437 if (pEvdev->old_vals[0] != -1)
438 pEvdev->delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0];
439 if (pEvdev->old_vals[1] != -1)
440 pEvdev->delta[REL_Y] = pEvdev->vals[1] - pEvdev->old_vals[1];
441 if (pEvdev->abs & ABS_X_VALUE)
442 pEvdev->old_vals[0] = pEvdev->vals[0];
443 if (pEvdev->abs & ABS_Y_VALUE)
444 pEvdev->old_vals[1] = pEvdev->vals[1];
446 pEvdev->old_vals[0] = pEvdev->old_vals[1] = -1;
453 int first = REL_CNT, last = 0;
456 if (pEvdev->swap_axes) {
457 tmp = pEvdev->delta[REL_X];
458 pEvdev->delta[REL_X] = pEvdev->delta[REL_Y];
459 pEvdev->delta[REL_Y] = tmp;
461 if (pEvdev->invert_x)
462 pEvdev->delta[REL_X] *= -1;
463 if (pEvdev->invert_y)
464 pEvdev->delta[REL_Y] *= -1;
466 for (i = 0; i < REL_CNT; i++)
468 int map = pEvdev->axis_map[i];
471 v[map] = pEvdev->delta[i];
479 *num_v = (last - first + 1);
483 * Some devices only generate valid abs coords when BTN_DIGI is
484 * pressed. On wacom tablets, this means that the pen is in
485 * proximity of the tablet. After the pen is removed, BTN_DIGI is
486 * released, and a (0, 0) absolute event is generated. Checking
487 * pEvdev->digi here, lets us ignore that event. pEvdev is
488 * initialized to 1 so devices that doesn't use this scheme still
491 else if (pEvdev->abs && pEvdev->tool) {
492 memcpy(v, pEvdev->vals, sizeof(int) * pEvdev->num_vals);
494 if (pEvdev->swap_axes) {
500 if (pEvdev->flags & EVDEV_CALIBRATED)
502 v[0] = xf86ScaleAxis(v[0],
503 pEvdev->absinfo[ABS_X].maximum,
504 pEvdev->absinfo[ABS_X].minimum,
505 pEvdev->calibration.max_x, pEvdev->calibration.min_x);
506 v[1] = xf86ScaleAxis(v[1],
507 pEvdev->absinfo[ABS_Y].maximum,
508 pEvdev->absinfo[ABS_Y].minimum,
509 pEvdev->calibration.max_y, pEvdev->calibration.min_y);
512 if (pEvdev->invert_x)
513 v[0] = (pEvdev->absinfo[ABS_X].maximum - v[0] +
514 pEvdev->absinfo[ABS_X].minimum);
515 if (pEvdev->invert_y)
516 v[1] = (pEvdev->absinfo[ABS_Y].maximum - v[1] +
517 pEvdev->absinfo[ABS_Y].minimum);
519 *num_v = pEvdev->num_vals;
525 * Take a button input event and process it accordingly.
528 EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
532 EvdevPtr pEvdev = pInfo->private;
534 button = EvdevUtilButtonEventToButtonNumber(pEvdev, ev->code);
536 /* Get the signed value, earlier kernels had this as unsigned */
539 /* Handle drag lock */
540 if (EvdevDragLockFilterEvent(pInfo, button, value))
543 if (EvdevWheelEmuFilterButton(pInfo, button, value))
546 if (EvdevMBEmuFilterEvent(pInfo, button, value))
550 EvdevQueueButtonEvent(pInfo, button, value);
552 EvdevQueueKbdEvent(pInfo, ev, value);
556 * Take the relative motion input event and process it accordingly.
559 EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
562 EvdevPtr pEvdev = pInfo->private;
564 /* Get the signed value, earlier kernels had this as unsigned */
572 EvdevQueueButtonClicks(pInfo, wheel_up_button, value);
574 EvdevQueueButtonClicks(pInfo, wheel_down_button, -value);
580 EvdevQueueButtonClicks(pInfo, wheel_right_button, value);
582 EvdevQueueButtonClicks(pInfo, wheel_left_button, -value);
585 /* We don't post wheel events as axis motion. */
587 /* Ignore EV_REL events if we never set up for them. */
588 if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS))
591 /* Handle mouse wheel emulation */
592 if (EvdevWheelEmuFilterMotion(pInfo, ev))
595 pEvdev->delta[ev->code] += value;
601 * Take the absolute motion input event and process it accordingly.
604 EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
607 EvdevPtr pEvdev = pInfo->private;
609 /* Get the signed value, earlier kernels had this as unsigned */
612 /* Ignore EV_ABS events if we never set up for them. */
613 if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
616 if (ev->code > ABS_MAX)
619 pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
620 if (ev->code == ABS_X)
621 pEvdev->abs |= ABS_X_VALUE;
622 else if (ev->code == ABS_Y)
623 pEvdev->abs |= ABS_Y_VALUE;
625 pEvdev->abs |= ABS_VALUE;
629 * Take the key press/release input event and process it accordingly.
632 EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
635 EvdevPtr pEvdev = pInfo->private;
637 /* Get the signed value, earlier kernels had this as unsigned */
640 /* don't repeat mouse buttons */
641 if (ev->code >= BTN_MOUSE && ev->code < KEY_OK)
647 case BTN_TOOL_RUBBER:
649 case BTN_TOOL_PENCIL:
650 case BTN_TOOL_AIRBRUSH:
651 case BTN_TOOL_FINGER:
654 pEvdev->tool = value ? ev->code : 0;
658 pEvdev->tool = value ? ev->code : 0;
659 if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)))
661 /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
664 /* Intentional fallthrough! */
667 EvdevProcessButtonEvent(pInfo, ev);
673 * Post the relative motion events.
676 EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
677 int v[MAX_VALUATORS])
679 EvdevPtr pEvdev = pInfo->private;
682 xf86PostMotionEventP(pInfo->dev, FALSE, *first_v, *num_v, v + *first_v);
687 * Post the absolute motion events.
690 EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
691 int v[MAX_VALUATORS])
693 EvdevPtr pEvdev = pInfo->private;
696 * Some devices only generate valid abs coords when BTN_DIGI is
697 * pressed. On wacom tablets, this means that the pen is in
698 * proximity of the tablet. After the pen is removed, BTN_DIGI is
699 * released, and a (0, 0) absolute event is generated. Checking
700 * pEvdev->digi here, lets us ignore that event. pEvdev is
701 * initialized to 1 so devices that doesn't use this scheme still
704 if (pEvdev->abs && pEvdev->tool)
705 xf86PostMotionEventP(pInfo->dev, TRUE, *first_v, *num_v, v);
709 * Post the queued key/button events.
711 static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
712 int v[MAX_VALUATORS])
715 EvdevPtr pEvdev = pInfo->private;
717 for (i = 0; i < pEvdev->num_queue; i++) {
718 switch (pEvdev->queue[i].type) {
720 xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].key,
721 pEvdev->queue[i].val);
724 /* FIXME: Add xf86PostButtonEventP to the X server so that we may
725 * pass the valuators on ButtonPress/Release events, too. Currently
726 * only MotionNotify events contain the pointer position. */
727 xf86PostButtonEvent(pInfo->dev, 0, pEvdev->queue[i].key,
728 pEvdev->queue[i].val, 0, 0);
735 * Take the synchronization input event and process it accordingly; the motion
736 * notify events are sent first, then any button/key press/release events.
739 EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
741 int num_v = 0, first_v = 0;
742 int v[MAX_VALUATORS];
743 EvdevPtr pEvdev = pInfo->private;
745 EvdevProcessValuators(pInfo, v, &num_v, &first_v);
747 EvdevPostRelativeMotionEvents(pInfo, &num_v, &first_v, v);
748 EvdevPostAbsoluteMotionEvents(pInfo, &num_v, &first_v, v);
749 EvdevPostQueuedEvents(pInfo, &num_v, &first_v, v);
751 memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
752 memset(pEvdev->queue, 0, sizeof(pEvdev->queue));
753 pEvdev->num_queue = 0;
759 * Process the events from the device; nothing is actually posted to the server
760 * until an EV_SYN event is received.
763 EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
767 EvdevProcessRelativeMotionEvent(pInfo, ev);
770 EvdevProcessAbsoluteMotionEvent(pInfo, ev);
773 EvdevProcessKeyEvent(pInfo, ev);
776 EvdevProcessSyncEvent(pInfo, ev);
785 /* just a magic number to reduce the number of reads */
786 #define NUM_EVENTS 16
789 EvdevReadInput(InputInfoPtr pInfo)
791 struct input_event ev[NUM_EVENTS];
792 int i, len = sizeof(ev);
793 EvdevPtr pEvdev = pInfo->private;
795 while (len == sizeof(ev))
797 len = read(pInfo->fd, &ev, sizeof(ev));
800 if (errno == ENODEV) /* May happen after resume */
802 EvdevMBEmuFinalize(pInfo);
803 xf86RemoveEnabledDevice(pInfo);
806 if (pEvdev->reopen_timer)
808 pEvdev->reopen_left = pEvdev->reopen_attempts;
809 pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 100, EvdevReopenTimer, pInfo);
811 } else if (errno != EAGAIN)
813 /* We use X_NONE here because it doesn't alloc */
814 xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
820 /* The kernel promises that we always only read a complete
821 * event, so len != sizeof ev is an error. */
822 if (len % sizeof(ev[0])) {
823 /* We use X_NONE here because it doesn't alloc */
824 xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, strerror(errno));
828 for (i = 0; i < len/sizeof(ev[0]); i++)
829 EvdevProcessEvent(pInfo, &ev[i]);
833 #define TestBit(bit, array) ((array[(bit) / LONG_BITS]) & (1L << ((bit) % LONG_BITS)))
836 EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
838 /* Nothing to do, dix handles all settings */
841 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
842 static KeySym map[] = {
843 /* 0x00 */ NoSymbol, NoSymbol,
844 /* 0x01 */ XK_Escape, NoSymbol,
845 /* 0x02 */ XK_1, XK_exclam,
846 /* 0x03 */ XK_2, XK_at,
847 /* 0x04 */ XK_3, XK_numbersign,
848 /* 0x05 */ XK_4, XK_dollar,
849 /* 0x06 */ XK_5, XK_percent,
850 /* 0x07 */ XK_6, XK_asciicircum,
851 /* 0x08 */ XK_7, XK_ampersand,
852 /* 0x09 */ XK_8, XK_asterisk,
853 /* 0x0a */ XK_9, XK_parenleft,
854 /* 0x0b */ XK_0, XK_parenright,
855 /* 0x0c */ XK_minus, XK_underscore,
856 /* 0x0d */ XK_equal, XK_plus,
857 /* 0x0e */ XK_BackSpace, NoSymbol,
858 /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,
859 /* 0x10 */ XK_Q, NoSymbol,
860 /* 0x11 */ XK_W, NoSymbol,
861 /* 0x12 */ XK_E, NoSymbol,
862 /* 0x13 */ XK_R, NoSymbol,
863 /* 0x14 */ XK_T, NoSymbol,
864 /* 0x15 */ XK_Y, NoSymbol,
865 /* 0x16 */ XK_U, NoSymbol,
866 /* 0x17 */ XK_I, NoSymbol,
867 /* 0x18 */ XK_O, NoSymbol,
868 /* 0x19 */ XK_P, NoSymbol,
869 /* 0x1a */ XK_bracketleft, XK_braceleft,
870 /* 0x1b */ XK_bracketright,XK_braceright,
871 /* 0x1c */ XK_Return, NoSymbol,
872 /* 0x1d */ XK_Control_L, NoSymbol,
873 /* 0x1e */ XK_A, NoSymbol,
874 /* 0x1f */ XK_S, NoSymbol,
875 /* 0x20 */ XK_D, NoSymbol,
876 /* 0x21 */ XK_F, NoSymbol,
877 /* 0x22 */ XK_G, NoSymbol,
878 /* 0x23 */ XK_H, NoSymbol,
879 /* 0x24 */ XK_J, NoSymbol,
880 /* 0x25 */ XK_K, NoSymbol,
881 /* 0x26 */ XK_L, NoSymbol,
882 /* 0x27 */ XK_semicolon, XK_colon,
883 /* 0x28 */ XK_quoteright, XK_quotedbl,
884 /* 0x29 */ XK_quoteleft, XK_asciitilde,
885 /* 0x2a */ XK_Shift_L, NoSymbol,
886 /* 0x2b */ XK_backslash, XK_bar,
887 /* 0x2c */ XK_Z, NoSymbol,
888 /* 0x2d */ XK_X, NoSymbol,
889 /* 0x2e */ XK_C, NoSymbol,
890 /* 0x2f */ XK_V, NoSymbol,
891 /* 0x30 */ XK_B, NoSymbol,
892 /* 0x31 */ XK_N, NoSymbol,
893 /* 0x32 */ XK_M, NoSymbol,
894 /* 0x33 */ XK_comma, XK_less,
895 /* 0x34 */ XK_period, XK_greater,
896 /* 0x35 */ XK_slash, XK_question,
897 /* 0x36 */ XK_Shift_R, NoSymbol,
898 /* 0x37 */ XK_KP_Multiply, NoSymbol,
899 /* 0x38 */ XK_Alt_L, XK_Meta_L,
900 /* 0x39 */ XK_space, NoSymbol,
901 /* 0x3a */ XK_Caps_Lock, NoSymbol,
902 /* 0x3b */ XK_F1, NoSymbol,
903 /* 0x3c */ XK_F2, NoSymbol,
904 /* 0x3d */ XK_F3, NoSymbol,
905 /* 0x3e */ XK_F4, NoSymbol,
906 /* 0x3f */ XK_F5, NoSymbol,
907 /* 0x40 */ XK_F6, NoSymbol,
908 /* 0x41 */ XK_F7, NoSymbol,
909 /* 0x42 */ XK_F8, NoSymbol,
910 /* 0x43 */ XK_F9, NoSymbol,
911 /* 0x44 */ XK_F10, NoSymbol,
912 /* 0x45 */ XK_Num_Lock, NoSymbol,
913 /* 0x46 */ XK_Scroll_Lock, NoSymbol,
914 /* These KP keys should have the KP_7 keysyms in the numlock
916 /* 0x47 */ XK_KP_Home, XK_KP_7,
917 /* 0x48 */ XK_KP_Up, XK_KP_8,
918 /* 0x49 */ XK_KP_Prior, XK_KP_9,
919 /* 0x4a */ XK_KP_Subtract, NoSymbol,
920 /* 0x4b */ XK_KP_Left, XK_KP_4,
921 /* 0x4c */ XK_KP_Begin, XK_KP_5,
922 /* 0x4d */ XK_KP_Right, XK_KP_6,
923 /* 0x4e */ XK_KP_Add, NoSymbol,
924 /* 0x4f */ XK_KP_End, XK_KP_1,
925 /* 0x50 */ XK_KP_Down, XK_KP_2,
926 /* 0x51 */ XK_KP_Next, XK_KP_3,
927 /* 0x52 */ XK_KP_Insert, XK_KP_0,
928 /* 0x53 */ XK_KP_Delete, XK_KP_Decimal,
929 /* 0x54 */ NoSymbol, NoSymbol,
930 /* 0x55 */ XK_F13, NoSymbol,
931 /* 0x56 */ XK_less, XK_greater,
932 /* 0x57 */ XK_F11, NoSymbol,
933 /* 0x58 */ XK_F12, NoSymbol,
934 /* 0x59 */ XK_F14, NoSymbol,
935 /* 0x5a */ XK_F15, NoSymbol,
936 /* 0x5b */ XK_F16, NoSymbol,
937 /* 0x5c */ XK_F17, NoSymbol,
938 /* 0x5d */ XK_F18, NoSymbol,
939 /* 0x5e */ XK_F19, NoSymbol,
940 /* 0x5f */ XK_F20, NoSymbol,
941 /* 0x60 */ XK_KP_Enter, NoSymbol,
942 /* 0x61 */ XK_Control_R, NoSymbol,
943 /* 0x62 */ XK_KP_Divide, NoSymbol,
944 /* 0x63 */ XK_Print, XK_Sys_Req,
945 /* 0x64 */ XK_Alt_R, XK_Meta_R,
946 /* 0x65 */ NoSymbol, NoSymbol, /* KEY_LINEFEED */
947 /* 0x66 */ XK_Home, NoSymbol,
948 /* 0x67 */ XK_Up, NoSymbol,
949 /* 0x68 */ XK_Prior, NoSymbol,
950 /* 0x69 */ XK_Left, NoSymbol,
951 /* 0x6a */ XK_Right, NoSymbol,
952 /* 0x6b */ XK_End, NoSymbol,
953 /* 0x6c */ XK_Down, NoSymbol,
954 /* 0x6d */ XK_Next, NoSymbol,
955 /* 0x6e */ XK_Insert, NoSymbol,
956 /* 0x6f */ XK_Delete, NoSymbol,
957 /* 0x70 */ NoSymbol, NoSymbol, /* KEY_MACRO */
958 /* 0x71 */ NoSymbol, NoSymbol,
959 /* 0x72 */ NoSymbol, NoSymbol,
960 /* 0x73 */ NoSymbol, NoSymbol,
961 /* 0x74 */ NoSymbol, NoSymbol,
962 /* 0x75 */ XK_KP_Equal, NoSymbol,
963 /* 0x76 */ NoSymbol, NoSymbol,
964 /* 0x77 */ NoSymbol, NoSymbol,
965 /* 0x78 */ XK_F21, NoSymbol,
966 /* 0x79 */ XK_F22, NoSymbol,
967 /* 0x7a */ XK_F23, NoSymbol,
968 /* 0x7b */ XK_F24, NoSymbol,
969 /* 0x7c */ XK_KP_Separator, NoSymbol,
970 /* 0x7d */ XK_Meta_L, NoSymbol,
971 /* 0x7e */ XK_Meta_R, NoSymbol,
972 /* 0x7f */ XK_Multi_key, NoSymbol,
973 /* 0x80 */ NoSymbol, NoSymbol,
974 /* 0x81 */ NoSymbol, NoSymbol,
975 /* 0x82 */ NoSymbol, NoSymbol,
976 /* 0x83 */ NoSymbol, NoSymbol,
977 /* 0x84 */ NoSymbol, NoSymbol,
978 /* 0x85 */ NoSymbol, NoSymbol,
979 /* 0x86 */ NoSymbol, NoSymbol,
980 /* 0x87 */ NoSymbol, NoSymbol,
981 /* 0x88 */ NoSymbol, NoSymbol,
982 /* 0x89 */ NoSymbol, NoSymbol,
983 /* 0x8a */ NoSymbol, NoSymbol,
984 /* 0x8b */ NoSymbol, NoSymbol,
985 /* 0x8c */ NoSymbol, NoSymbol,
986 /* 0x8d */ NoSymbol, NoSymbol,
987 /* 0x8e */ NoSymbol, NoSymbol,
988 /* 0x8f */ NoSymbol, NoSymbol,
989 /* 0x90 */ NoSymbol, NoSymbol,
990 /* 0x91 */ NoSymbol, NoSymbol,
991 /* 0x92 */ NoSymbol, NoSymbol,
992 /* 0x93 */ NoSymbol, NoSymbol,
993 /* 0x94 */ NoSymbol, NoSymbol,
994 /* 0x95 */ NoSymbol, NoSymbol,
995 /* 0x96 */ NoSymbol, NoSymbol,
996 /* 0x97 */ NoSymbol, NoSymbol,
997 /* 0x98 */ NoSymbol, NoSymbol,
998 /* 0x99 */ NoSymbol, NoSymbol,
999 /* 0x9a */ NoSymbol, NoSymbol,
1000 /* 0x9b */ NoSymbol, NoSymbol,
1001 /* 0x9c */ NoSymbol, NoSymbol,
1002 /* 0x9d */ NoSymbol, NoSymbol,
1003 /* 0x9e */ NoSymbol, NoSymbol,
1004 /* 0x9f */ NoSymbol, NoSymbol,
1005 /* 0xa0 */ NoSymbol, NoSymbol,
1006 /* 0xa1 */ NoSymbol, NoSymbol,
1007 /* 0xa2 */ NoSymbol, NoSymbol,
1008 /* 0xa3 */ NoSymbol, NoSymbol,
1009 /* 0xa4 */ NoSymbol, NoSymbol,
1010 /* 0xa5 */ NoSymbol, NoSymbol,
1011 /* 0xa6 */ NoSymbol, NoSymbol,
1012 /* 0xa7 */ NoSymbol, NoSymbol,
1013 /* 0xa8 */ NoSymbol, NoSymbol,
1014 /* 0xa9 */ NoSymbol, NoSymbol,
1015 /* 0xaa */ NoSymbol, NoSymbol,
1016 /* 0xab */ NoSymbol, NoSymbol,
1017 /* 0xac */ NoSymbol, NoSymbol,
1018 /* 0xad */ NoSymbol, NoSymbol,
1019 /* 0xae */ NoSymbol, NoSymbol,
1020 /* 0xaf */ NoSymbol, NoSymbol,
1021 /* 0xb0 */ NoSymbol, NoSymbol,
1022 /* 0xb1 */ NoSymbol, NoSymbol,
1023 /* 0xb2 */ NoSymbol, NoSymbol,
1024 /* 0xb3 */ NoSymbol, NoSymbol,
1025 /* 0xb4 */ NoSymbol, NoSymbol,
1026 /* 0xb5 */ NoSymbol, NoSymbol,
1027 /* 0xb6 */ NoSymbol, NoSymbol,
1028 /* 0xb7 */ NoSymbol, NoSymbol,
1029 /* 0xb8 */ NoSymbol, NoSymbol,
1030 /* 0xb9 */ NoSymbol, NoSymbol,
1031 /* 0xba */ NoSymbol, NoSymbol,
1032 /* 0xbb */ NoSymbol, NoSymbol,
1033 /* 0xbc */ NoSymbol, NoSymbol,
1034 /* 0xbd */ NoSymbol, NoSymbol,
1035 /* 0xbe */ NoSymbol, NoSymbol,
1036 /* 0xbf */ NoSymbol, NoSymbol,
1037 /* 0xc0 */ NoSymbol, NoSymbol,
1038 /* 0xc1 */ NoSymbol, NoSymbol,
1039 /* 0xc2 */ NoSymbol, NoSymbol,
1040 /* 0xc3 */ NoSymbol, NoSymbol,
1041 /* 0xc4 */ NoSymbol, NoSymbol,
1042 /* 0xc5 */ NoSymbol, NoSymbol,
1043 /* 0xc6 */ NoSymbol, NoSymbol,
1044 /* 0xc7 */ NoSymbol, NoSymbol,
1045 /* 0xc8 */ NoSymbol, NoSymbol,
1046 /* 0xc9 */ NoSymbol, NoSymbol,
1047 /* 0xca */ NoSymbol, NoSymbol,
1048 /* 0xcb */ NoSymbol, NoSymbol,
1049 /* 0xcc */ NoSymbol, NoSymbol,
1050 /* 0xcd */ NoSymbol, NoSymbol,
1051 /* 0xce */ NoSymbol, NoSymbol,
1052 /* 0xcf */ NoSymbol, NoSymbol,
1053 /* 0xd0 */ NoSymbol, NoSymbol,
1054 /* 0xd1 */ NoSymbol, NoSymbol,
1055 /* 0xd2 */ NoSymbol, NoSymbol,
1056 /* 0xd3 */ NoSymbol, NoSymbol,
1057 /* 0xd4 */ NoSymbol, NoSymbol,
1058 /* 0xd5 */ NoSymbol, NoSymbol,
1059 /* 0xd6 */ NoSymbol, NoSymbol,
1060 /* 0xd7 */ NoSymbol, NoSymbol,
1061 /* 0xd8 */ NoSymbol, NoSymbol,
1062 /* 0xd9 */ NoSymbol, NoSymbol,
1063 /* 0xda */ NoSymbol, NoSymbol,
1064 /* 0xdb */ NoSymbol, NoSymbol,
1065 /* 0xdc */ NoSymbol, NoSymbol,
1066 /* 0xdd */ NoSymbol, NoSymbol,
1067 /* 0xde */ NoSymbol, NoSymbol,
1068 /* 0xdf */ NoSymbol, NoSymbol,
1069 /* 0xe0 */ NoSymbol, NoSymbol,
1070 /* 0xe1 */ NoSymbol, NoSymbol,
1071 /* 0xe2 */ NoSymbol, NoSymbol,
1072 /* 0xe3 */ NoSymbol, NoSymbol,
1073 /* 0xe4 */ NoSymbol, NoSymbol,
1074 /* 0xe5 */ NoSymbol, NoSymbol,
1075 /* 0xe6 */ NoSymbol, NoSymbol,
1076 /* 0xe7 */ NoSymbol, NoSymbol,
1077 /* 0xe8 */ NoSymbol, NoSymbol,
1078 /* 0xe9 */ NoSymbol, NoSymbol,
1079 /* 0xea */ NoSymbol, NoSymbol,
1080 /* 0xeb */ NoSymbol, NoSymbol,
1081 /* 0xec */ NoSymbol, NoSymbol,
1082 /* 0xed */ NoSymbol, NoSymbol,
1083 /* 0xee */ NoSymbol, NoSymbol,
1084 /* 0xef */ NoSymbol, NoSymbol,
1085 /* 0xf0 */ NoSymbol, NoSymbol,
1086 /* 0xf1 */ NoSymbol, NoSymbol,
1087 /* 0xf2 */ NoSymbol, NoSymbol,
1088 /* 0xf3 */ NoSymbol, NoSymbol,
1089 /* 0xf4 */ NoSymbol, NoSymbol,
1090 /* 0xf5 */ NoSymbol, NoSymbol,
1091 /* 0xf6 */ NoSymbol, NoSymbol,
1092 /* 0xf7 */ NoSymbol, NoSymbol,
1095 static struct { KeySym keysym; CARD8 mask; } modifiers[] = {
1096 { XK_Shift_L, ShiftMask },
1097 { XK_Shift_R, ShiftMask },
1098 { XK_Control_L, ControlMask },
1099 { XK_Control_R, ControlMask },
1100 { XK_Caps_Lock, LockMask },
1101 { XK_Alt_L, AltMask },
1102 { XK_Alt_R, AltMask },
1103 { XK_Meta_L, Mod4Mask },
1104 { XK_Meta_R, Mod4Mask },
1105 { XK_Num_Lock, NumLockMask },
1106 { XK_Scroll_Lock, ScrollLockMask },
1107 { XK_Mode_switch, AltLangMask }
1110 /* Server 1.6 and earlier */
1112 EvdevInitKeysyms(DeviceIntPtr device)
1117 CARD8 modMap[MAP_LENGTH];
1121 pInfo = device->public.devicePrivate;
1122 pEvdev = pInfo->private;
1124 /* Compute the modifier map */
1125 memset(modMap, 0, sizeof modMap);
1127 for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) {
1128 sym = map[i * GLYPHS_PER_KEY];
1129 for (j = 0; j < ArrayLength(modifiers); j++) {
1130 if (modifiers[j].keysym == sym)
1131 modMap[i + MIN_KEYCODE] = modifiers[j].mask;
1136 keySyms.mapWidth = GLYPHS_PER_KEY;
1137 keySyms.minKeyCode = MIN_KEYCODE;
1138 keySyms.maxKeyCode = MIN_KEYCODE + ArrayLength(map) / GLYPHS_PER_KEY - 1;
1140 XkbSetRulesDflts(pEvdev->rmlvo.rules, pEvdev->rmlvo.model,
1141 pEvdev->rmlvo.layout, pEvdev->rmlvo.variant,
1142 pEvdev->rmlvo.options);
1143 if (!XkbInitKeyboardDeviceStruct(device, &pEvdev->xkbnames,
1144 &keySyms, modMap, NULL,
1153 EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
1155 static struct { int xbit, code; } bits[] = {
1156 { CAPSFLAG, LED_CAPSL },
1157 { NUMFLAG, LED_NUML },
1158 { SCROLLFLAG, LED_SCROLLL },
1159 { MODEFLAG, LED_KANA },
1160 { COMPOSEFLAG, LED_COMPOSE }
1164 struct input_event ev[ArrayLength(bits)];
1167 memset(ev, 0, sizeof(ev));
1169 pInfo = device->public.devicePrivate;
1170 for (i = 0; i < ArrayLength(bits); i++) {
1171 ev[i].type = EV_LED;
1172 ev[i].code = bits[i].code;
1173 ev[i].value = (ctrl->leds & bits[i].xbit) > 0;
1176 write(pInfo->fd, ev, sizeof ev);
1180 EvdevAddKeyClass(DeviceIntPtr device)
1185 pInfo = device->public.devicePrivate;
1186 pEvdev = pInfo->private;
1188 /* sorry, no rules change allowed for you */
1189 xf86ReplaceStrOption(pInfo->options, "xkb_rules", "evdev");
1190 SetXkbOption(pInfo, "xkb_rules", &pEvdev->rmlvo.rules);
1191 SetXkbOption(pInfo, "xkb_model", &pEvdev->rmlvo.model);
1192 if (!pEvdev->rmlvo.model)
1193 SetXkbOption(pInfo, "XkbModel", &pEvdev->rmlvo.model);
1194 SetXkbOption(pInfo, "xkb_layout", &pEvdev->rmlvo.layout);
1195 if (!pEvdev->rmlvo.layout)
1196 SetXkbOption(pInfo, "XkbLayout", &pEvdev->rmlvo.layout);
1197 SetXkbOption(pInfo, "xkb_variant", &pEvdev->rmlvo.variant);
1198 if (!pEvdev->rmlvo.variant)
1199 SetXkbOption(pInfo, "XkbVariant", &pEvdev->rmlvo.variant);
1200 SetXkbOption(pInfo, "xkb_options", &pEvdev->rmlvo.options);
1201 if (!pEvdev->rmlvo.options)
1202 SetXkbOption(pInfo, "XkbOptions", &pEvdev->rmlvo.options);
1204 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5
1205 if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl))
1208 if (!EvdevInitKeysyms(device))
1217 EvdevAddAbsClass(DeviceIntPtr device)
1221 int num_axes, axis, i = 0;
1224 pInfo = device->public.devicePrivate;
1225 pEvdev = pInfo->private;
1227 if (!TestBit(EV_ABS, pEvdev->bitmask))
1230 num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
1233 pEvdev->num_vals = num_axes;
1234 memset(pEvdev->vals, 0, num_axes * sizeof(int));
1235 memset(pEvdev->old_vals, -1, num_axes * sizeof(int));
1236 atoms = malloc(pEvdev->num_vals * sizeof(Atom));
1238 for (axis = ABS_X; axis <= ABS_MAX; axis++) {
1239 pEvdev->axis_map[axis] = -1;
1240 if (!TestBit(axis, pEvdev->abs_bitmask))
1242 pEvdev->axis_map[axis] = i;
1246 EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
1248 if (!InitValuatorClassDeviceStruct(device, num_axes,
1249 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
1252 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
1255 GetMotionHistorySize(), Absolute))
1258 for (axis = ABS_X; axis <= ABS_MAX; axis++) {
1259 int axnum = pEvdev->axis_map[axis];
1262 xf86InitValuatorAxisStruct(device, axnum,
1263 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
1266 pEvdev->absinfo[axis].minimum,
1267 pEvdev->absinfo[axis].maximum,
1268 10000, 0, 10000, Absolute);
1269 xf86InitValuatorDefaults(device, axnum);
1270 pEvdev->old_vals[axnum] = -1;
1275 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
1282 EvdevAddRelClass(DeviceIntPtr device)
1286 int num_axes, axis, i = 0;
1289 pInfo = device->public.devicePrivate;
1290 pEvdev = pInfo->private;
1292 if (!TestBit(EV_REL, pEvdev->bitmask))
1295 num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX));
1299 /* Wheels are special, we post them as button events. So let's ignore them
1300 * in the axes list too */
1301 if (TestBit(REL_WHEEL, pEvdev->rel_bitmask))
1303 if (TestBit(REL_HWHEEL, pEvdev->rel_bitmask))
1305 if (TestBit(REL_DIAL, pEvdev->rel_bitmask))
1311 pEvdev->num_vals = num_axes;
1312 memset(pEvdev->vals, 0, num_axes * sizeof(int));
1313 atoms = malloc(pEvdev->num_vals * sizeof(Atom));
1315 for (axis = REL_X; axis <= REL_MAX; axis++)
1317 pEvdev->axis_map[axis] = -1;
1318 /* We don't post wheel events, so ignore them here too */
1319 if (axis == REL_WHEEL || axis == REL_HWHEEL || axis == REL_DIAL)
1321 if (!TestBit(axis, pEvdev->rel_bitmask))
1323 pEvdev->axis_map[axis] = i;
1327 EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
1329 if (!InitValuatorClassDeviceStruct(device, num_axes,
1330 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
1333 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
1336 GetMotionHistorySize(), Relative))
1339 for (axis = REL_X; axis <= REL_MAX; axis++)
1341 int axnum = pEvdev->axis_map[axis];
1345 xf86InitValuatorAxisStruct(device, axnum,
1346 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
1349 -1, -1, 1, 0, 1, Relative);
1350 xf86InitValuatorDefaults(device, axnum);
1355 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
1362 EvdevAddButtonClass(DeviceIntPtr device)
1368 pInfo = device->public.devicePrivate;
1369 pEvdev = pInfo->private;
1371 labels = malloc(pEvdev->num_buttons * sizeof(Atom));
1372 EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels);
1374 if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons,
1375 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
1386 * Init the button mapping for the device. By default, this is a 1:1 mapping,
1387 * i.e. Button 1 maps to Button 1, Button 2 to 2, etc.
1389 * If a mapping has been specified, the mapping is the default, with the
1390 * user-defined ones overwriting the defaults.
1391 * i.e. a user-defined mapping of "3 2 1" results in a mapping of 3 2 1 4 5 6 ...
1393 * Invalid button mappings revert to the default.
1395 * Note that index 0 is unused, button 0 does not exist.
1396 * This mapping is initialised for all devices, but only applied if the device
1397 * has buttons (in EvdevAddButtonClass).
1400 EvdevInitButtonMapping(InputInfoPtr pInfo)
1402 int i, nbuttons = 1;
1403 char *mapping = NULL;
1404 EvdevPtr pEvdev = pInfo->private;
1406 /* Check for user-defined button mapping */
1407 if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL)))
1412 xf86Msg(X_CONFIG, "%s: ButtonMapping '%s'\n", pInfo->name, mapping);
1413 while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS)
1415 btn = strtol(mapping, &s, 10);
1417 if (s == mapping || btn < 0 || btn > EVDEV_MAXBUTTONS)
1420 "%s: ... Invalid button mapping. Using defaults\n",
1422 nbuttons = 1; /* ensure defaults start at 1 */
1426 pEvdev->btnmap[nbuttons++] = btn;
1431 for (i = nbuttons; i < ArrayLength(pEvdev->btnmap); i++)
1432 pEvdev->btnmap[i] = i;
1437 EvdevInitAnyClass(DeviceIntPtr device, EvdevPtr pEvdev)
1439 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS &&
1440 EvdevAddRelClass(device) == Success)
1441 xf86Msg(X_INFO, "%s: initialized for relative axes.\n", device->name);
1442 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS &&
1443 EvdevAddAbsClass(device) == Success)
1444 xf86Msg(X_INFO, "%s: initialized for absolute axes.\n", device->name);
1448 EvdevInitAbsClass(DeviceIntPtr device, EvdevPtr pEvdev)
1450 if (EvdevAddAbsClass(device) == Success) {
1452 xf86Msg(X_INFO,"%s: initialized for absolute axes.\n", device->name);
1456 xf86Msg(X_ERROR,"%s: failed to initialize for absolute axes.\n",
1459 pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
1465 EvdevInitRelClass(DeviceIntPtr device, EvdevPtr pEvdev)
1467 int has_abs_axes = pEvdev->flags & EVDEV_ABSOLUTE_EVENTS;
1469 if (EvdevAddRelClass(device) == Success) {
1471 xf86Msg(X_INFO,"%s: initialized for relative axes.\n", device->name);
1475 xf86Msg(X_WARNING,"%s: ignoring absolute axes.\n", device->name);
1476 pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
1481 xf86Msg(X_ERROR,"%s: failed to initialize for relative axes.\n",
1484 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
1487 EvdevInitAbsClass(device, pEvdev);
1492 EvdevInitTouchDevice(DeviceIntPtr device, EvdevPtr pEvdev)
1494 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) {
1496 xf86Msg(X_WARNING,"%s: touchpads, tablets and touchscreens ignore "
1497 "relative axes.\n", device->name);
1499 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
1502 EvdevInitAbsClass(device, pEvdev);
1506 EvdevInit(DeviceIntPtr device)
1512 pInfo = device->public.devicePrivate;
1513 pEvdev = pInfo->private;
1515 /* clear all axis_map entries */
1516 for(i = 0; i < max(ABS_CNT,REL_CNT); i++)
1517 pEvdev->axis_map[i]=-1;
1519 if (pEvdev->flags & EVDEV_KEYBOARD_EVENTS)
1520 EvdevAddKeyClass(device);
1521 if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
1522 EvdevAddButtonClass(device);
1524 /* We don't allow relative and absolute axes on the same device. The
1525 * reason is that some devices (MS Optical Desktop 2000) register both
1526 * rel and abs axes for x/y.
1528 * The abs axes register min/max; this min/max then also applies to the
1529 * relative device (the mouse) and caps it at 0..255 for both axes.
1530 * So, unless you have a small screen, you won't be enjoying it much;
1531 * consequently, absolute axes are generally ignored.
1533 * However, currenly only a device with absolute axes can be registered
1534 * as a touch{pad,screen}. Thus, given such a device, absolute axes are
1535 * used and relative axes are ignored.
1538 if (pEvdev->flags & (EVDEV_UNIGNORE_RELATIVE | EVDEV_UNIGNORE_ABSOLUTE))
1539 EvdevInitAnyClass(device, pEvdev);
1540 else if (pEvdev->flags & (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET))
1541 EvdevInitTouchDevice(device, pEvdev);
1542 else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
1543 EvdevInitRelClass(device, pEvdev);
1544 #ifdef _F_INIT_ABS_ONLY_FOR_POINTER_
1545 else if ( !(pEvdev->flags & EVDEV_KEYBOARD_EVENTS) && (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) )
1547 else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
1549 EvdevInitAbsClass(device, pEvdev);
1551 #ifdef HAVE_PROPERTIES
1552 /* We drop the return value, the only time we ever want the handlers to
1553 * unregister is when the device dies. In which case we don't have to
1554 * unregister anyway */
1555 EvdevInitProperty(device);
1556 XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
1557 EvdevMBEmuInitProperty(device);
1558 EvdevWheelEmuInitProperty(device);
1559 EvdevDragLockInitProperty(device);
1566 * Init all extras (wheel emulation, etc.) and grab the device.
1568 * Coming from a resume, the grab may fail with ENODEV. In this case, we set a
1569 * timer to wake up and try to reopen the device later.
1572 EvdevOn(DeviceIntPtr device)
1578 pInfo = device->public.devicePrivate;
1579 pEvdev = pInfo->private;
1581 if (pInfo->fd != -1 && pEvdev->grabDevice &&
1582 (rc = ioctl(pInfo->fd, EVIOCGRAB, (void *)1)))
1584 xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
1587 /* ENODEV - device has disappeared after resume */
1588 if (rc && errno == ENODEV)
1595 if (pInfo->fd == -1)
1597 pEvdev->reopen_left = pEvdev->reopen_attempts;
1598 pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 100, EvdevReopenTimer, pInfo);
1601 pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
1602 if (EvdevIsDuplicate(pInfo))
1604 xf86Msg(X_WARNING, "%s: Refusing to enable duplicate device.\n",
1609 pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 0, NULL, NULL);
1611 xf86FlushInput(pInfo->fd);
1612 xf86AddEnabledDevice(pInfo);
1613 EvdevMBEmuOn(pInfo);
1614 pEvdev->flags |= EVDEV_INITIALIZED;
1615 device->public.on = TRUE;
1623 EvdevProc(DeviceIntPtr device, int what)
1627 int region[4] = { 0, };
1629 pInfo = device->public.devicePrivate;
1630 pEvdev = pInfo->private;
1635 return EvdevInit(device);
1638 return EvdevOn(device);
1641 if (pEvdev->flags & EVDEV_INITIALIZED)
1642 EvdevMBEmuFinalize(pInfo);
1644 if (pInfo->fd != -1)
1646 if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
1647 xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
1649 xf86RemoveEnabledDevice(pInfo);
1653 pEvdev->min_maj = 0;
1654 pEvdev->flags &= ~EVDEV_INITIALIZED;
1655 device->public.on = FALSE;
1656 if (pEvdev->reopen_timer)
1658 TimerFree(pEvdev->reopen_timer);
1659 pEvdev->reopen_timer = NULL;
1664 #ifdef _F_EVDEV_CONFINE_REGION_
1665 if( pEvdev->confined_id )
1666 EvdevSetConfineRegion(pInfo, 1, ®ion[0]);
1667 #endif//_F_EVDEV_CONFINE_REGION_
1668 xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
1669 if (pInfo->fd != -1) {
1673 EvdevRemoveDevice(pInfo);
1674 pEvdev->min_maj = 0;
1682 * Get as much information as we can from the fd and cache it.
1683 * If compare is True, then the information retrieved will be compared to the
1684 * one already cached. If the information does not match, then this function
1687 * @return Success if the information was cached, or !Success otherwise.
1690 EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare)
1692 EvdevPtr pEvdev = pInfo->private;
1696 char name[1024] = {0};
1697 unsigned long bitmask[NLONGS(EV_CNT)] = {0};
1698 unsigned long key_bitmask[NLONGS(KEY_CNT)] = {0};
1699 unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0};
1700 unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0};
1701 unsigned long led_bitmask[NLONGS(LED_CNT)] = {0};
1703 if (ioctl(pInfo->fd, EVIOCGNAME(sizeof(name) - 1), name) < 0) {
1704 xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
1709 strcpy(pEvdev->name, name);
1710 } else if (strcmp(pEvdev->name, name)) {
1711 xf86Msg(X_ERROR, "%s: device name changed: %s != %s\n",
1712 pInfo->name, pEvdev->name, name);
1716 len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask);
1718 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
1719 pInfo->name, strerror(errno));
1724 memcpy(pEvdev->bitmask, bitmask, len);
1725 } else if (memcmp(pEvdev->bitmask, bitmask, len)) {
1726 xf86Msg(X_ERROR, "%s: device bitmask has changed\n", pInfo->name);
1730 len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask);
1732 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
1733 pInfo->name, strerror(errno));
1738 memcpy(pEvdev->rel_bitmask, rel_bitmask, len);
1739 } else if (memcmp(pEvdev->rel_bitmask, rel_bitmask, len)) {
1740 xf86Msg(X_ERROR, "%s: device rel_bitmask has changed\n", pInfo->name);
1744 len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
1746 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
1747 pInfo->name, strerror(errno));
1752 memcpy(pEvdev->abs_bitmask, abs_bitmask, len);
1753 } else if (memcmp(pEvdev->abs_bitmask, abs_bitmask, len)) {
1754 xf86Msg(X_ERROR, "%s: device abs_bitmask has changed\n", pInfo->name);
1758 len = ioctl(pInfo->fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask);
1760 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
1761 pInfo->name, strerror(errno));
1766 memcpy(pEvdev->led_bitmask, led_bitmask, len);
1767 } else if (memcmp(pEvdev->led_bitmask, led_bitmask, len)) {
1768 xf86Msg(X_ERROR, "%s: device led_bitmask has changed\n", pInfo->name);
1773 * Do not try to validate absinfo data since it is not expected
1774 * to be static, always refresh it in evdev structure.
1776 for (i = ABS_X; i <= ABS_MAX; i++) {
1777 if (TestBit(i, abs_bitmask)) {
1778 len = ioctl(pInfo->fd, EVIOCGABS(i), &pEvdev->absinfo[i]);
1780 xf86Msg(X_ERROR, "%s: ioctl EVIOCGABSi(%d) failed: %s\n",
1781 pInfo->name, i, strerror(errno));
1787 len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
1789 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
1790 pInfo->name, strerror(errno));
1796 * Keys are special as user can adjust keymap at any time (on
1797 * devices that support EVIOCSKEYCODE. However we do not expect
1798 * buttons reserved for mice/tablets/digitizers and so on to
1799 * appear/disappear so we will check only those in
1800 * [BTN_MISC, KEY_OK) range.
1802 size_t start_word = BTN_MISC / LONG_BITS;
1803 size_t start_byte = start_word * sizeof(unsigned long);
1804 size_t end_word = KEY_OK / LONG_BITS;
1805 size_t end_byte = end_word * sizeof(unsigned long);
1807 if (len >= start_byte &&
1808 memcmp(&pEvdev->key_bitmask[start_word], &key_bitmask[start_word],
1809 min(len, end_byte) - start_byte + 1)) {
1810 xf86Msg(X_ERROR, "%s: device key_bitmask has changed\n", pInfo->name);
1815 /* Copy the data so we have reasonably up-to-date info */
1816 memcpy(pEvdev->key_bitmask, key_bitmask, len);
1826 EvdevProbe(InputInfoPtr pInfo)
1828 int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll;
1830 int ignore_abs = 0, ignore_rel = 0;
1831 EvdevPtr pEvdev = pInfo->private;
1833 if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
1834 if (errno == EINVAL) {
1835 /* keyboards are unsafe in 2.4 */
1837 pEvdev->grabDevice = 0;
1839 xf86Msg(X_ERROR, "Grab failed. Device already configured?\n");
1842 } else if (pEvdev->grabDevice) {
1843 ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
1846 /* Trinary state for ignoring axes:
1847 - unset: do the normal thing.
1848 - TRUE: explicitly ignore them.
1849 - FALSE: unignore axes, use them at all cost if they're present.
1851 if (xf86FindOption(pInfo->options, "IgnoreRelativeAxes"))
1853 if (xf86SetBoolOption(pInfo->options, "IgnoreRelativeAxes", FALSE))
1856 pEvdev->flags |= EVDEV_UNIGNORE_RELATIVE;
1859 if (xf86FindOption(pInfo->options, "IgnoreAbsoluteAxes"))
1861 if (xf86SetBoolOption(pInfo->options, "IgnoreAbsoluteAxes", FALSE))
1864 pEvdev->flags |= EVDEV_UNIGNORE_ABSOLUTE;
1867 has_rel_axes = FALSE;
1868 has_abs_axes = FALSE;
1873 /* count all buttons */
1874 for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
1877 if (TestBit(i, pEvdev->key_bitmask))
1879 mapping = EvdevUtilButtonEventToButtonNumber(pEvdev, i);
1880 if (mapping > num_buttons)
1881 num_buttons = mapping;
1887 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
1888 pEvdev->num_buttons = num_buttons;
1889 xf86Msg(X_INFO, "%s: Found %d mouse buttons\n", pInfo->name,
1893 for (i = 0; i < REL_MAX; i++) {
1894 if (TestBit(i, pEvdev->rel_bitmask)) {
1895 has_rel_axes = TRUE;
1901 if (TestBit(REL_WHEEL, pEvdev->rel_bitmask) ||
1902 TestBit(REL_HWHEEL, pEvdev->rel_bitmask) ||
1903 TestBit(REL_DIAL, pEvdev->rel_bitmask)) {
1904 xf86Msg(X_INFO, "%s: Found scroll wheel(s)\n", pInfo->name);
1907 xf86Msg(X_INFO, "%s: Forcing buttons for scroll wheel(s)\n",
1909 num_buttons = (num_buttons < 3) ? 7 : num_buttons + 4;
1910 pEvdev->num_buttons = num_buttons;
1915 xf86Msg(X_INFO, "%s: Found relative axes\n", pInfo->name);
1916 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
1918 if (TestBit(REL_X, pEvdev->rel_bitmask) &&
1919 TestBit(REL_Y, pEvdev->rel_bitmask)) {
1920 xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name);
1923 xf86Msg(X_INFO, "%s: Relative axes present but ignored.\n", pInfo->name);
1924 has_rel_axes = FALSE;
1928 for (i = 0; i < ABS_MAX; i++) {
1929 if (TestBit(i, pEvdev->abs_bitmask)) {
1930 has_abs_axes = TRUE;
1935 if (ignore_abs && has_abs_axes)
1937 xf86Msg(X_INFO, "%s: Absolute axes present but ignored.\n", pInfo->name);
1938 has_abs_axes = FALSE;
1939 } else if (has_abs_axes) {
1940 xf86Msg(X_INFO, "%s: Found absolute axes\n", pInfo->name);
1941 pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
1943 if ((TestBit(ABS_X, pEvdev->abs_bitmask) &&
1944 TestBit(ABS_Y, pEvdev->abs_bitmask))) {
1945 xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
1946 if (TestBit(BTN_TOOL_PEN, pEvdev->key_bitmask))
1948 xf86Msg(X_INFO, "%s: Found absolute tablet.\n", pInfo->name);
1949 pEvdev->flags |= EVDEV_TABLET;
1950 if (!pEvdev->num_buttons)
1952 pEvdev->num_buttons = 7; /* LMR + scroll wheels */
1953 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
1955 } else if (TestBit(ABS_PRESSURE, pEvdev->abs_bitmask) ||
1956 TestBit(BTN_TOUCH, pEvdev->key_bitmask)) {
1957 if (num_buttons || TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask)) {
1958 xf86Msg(X_INFO, "%s: Found absolute touchpad.\n", pInfo->name);
1959 pEvdev->flags |= EVDEV_TOUCHPAD;
1960 memset(pEvdev->old_vals, -1, sizeof(int) * pEvdev->num_vals);
1962 xf86Msg(X_INFO, "%s: Found absolute touchscreen\n", pInfo->name);
1963 pEvdev->flags |= EVDEV_TOUCHSCREEN;
1964 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
1970 for (i = 0; i < BTN_MISC; i++) {
1971 if (TestBit(i, pEvdev->key_bitmask)) {
1972 xf86Msg(X_INFO, "%s: Found keys\n", pInfo->name);
1973 pEvdev->flags |= EVDEV_KEYBOARD_EVENTS;
1979 if (has_rel_axes || has_abs_axes || num_buttons) {
1980 if (pEvdev->flags & EVDEV_TOUCHPAD) {
1981 xf86Msg(X_INFO, "%s: Configuring as touchpad\n", pInfo->name);
1982 pInfo->type_name = XI_TOUCHPAD;
1983 } else if (pEvdev->flags & EVDEV_TABLET) {
1984 xf86Msg(X_INFO, "%s: Configuring as tablet\n", pInfo->name);
1985 pInfo->type_name = XI_TABLET;
1986 } else if (pEvdev->flags & EVDEV_TOUCHSCREEN) {
1987 xf86Msg(X_INFO, "%s: Configuring as touchscreen\n", pInfo->name);
1988 pInfo->type_name = XI_TOUCHSCREEN;
1990 xf86Msg(X_INFO, "%s: Configuring as mouse\n", pInfo->name);
1991 pInfo->type_name = XI_MOUSE;
1997 xf86Msg(X_INFO, "%s: Kernel < 2.6 is too old, ignoring keyboard\n",
2000 xf86Msg(X_INFO, "%s: Configuring as keyboard\n", pInfo->name);
2001 pInfo->type_name = XI_KEYBOARD;
2007 xf86Msg(X_INFO, "%s: Adding scrollwheel support\n", pInfo->name);
2008 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
2009 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
2016 EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
2018 EvdevPtr pEvdev = pInfo->private;
2020 if (num_calibration == 0) {
2021 pEvdev->flags &= ~EVDEV_CALIBRATED;
2022 pEvdev->calibration.min_x = 0;
2023 pEvdev->calibration.max_x = 0;
2024 pEvdev->calibration.min_y = 0;
2025 pEvdev->calibration.max_y = 0;
2026 } else if (num_calibration == 4) {
2027 pEvdev->flags |= EVDEV_CALIBRATED;
2028 pEvdev->calibration.min_x = calibration[0];
2029 pEvdev->calibration.max_x = calibration[1];
2030 pEvdev->calibration.min_y = calibration[2];
2031 pEvdev->calibration.max_y = calibration[3];
2035 #ifdef _F_EVDEV_CONFINE_REGION_
2037 GetMasterPointerFromId(int deviceid)
2039 DeviceIntPtr pDev = inputInfo.devices;
2042 if( pDev->id == deviceid && pDev->master )
2044 return pDev->master;
2053 IsMaster(DeviceIntPtr dev)
2055 return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
2059 GetPairedDevice(DeviceIntPtr dev)
2061 if (!IsMaster(dev) && dev->master)
2064 return dev->spriteInfo->paired;
2068 GetMaster(DeviceIntPtr dev, int which)
2070 DeviceIntPtr master;
2075 master = dev->master;
2079 if (which == MASTER_KEYBOARD)
2081 if (master->type != MASTER_KEYBOARD)
2082 master = GetPairedDevice(master);
2085 if (master->type != MASTER_POINTER)
2086 master = GetPairedDevice(master);
2094 EvdevHookPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
2095 BoxPtr pHotBox, BoxPtr pTopLeftBox)
2097 *pTopLeftBox = *pHotBox;
2101 EvdevHookPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
2106 pInfo = pDev->public.devicePrivate;
2107 if(!pInfo || !pInfo->private) return;
2108 pEvdev = pInfo->private;
2110 miPointerPtr pPointer;
2111 pPointer = MIPOINTER(pDev);
2113 if( IsMaster(pDev) && GetMasterPointerFromId(pEvdev->confined_id) == pDev )
2115 if( pBox->x1 < pEvdev->pointer_confine_region.x1 )
2116 pBox->x1 = pEvdev->pointer_confine_region.x1;
2117 if( pBox->y1 < pEvdev->pointer_confine_region.y1 )
2118 pBox->y1 = pEvdev->pointer_confine_region.y1;
2119 if( pBox->x2 > pEvdev->pointer_confine_region.x2 )
2120 pBox->x2 = pEvdev->pointer_confine_region.x2;
2121 if( pBox->y2 > pEvdev->pointer_confine_region.y2 )
2122 pBox->y2 = pEvdev->pointer_confine_region.y2;
2125 pPointer->limits = *pBox;
2126 pPointer->confined = PointerConfinedToScreen(pDev);
2130 EvdevSetCursorLimits(InputInfoPtr pInfo, int region[5], int isSet)
2132 EvdevPtr pEvdev = pInfo->private;
2136 ScreenPtr pCursorScreen = NULL;
2138 pCursorScreen = miPointerGetScreen(pInfo->dev);
2140 if( !pCursorScreen )
2142 xf86DrvMsg(-1, X_ERROR, "[X11][SetCursorLimits] Failed to get screen information for pointer !\n");
2148 //Clip confine region with screen's width/height
2151 if( region[2] >= pCursorScreen->width )
2152 region[2] = pCursorScreen->width - 1;
2153 if( region [1] < 0 )
2155 if( region[3] >= pCursorScreen->height )
2156 region[3] = pCursorScreen->height - 1;
2158 pEvdev->pointer_confine_region.x1 = region[0];
2159 pEvdev->pointer_confine_region.y1 = region[1];
2160 pEvdev->pointer_confine_region.x2 = region[2];
2161 pEvdev->pointer_confine_region.y2 = region[3];
2162 pEvdev->confined_id = pInfo->dev->id;
2164 pCursorScreen->ConstrainCursor(inputInfo.pointer, pCursorScreen, &pEvdev->pointer_confine_region);
2165 xf86DrvMsg(-1, X_INFO, "[X11][SetCursorLimits] Constrain information for cursor was set to TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) !\n",
2166 region[0], region[1], region[2], region[3]);
2168 if( pCursorScreen->ConstrainCursor != EvdevHookPointerCursorLimits &&
2169 pCursorScreen->ConstrainCursor != EvdevHookPointerConstrainCursor)
2171 //Backup original function pointer(s)
2172 pEvdev->pOrgConstrainCursor = pCursorScreen->ConstrainCursor;
2173 pEvdev->pOrgCursorLimits = pCursorScreen->CursorLimits;
2175 //Overriding function pointer(s)
2176 pCursorScreen->CursorLimits = EvdevHookPointerCursorLimits;
2177 pCursorScreen->ConstrainCursor = EvdevHookPointerConstrainCursor;
2180 //Skip pointer warp if region[4] is zero
2184 v[0] = region[0] + (int)((float)(region[2]-region[0])/2);
2185 v[1] = region[1] + (int)((float)(region[3]-region[1])/2);
2187 xf86PostMotionEventP(pInfo->dev, TRUE, REL_X, 2, v);
2188 xf86DrvMsg(-1, X_INFO, "[X11][SetCursorLimits] Cursor was warped to (%d, %d) !\n", v[0], v[1]);
2189 miPointerGetPosition(pInfo->dev, &x, &y);
2190 xf86DrvMsg(-1, X_INFO, "[X11][SetCursorLimits] Cursor is located at (%d, %d) !\n", x, y);
2194 pEvdev->pointer_confine_region.x1 = 0;
2195 pEvdev->pointer_confine_region.y1 = 0;
2196 pEvdev->pointer_confine_region.x2 = pCursorScreen->width - 1;
2197 pEvdev->pointer_confine_region.y2 = pCursorScreen->height - 1;
2198 pEvdev->confined_id = 0;
2200 pCursorScreen->ConstrainCursor(inputInfo.pointer, pCursorScreen, &pEvdev->pointer_confine_region);
2201 xf86DrvMsg(-1, X_INFO, "[X11][SetCursorLimits] Constrain information for cursor was restored ! TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) !\n",
2202 pEvdev->pointer_confine_region.x1, pEvdev->pointer_confine_region.y1,
2203 pEvdev->pointer_confine_region.x2, pEvdev->pointer_confine_region.y2);
2205 //Restore original function pointer(s)
2206 pCursorScreen->CursorLimits = pEvdev->pOrgCursorLimits;
2207 pCursorScreen->ConstrainCursor = pEvdev->pOrgConstrainCursor;
2212 EvdevSetConfineRegion(InputInfoPtr pInfo, int num_item, int region[5])
2214 EvdevPtr pEvdev = pInfo->private;
2216 if( num_item != 5 && num_item != 1 )
2221 if ( (region[2]-region[0]>0) && (region[3]-region[1]>0) )
2223 EvdevSetCursorLimits(pInfo, ®ion[0], 1);
2224 xf86DrvMsg(-1, X_INFO, "[X11][SetConfineRegion] Confine region was set to TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) pointerwarp=%d\n",
2225 region[0], region[1], region[2], region[3], region[4]);
2226 pEvdev->flags |= EVDEV_CONFINE_REGION;
2229 else if( num_item == 1 )
2231 if( !region[0] && (pEvdev->flags & EVDEV_CONFINE_REGION) )
2233 EvdevSetCursorLimits(pInfo, ®ion[0], 0);
2234 xf86DrvMsg(-1, X_INFO, "[X11][SetConfineRegion] Confine region was unset !\n");
2235 pEvdev->flags &= ~EVDEV_CONFINE_REGION;
2239 #endif /* _F_EVDEV_CONFINE_REGION_ */
2242 EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2245 const char *device, *str;
2246 int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
2247 int num_resolution = 0, resolution[4] = { 0, 0, 0, 0 };
2252 ErrorF("[X11][EvdevPreInit] pInfo is NULL !\n");
2256 /* Initialise the InputInfoRec. */
2258 pInfo->type_name = "UNKNOWN";
2259 pInfo->device_control = EvdevProc;
2260 pInfo->read_input = EvdevReadInput;
2261 pInfo->switch_mode = NULL;
2264 if (!(pEvdev = calloc(sizeof(EvdevRec), 1)))
2267 pInfo->private = pEvdev;
2269 xf86CollectInputOptions(pInfo, evdevDefaults);
2270 xf86ProcessCommonOptions(pInfo, pInfo->options);
2273 * We initialize pEvdev->tool to 1 so that device that doesn't use
2274 * proximity will still report events.
2278 device = xf86CheckStrOption(pInfo->options, "Device", NULL);
2280 xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name);
2281 xf86DeleteInput(pInfo, 0);
2286 pEvdev->device = device;
2288 xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
2290 pInfo->fd = open(device, O_RDWR | O_NONBLOCK, 0);
2291 } while (pInfo->fd < 0 && errno == EINTR);
2293 if (pInfo->fd < 0) {
2294 xf86Msg(X_ERROR, "Unable to open evdev device \"%s\".\n", device);
2295 xf86DeleteInput(pInfo, 0);
2300 /* Check major/minor of device node to avoid adding duplicate devices. */
2301 pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
2302 if (EvdevIsDuplicate(pInfo))
2304 xf86Msg(X_WARNING, "%s: device file already in use. Ignoring.\n",
2307 xf86DeleteInput(pInfo, 0);
2312 pEvdev->reopen_attempts = xf86SetIntOption(pInfo->options, "ReopenAttempts", 10);
2313 pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
2314 pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
2315 pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
2317 str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
2319 num_calibration = sscanf(str, "%d %d %d %d",
2320 &calibration[0], &calibration[1],
2321 &calibration[2], &calibration[3]);
2322 if (num_calibration == 4)
2323 EvdevSetCalibration(pInfo, num_calibration, calibration);
2326 "%s: Insufficient calibration factors (%d). Ignoring calibration\n",
2327 pInfo->name, num_calibration);
2330 str = xf86CheckStrOption(pInfo->options, "Resolution", NULL);
2332 num_resolution = sscanf(str, "%d %d %d %d",
2333 &resolution[0], &resolution[1],
2334 &resolution[2], &resolution[3]);
2335 if (num_resolution == 4)
2336 EvdevSetResolution(pInfo, num_resolution, resolution);
2339 "%s: Insufficient resolution factors (%d). Ignoring resolution\n",
2340 pInfo->name, num_resolution);
2343 /* Grabbing the event device stops in-kernel event forwarding. In other
2344 words, it disables rfkill and the "Macintosh mouse button emulation".
2345 Note that this needs a server that sets the console to RAW mode. */
2346 pEvdev->grabDevice = xf86CheckBoolOption(pInfo->options, "GrabDevice", 0);
2348 EvdevInitButtonMapping(pInfo);
2350 if (EvdevCacheCompare(pInfo, FALSE) ||
2351 EvdevProbe(pInfo)) {
2353 xf86DeleteInput(pInfo, 0);
2358 if(pEvdev->flags & EVDEV_RESOLUTION)
2360 EvdevSwapAxes(pEvdev);
2362 #ifdef _F_IGNORE_TSP_RESOLUTION_
2365 pEvdev->absinfo[ABS_X].maximum = 0;
2366 pEvdev->absinfo[ABS_X].minimum = 0;
2367 pEvdev->absinfo[ABS_Y].maximum = 0;
2368 pEvdev->absinfo[ABS_Y].minimum = 0;
2370 #endif//_F_IGNORE_TSP_RESOLUTION_
2372 EvdevAddDevice(pInfo);
2374 if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
2376 EvdevMBEmuPreInit(pInfo);
2377 EvdevWheelEmuPreInit(pInfo);
2378 EvdevDragLockPreInit(pInfo);
2381 memset(&pEvdev->pointer_confine_region, 0, sizeof(pEvdev->pointer_confine_region));
2391 _X_EXPORT InputDriverRec EVDEV = {
2402 EvdevUnplug(pointer p)
2407 EvdevPlug(pointer module,
2412 xf86AddInputDriver(&EVDEV, module, 0);
2416 static XF86ModuleVersionInfo EvdevVersionRec =
2422 XORG_VERSION_CURRENT,
2423 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
2430 _X_EXPORT XF86ModuleData evdevModuleData =
2438 /* Return an index value for a given button event code
2439 * returns 0 on non-button event.
2442 EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code)
2444 unsigned int button = 0;
2459 /* Treat BTN_[0-2] as LMR buttons on devices that do not advertise
2460 BTN_LEFT, BTN_MIDDLE, BTN_RIGHT.
2461 Otherwise, treat BTN_[0+n] as button 5+n.
2462 XXX: This causes duplicate mappings for BTN_0 + n and BTN_SIDE + n
2465 button = (TestBit(BTN_LEFT, pEvdev->key_bitmask)) ? 8 : 1;
2468 button = (TestBit(BTN_MIDDLE, pEvdev->key_bitmask)) ? 9 : 2;
2471 button = (TestBit(BTN_RIGHT, pEvdev->key_bitmask)) ? 10 : 3;
2474 /* FIXME: BTN_3.. and BTN_SIDE.. have the same button mapping */
2482 button = (code - BTN_0 + 5);
2490 button = (code - BTN_LEFT + 5);
2494 if ((code > BTN_TASK) && (code < KEY_OK)) {
2495 if (code < BTN_JOYSTICK) {
2496 if (code < BTN_MOUSE)
2497 button = (code - BTN_0 + 5);
2499 button = (code - BTN_LEFT + 5);
2504 if (button > EVDEV_MAXBUTTONS)
2510 #ifdef HAVE_PROPERTIES
2512 /* Aligned with linux/input.h.
2513 Note that there are holes in the ABS_ range, these are simply replaced with
2515 static char* abs_labels[] = {
2516 AXIS_LABEL_PROP_ABS_X, /* 0x00 */
2517 AXIS_LABEL_PROP_ABS_Y, /* 0x01 */
2518 AXIS_LABEL_PROP_ABS_Z, /* 0x02 */
2519 AXIS_LABEL_PROP_ABS_RX, /* 0x03 */
2520 AXIS_LABEL_PROP_ABS_RY, /* 0x04 */
2521 AXIS_LABEL_PROP_ABS_RZ, /* 0x05 */
2522 AXIS_LABEL_PROP_ABS_THROTTLE, /* 0x06 */
2523 AXIS_LABEL_PROP_ABS_RUDDER, /* 0x07 */
2524 AXIS_LABEL_PROP_ABS_WHEEL, /* 0x08 */
2525 AXIS_LABEL_PROP_ABS_GAS, /* 0x09 */
2526 AXIS_LABEL_PROP_ABS_BRAKE, /* 0x0a */
2527 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
2528 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
2529 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
2530 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
2531 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
2532 AXIS_LABEL_PROP_ABS_HAT0X, /* 0x10 */
2533 AXIS_LABEL_PROP_ABS_HAT0Y, /* 0x11 */
2534 AXIS_LABEL_PROP_ABS_HAT1X, /* 0x12 */
2535 AXIS_LABEL_PROP_ABS_HAT1Y, /* 0x13 */
2536 AXIS_LABEL_PROP_ABS_HAT2X, /* 0x14 */
2537 AXIS_LABEL_PROP_ABS_HAT2Y, /* 0x15 */
2538 AXIS_LABEL_PROP_ABS_HAT3X, /* 0x16 */
2539 AXIS_LABEL_PROP_ABS_HAT3Y, /* 0x17 */
2540 AXIS_LABEL_PROP_ABS_PRESSURE, /* 0x18 */
2541 AXIS_LABEL_PROP_ABS_DISTANCE, /* 0x19 */
2542 AXIS_LABEL_PROP_ABS_TILT_X, /* 0x1a */
2543 AXIS_LABEL_PROP_ABS_TILT_Y, /* 0x1b */
2544 AXIS_LABEL_PROP_ABS_TOOL_WIDTH, /* 0x1c */
2545 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
2546 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
2547 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
2548 AXIS_LABEL_PROP_ABS_VOLUME /* 0x20 */
2551 static char* rel_labels[] = {
2552 AXIS_LABEL_PROP_REL_X,
2553 AXIS_LABEL_PROP_REL_Y,
2554 AXIS_LABEL_PROP_REL_Z,
2555 AXIS_LABEL_PROP_REL_RX,
2556 AXIS_LABEL_PROP_REL_RY,
2557 AXIS_LABEL_PROP_REL_RZ,
2558 AXIS_LABEL_PROP_REL_HWHEEL,
2559 AXIS_LABEL_PROP_REL_DIAL,
2560 AXIS_LABEL_PROP_REL_WHEEL,
2561 AXIS_LABEL_PROP_REL_MISC
2564 static char* btn_labels[][16] = {
2565 { /* BTN_MISC group offset 0x100*/
2566 BTN_LABEL_PROP_BTN_0, /* 0x00 */
2567 BTN_LABEL_PROP_BTN_1, /* 0x01 */
2568 BTN_LABEL_PROP_BTN_2, /* 0x02 */
2569 BTN_LABEL_PROP_BTN_3, /* 0x03 */
2570 BTN_LABEL_PROP_BTN_4, /* 0x04 */
2571 BTN_LABEL_PROP_BTN_5, /* 0x05 */
2572 BTN_LABEL_PROP_BTN_6, /* 0x06 */
2573 BTN_LABEL_PROP_BTN_7, /* 0x07 */
2574 BTN_LABEL_PROP_BTN_8, /* 0x08 */
2575 BTN_LABEL_PROP_BTN_9 /* 0x09 */
2577 { /* BTN_MOUSE group offset 0x110 */
2578 BTN_LABEL_PROP_BTN_LEFT, /* 0x00 */
2579 BTN_LABEL_PROP_BTN_RIGHT, /* 0x01 */
2580 BTN_LABEL_PROP_BTN_MIDDLE, /* 0x02 */
2581 BTN_LABEL_PROP_BTN_SIDE, /* 0x03 */
2582 BTN_LABEL_PROP_BTN_EXTRA, /* 0x04 */
2583 BTN_LABEL_PROP_BTN_FORWARD, /* 0x05 */
2584 BTN_LABEL_PROP_BTN_BACK, /* 0x06 */
2585 BTN_LABEL_PROP_BTN_TASK /* 0x07 */
2587 { /* BTN_JOYSTICK group offset 0x120 */
2588 BTN_LABEL_PROP_BTN_TRIGGER, /* 0x00 */
2589 BTN_LABEL_PROP_BTN_THUMB, /* 0x01 */
2590 BTN_LABEL_PROP_BTN_THUMB2, /* 0x02 */
2591 BTN_LABEL_PROP_BTN_TOP, /* 0x03 */
2592 BTN_LABEL_PROP_BTN_TOP2, /* 0x04 */
2593 BTN_LABEL_PROP_BTN_PINKIE, /* 0x05 */
2594 BTN_LABEL_PROP_BTN_BASE, /* 0x06 */
2595 BTN_LABEL_PROP_BTN_BASE2, /* 0x07 */
2596 BTN_LABEL_PROP_BTN_BASE3, /* 0x08 */
2597 BTN_LABEL_PROP_BTN_BASE4, /* 0x09 */
2598 BTN_LABEL_PROP_BTN_BASE5, /* 0x0a */
2599 BTN_LABEL_PROP_BTN_BASE6, /* 0x0b */
2603 BTN_LABEL_PROP_BTN_DEAD /* 0x0f */
2605 { /* BTN_GAMEPAD group offset 0x130 */
2606 BTN_LABEL_PROP_BTN_A, /* 0x00 */
2607 BTN_LABEL_PROP_BTN_B, /* 0x01 */
2608 BTN_LABEL_PROP_BTN_C, /* 0x02 */
2609 BTN_LABEL_PROP_BTN_X, /* 0x03 */
2610 BTN_LABEL_PROP_BTN_Y, /* 0x04 */
2611 BTN_LABEL_PROP_BTN_Z, /* 0x05 */
2612 BTN_LABEL_PROP_BTN_TL, /* 0x06 */
2613 BTN_LABEL_PROP_BTN_TR, /* 0x07 */
2614 BTN_LABEL_PROP_BTN_TL2, /* 0x08 */
2615 BTN_LABEL_PROP_BTN_TR2, /* 0x09 */
2616 BTN_LABEL_PROP_BTN_SELECT, /* 0x0a */
2617 BTN_LABEL_PROP_BTN_START, /* 0x0b */
2618 BTN_LABEL_PROP_BTN_MODE, /* 0x0c */
2619 BTN_LABEL_PROP_BTN_THUMBL, /* 0x0d */
2620 BTN_LABEL_PROP_BTN_THUMBR /* 0x0e */
2622 { /* BTN_DIGI group offset 0x140 */
2623 BTN_LABEL_PROP_BTN_TOOL_PEN, /* 0x00 */
2624 BTN_LABEL_PROP_BTN_TOOL_RUBBER, /* 0x01 */
2625 BTN_LABEL_PROP_BTN_TOOL_BRUSH, /* 0x02 */
2626 BTN_LABEL_PROP_BTN_TOOL_PENCIL, /* 0x03 */
2627 BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH, /* 0x04 */
2628 BTN_LABEL_PROP_BTN_TOOL_FINGER, /* 0x05 */
2629 BTN_LABEL_PROP_BTN_TOOL_MOUSE, /* 0x06 */
2630 BTN_LABEL_PROP_BTN_TOOL_LENS, /* 0x07 */
2633 BTN_LABEL_PROP_BTN_TOUCH, /* 0x0a */
2634 BTN_LABEL_PROP_BTN_STYLUS, /* 0x0b */
2635 BTN_LABEL_PROP_BTN_STYLUS2, /* 0x0c */
2636 BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP, /* 0x0d */
2637 BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP /* 0x0e */
2639 { /* BTN_WHEEL group offset 0x150 */
2640 BTN_LABEL_PROP_BTN_GEAR_DOWN, /* 0x00 */
2641 BTN_LABEL_PROP_BTN_GEAR_UP /* 0x01 */
2645 #endif /* HAVE_LABELS */
2647 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
2656 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
2658 labels = abs_labels;
2659 labels_len = ArrayLength(abs_labels);
2660 misc_label = AXIS_LABEL_PROP_ABS_MISC;
2661 } else if ((pEvdev->flags & EVDEV_RELATIVE_EVENTS))
2663 labels = rel_labels;
2664 labels_len = ArrayLength(rel_labels);
2665 misc_label = AXIS_LABEL_PROP_REL_MISC;
2668 memset(atoms, 0, natoms * sizeof(Atom));
2670 /* Now fill the ones we know */
2671 for (axis = 0; axis < labels_len; axis++)
2673 if (pEvdev->axis_map[axis] == -1)
2676 atom = XIGetKnownProperty(labels[axis]);
2677 if (!atom) /* Should not happen */
2680 atoms[pEvdev->axis_map[axis]] = atom;
2685 static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
2691 /* First, make sure all atoms are initialized */
2692 atom = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN);
2693 for (button = 0; button < natoms; button++)
2694 atoms[button] = atom;
2696 for (button = BTN_MISC; button < BTN_JOYSTICK; button++)
2698 if (TestBit(button, pEvdev->key_bitmask))
2700 int group = (button % 0x100)/16;
2701 int idx = button - ((button/16) * 16);
2703 if (!btn_labels[group][idx])
2706 atom = XIGetKnownProperty(btn_labels[group][idx]);
2710 /* Props are 0-indexed, button numbers start with 1 */
2711 bmap = EvdevUtilButtonEventToButtonNumber(pEvdev, button) - 1;
2716 /* wheel buttons, hardcoded anyway */
2718 atoms[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
2720 atoms[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
2722 atoms[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
2724 atoms[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
2729 EvdevInitProperty(DeviceIntPtr dev)
2731 InputInfoPtr pInfo = dev->public.devicePrivate;
2732 EvdevPtr pEvdev = pInfo->private;
2736 #ifdef _F_EVDEV_CONFINE_REGION_
2737 int region[4] = { 0, };
2738 #endif//_F_EVDEV_CONFINE_REGION_
2740 prop_reopen = MakeAtom(EVDEV_PROP_REOPEN, strlen(EVDEV_PROP_REOPEN),
2743 reopen = pEvdev->reopen_attempts;
2744 rc = XIChangeDeviceProperty(dev, prop_reopen, XA_INTEGER, 8,
2745 PropModeReplace, 1, &reopen, FALSE);
2749 XISetDevicePropertyDeletable(dev, prop_reopen, FALSE);
2751 if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS))
2753 invert[0] = pEvdev->invert_x;
2754 invert[1] = pEvdev->invert_y;
2756 prop_invert = MakeAtom(EVDEV_PROP_INVERT_AXES, strlen(EVDEV_PROP_INVERT_AXES), TRUE);
2758 rc = XIChangeDeviceProperty(dev, prop_invert, XA_INTEGER, 8,
2764 XISetDevicePropertyDeletable(dev, prop_invert, FALSE);
2766 prop_calibration = MakeAtom(EVDEV_PROP_CALIBRATION,
2767 strlen(EVDEV_PROP_CALIBRATION), TRUE);
2768 if (pEvdev->flags & EVDEV_CALIBRATED) {
2771 calibration[0] = pEvdev->calibration.min_x;
2772 calibration[1] = pEvdev->calibration.max_x;
2773 calibration[2] = pEvdev->calibration.min_y;
2774 calibration[3] = pEvdev->calibration.max_y;
2776 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
2777 32, PropModeReplace, 4, calibration,
2779 } else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) {
2780 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
2781 32, PropModeReplace, 0, NULL,
2787 XISetDevicePropertyDeletable(dev, prop_calibration, FALSE);
2789 prop_swap = MakeAtom(EVDEV_PROP_SWAP_AXES,
2790 strlen(EVDEV_PROP_SWAP_AXES), TRUE);
2792 rc = XIChangeDeviceProperty(dev, prop_swap, XA_INTEGER, 8,
2793 PropModeReplace, 1, &pEvdev->swap_axes, FALSE);
2797 XISetDevicePropertyDeletable(dev, prop_swap, FALSE);
2800 /* Axis labelling */
2801 if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
2803 Atom atoms[pEvdev->num_vals];
2804 EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
2805 XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32,
2806 PropModeReplace, pEvdev->num_vals, atoms, FALSE);
2807 XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE);
2809 /* Button labelling */
2810 if ((pEvdev->num_buttons > 0) && (prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP)))
2812 Atom atoms[EVDEV_MAXBUTTONS];
2813 EvdevInitButtonLabels(pEvdev, EVDEV_MAXBUTTONS, atoms);
2814 XIChangeDeviceProperty(dev, prop_btn_label, XA_ATOM, 32,
2815 PropModeReplace, pEvdev->num_buttons, atoms, FALSE);
2816 XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE);
2818 #endif /* HAVE_LABELS */
2820 #ifdef _F_EVDEV_CONFINE_REGION_
2821 prop_confine_region = MakeAtom(EVDEV_PROP_CONFINE_REGION,
2822 strlen(EVDEV_PROP_CONFINE_REGION), TRUE);
2823 rc = XIChangeDeviceProperty(dev, prop_confine_region, XA_INTEGER,
2824 32, PropModeReplace, 4, region, FALSE);
2828 #endif /* _F_EVDEV_CONFINE_REGION_ */
2833 static void EvdevSwapAxes(EvdevPtr pEvdev)
2835 if(pEvdev->swap_axes)
2837 pEvdev->absinfo[ABS_Y].maximum = pEvdev->resolution.min_x;
2838 pEvdev->absinfo[ABS_Y].minimum = pEvdev->resolution.max_x;
2839 pEvdev->absinfo[ABS_X].maximum = pEvdev->resolution.min_y;
2840 pEvdev->absinfo[ABS_X].minimum = pEvdev->resolution.max_y;
2844 pEvdev->absinfo[ABS_X].maximum = pEvdev->resolution.min_x;
2845 pEvdev->absinfo[ABS_X].minimum = pEvdev->resolution.max_x;
2846 pEvdev->absinfo[ABS_Y].maximum = pEvdev->resolution.min_y;
2847 pEvdev->absinfo[ABS_Y].minimum = pEvdev->resolution.max_y;
2852 EvdevSetResolution(InputInfoPtr pInfo, int num_resolution, int resolution[4])
2854 EvdevPtr pEvdev = pInfo->private;
2856 if (num_resolution == 0) {
2857 pEvdev->flags &= ~EVDEV_RESOLUTION;
2858 pEvdev->resolution.min_x = 0;
2859 pEvdev->resolution.max_x = 0;
2860 pEvdev->resolution.min_y = 0;
2861 pEvdev->resolution.max_y = 0;
2862 } else if (num_resolution == 4) {
2863 pEvdev->flags |= EVDEV_RESOLUTION;
2864 pEvdev->resolution.min_x = resolution[0];
2865 pEvdev->resolution.max_x = resolution[1];
2866 pEvdev->resolution.min_y = resolution[2];
2867 pEvdev->resolution.max_y = resolution[3];
2872 EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
2875 InputInfoPtr pInfo = dev->public.devicePrivate;
2876 EvdevPtr pEvdev = pInfo->private;
2878 if (atom == prop_invert)
2881 if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
2886 data = (BOOL*)val->data;
2887 pEvdev->invert_x = data[0];
2888 pEvdev->invert_y = data[1];
2890 } else if (atom == prop_reopen)
2892 if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
2896 pEvdev->reopen_attempts = *((CARD8*)val->data);
2897 } else if (atom == prop_calibration)
2899 if (val->format != 32 || val->type != XA_INTEGER)
2901 if (val->size != 4 && val->size != 0)
2905 EvdevSetCalibration(pInfo, val->size, val->data);
2906 } else if (atom == prop_swap)
2908 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
2912 pEvdev->swap_axes = *((BOOL*)val->data);
2913 EvdevSwapAxes(pEvdev);
2914 } else if (atom == prop_axis_label || atom == prop_btn_label)
2915 return BadAccess; /* Axis/Button labels can't be changed */
2916 #ifdef _F_EVDEV_CONFINE_REGION_
2917 else if (atom == prop_confine_region)
2919 if (val->format != 32 || val->type != XA_INTEGER)
2921 if (val->size != 1 && val->size != 5)
2925 EvdevSetConfineRegion(pInfo, val->size, val->data);
2927 #endif /* _F_EVDEV_CONFINE_REGION_ */