3 * xserver-xorg-input-evdev
5 * Contact: Sung-Jin Park <sj76.park@samsung.com>
6 * Sangjin LEE <lsj119@samsung.com>
8 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
9 * Copyright © 2004-2008 Red Hat, Inc.
11 * Permission to use, copy, modify, distribute, and sell this software
12 * and its documentation for any purpose is hereby granted without
13 * fee, provided that the above copyright notice appear in all copies
14 * and that both that copyright notice and this permission notice
15 * appear in supporting documentation, and that the name of Red Hat
16 * not be used in advertising or publicity pertaining to distribution
17 * of the software without specific, written prior permission. Red
18 * Hat makes no representations about the suitability of this software
19 * for any purpose. It is provided "as is" without express or implied
22 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
23 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
24 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
25 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
26 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
27 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
28 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 * Kristian Høgsberg (krh@redhat.com)
32 * Adam Jackson (ajax@redhat.com)
33 * Peter Hutterer (peter.hutterer@redhat.com)
34 * Oliver McFadden (oliver.mcfadden@nokia.com)
43 #include <X11/keysym.h>
44 #include <X11/extensions/XI.h>
46 #include <linux/version.h>
54 #include <xf86Xinput.h>
56 #include <xorgVersion.h>
59 #include <X11/Xatom.h>
60 #include <evdev-properties.h>
61 #include <xserver-properties.h>
63 #ifdef _F_EVDEV_CONFINE_REGION_
64 #include <xorg/mipointrst.h>
66 #define MIPOINTER(dev) \
67 ((!IsMaster(dev) && !dev->master) ? \
68 (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
69 (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
71 #endif /* _F_EVDEV_CONFINE_REGION_ */
73 #ifndef XI_PROP_PRODUCT_ID
74 #define XI_PROP_PRODUCT_ID "Device Product ID"
77 #ifndef XI_PROP_VIRTUAL_DEVICE
78 #define XI_PROP_VIRTUAL_DEVICE "Virtual Device"
81 #ifndef XI_PROP_DEVICE_TYPE
82 #define XI_PROP_DEVICE_TYPE "Device Type"
85 /* removed from server, purge when dropping support for server 1.10 */
86 #define XI86_SEND_DRAG_EVENTS 0x08
89 #include <inputstr.h> /* for MAX_DEVICES */
90 #define MAXDEVICES MAX_DEVICES
93 #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
96 #define GLYPHS_PER_KEY 2
97 #define AltMask Mod1Mask
98 #define NumLockMask Mod2Mask
99 #define AltLangMask Mod3Mask
100 #define KanaMask Mod4Mask
101 #define ScrollLockMask Mod5Mask
107 #define COMPOSEFLAG 16
110 #define ABS_MT_SLOT 0x2f
113 #ifndef ABS_MT_TRACKING_ID
114 #define ABS_MT_TRACKING_ID 0x39
117 static char *evdevDefaults[] = {
124 /* Any of those triggers a proximity event */
125 static int proximity_bits[] = {
136 static int EvdevOn(DeviceIntPtr);
137 static int EvdevCache(InputInfoPtr pInfo);
138 static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
139 static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode);
140 static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab);
141 static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
142 static int EvdevOpenDevice(InputInfoPtr pInfo);
144 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int mode, int natoms, Atom *atoms);
145 static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
146 static void EvdevInitProperty(DeviceIntPtr dev);
147 static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
148 XIPropertyValuePtr val, BOOL checkonly);
149 #ifdef _F_GESTURE_EXTENSION_
150 extern void mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e);
151 static void EvdevMTSync(InputInfoPtr pInfo, MTSyncType sync);
152 static BOOL EvdevMTStatusGet(InputInfoPtr pInfo, MTSyncType sync);
153 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
154 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
155 static void EvdevSetTransformMatrix(InputInfoPtr pInfo, int num_transform, float *tmatrix);
156 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
157 #ifdef _F_EVDEV_CONFINE_REGION_
158 Bool IsMaster(DeviceIntPtr dev);
159 DeviceIntPtr GetPairedDevice(DeviceIntPtr dev);
160 DeviceIntPtr GetMaster(DeviceIntPtr dev, int which);
161 DeviceIntPtr GetMasterPointerFromId(int deviceid);
162 static void EvdevHookPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, BoxPtr pHotBox, BoxPtr pTopLeftBox);
163 static void EvdevHookPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox);
164 static void EvdevSetCursorLimits(InputInfoPtr pInfo, int region[6], int isSet);
165 static void EvdevSetConfineRegion(InputInfoPtr pInfo, int num_item, int region[6]);
166 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
167 static CARD32 EvdevRelativeMoveTimer(OsTimerPtr timer, CARD32 time, pointer arg);
168 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
170 static Atom prop_confine_region = 0;
171 #endif /* _F_EVDEV_CONFINE_REGION_ */
172 static Atom prop_product_id;
173 static Atom prop_invert;
174 static Atom prop_calibration;
175 static Atom prop_swap;
176 static Atom prop_axis_label;
177 static Atom prop_btn_label;
178 static Atom prop_device;
179 static Atom prop_virtual;
180 #ifdef _F_ENABLE_DEVICE_TYPE_PROP_
181 static Atom prop_device_type;
182 #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
183 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
184 static Atom prop_relative_move_status;
185 static Atom prop_relative_move_ack;
186 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
187 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
188 static Atom prop_transform;
189 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
191 #ifdef _F_USE_DEFAULT_XKB_RULES_
192 static Atom prop_xkb_rules = None;
193 #endif //_F_USE_DEFAULT_XKB_RULES_
195 /* All devices the evdev driver has allocated and knows about.
196 * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
197 * cannot be used by evdev, leaving us with a space of 2 at the end. */
198 static EvdevPtr evdev_devices[MAXDEVICES] = {NULL};
200 #ifdef _F_REMAP_KEYS_
202 remapKey(EvdevPtr ev, uint16_t code)
204 uint8_t slice=code/256;
205 uint8_t offs=code%256;
207 if (!ev->keyremap) return code;
208 if (!(ev->keyremap->sl[slice])) return code;
209 if (!(ev->keyremap->sl[slice]->cd[offs])) return code;
210 return ev->keyremap->sl[slice]->cd[offs];
214 addRemap(EvdevPtr ev,uint16_t code,uint8_t value)
216 uint8_t slice=code/256;
217 uint8_t offs=code%256;
220 ev->keyremap=(EvdevKeyRemapPtr)calloc(sizeof(EvdevKeyRemap),1);
222 if (!ev->keyremap->sl[slice]) {
223 ev->keyremap->sl[slice]=(EvdevKeyRemapSlice*)calloc(sizeof(EvdevKeyRemapSlice),1);
225 ev->keyremap->sl[slice]->cd[offs]=value;
229 freeRemap(EvdevPtr ev)
232 if (!ev->keyremap) return;
233 for (slice=0;slice<256;++slice) {
234 if (!ev->keyremap->sl[slice]) continue;
235 free(ev->keyremap->sl[slice]);
240 #endif //_F_REMAP_KEYS_
242 static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode)
247 pInfo = device->public.devicePrivate;
248 pEvdev = pInfo->private;
250 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
252 if (mode == Relative)
260 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
264 pEvdev->flags |= EVDEV_RELATIVE_MODE;
274 static size_t EvdevCountBits(unsigned long *array, size_t nlongs)
279 for (i = 0; i < nlongs; i++) {
280 unsigned long x = array[i];
291 static inline int EvdevBitIsSet(const unsigned long *array, int bit)
293 return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
296 static inline void EvdevSetBit(unsigned long *array, int bit)
298 array[bit / LONG_BITS] |= (1LL << (bit % LONG_BITS));
302 EvdevGetMajorMinor(InputInfoPtr pInfo)
306 if (fstat(pInfo->fd, &st) == -1)
308 xf86IDrvMsg(pInfo, X_ERROR, "stat failed (%s). cannot check for duplicates.\n",
317 * Return TRUE if one of the devices we know about has the same min/maj
321 EvdevIsDuplicate(InputInfoPtr pInfo)
323 EvdevPtr pEvdev = pInfo->private;
324 EvdevPtr* dev = evdev_devices;
330 if ((*dev) != pEvdev &&
332 (*dev)->min_maj == pEvdev->min_maj)
341 * Add to internal device list.
344 EvdevAddDevice(InputInfoPtr pInfo)
346 EvdevPtr pEvdev = pInfo->private;
347 EvdevPtr* dev = evdev_devices;
356 * Remove from internal device list.
359 EvdevRemoveDevice(InputInfoPtr pInfo)
361 EvdevPtr pEvdev = pInfo->private;
362 EvdevPtr *dev = evdev_devices;
370 memmove(dev, dev + 1,
371 sizeof(evdev_devices) - (count * sizeof(EvdevPtr)));
380 SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
384 if ((s = xf86SetStrOption(pInfo->options, name, NULL))) {
395 EvdevDeviceIsVirtual(const char* devicenode)
397 struct udev *udev = NULL;
398 struct udev_device *device = NULL;
407 if (stat(devicenode, &st) < 0) {
408 ErrorF("Failed to get (%s)'s status (stat)\n", devicenode);
411 device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
417 devpath = udev_device_get_devpath(device);
421 if (strstr(devpath, "LNXSYSTM"))
425 udev_device_unref(device);
430 #ifndef HAVE_SMOOTH_SCROLLING
431 static int wheel_up_button = 4;
432 static int wheel_down_button = 5;
433 static int wheel_left_button = 6;
434 static int wheel_right_button = 7;
437 #ifdef _F_REMAP_KEYS_
439 SetRemapOption(InputInfoPtr pInfo,const char* name)
442 unsigned long int code,value;
444 EvdevPtr ev = pInfo->private;
446 s = xf86SetStrOption(pInfo->options, name, NULL);
454 while (sscanf(c," %li = %li %n",&code,&value,&consumed) > 1) {
456 if (code < 0 || code > 65535L) {
457 xf86Msg(X_ERROR,"%s: input code %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,code);
460 if (value < MIN_KEYCODE || value > 255) {
461 xf86Msg(X_ERROR,"%s: output value %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,value);
464 xf86Msg(X_INFO,"%s: remapping %ld into %ld.\n",pInfo->name,code,value);
465 addRemap(ev,code,value-MIN_KEYCODE);
469 xf86Msg(X_ERROR, "%s: invalid input for option \"event_key_remap\" starting at '%s', ignoring.\n",
473 #endif //_F_REMAP_KEYS_
476 EvdevNextInQueue(InputInfoPtr pInfo)
478 EvdevPtr pEvdev = pInfo->private;
480 if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
482 xf86IDrvMsg(pInfo, X_NONE, "dropping event due to full queue!\n");
487 return &pEvdev->queue[pEvdev->num_queue - 1];
491 EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
493 #ifdef _F_REMAP_KEYS_
494 int code = remapKey((EvdevPtr)(pInfo->private),ev->code) + MIN_KEYCODE;
495 #else //_F_REMAP_KEYS_
496 int code = ev->code + MIN_KEYCODE;
497 #endif //_F_REMAP_KEYS_
498 EventQueuePtr pQueue;
500 /* Filter all repeated events from device.
501 We'll do softrepeat in the server, but only since 1.6 */
505 if ((pQueue = EvdevNextInQueue(pInfo)))
507 pQueue->type = EV_QUEUE_KEY;
508 pQueue->detail.key = code;
514 EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
516 EventQueuePtr pQueue;
518 if ((pQueue = EvdevNextInQueue(pInfo)))
520 pQueue->type = EV_QUEUE_BTN;
521 pQueue->detail.key = button;
527 EvdevQueueProximityEvent(InputInfoPtr pInfo, int value)
529 EventQueuePtr pQueue;
530 if ((pQueue = EvdevNextInQueue(pInfo)))
532 pQueue->type = EV_QUEUE_PROXIMITY;
533 pQueue->detail.key = 0;
540 EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask,
543 EventQueuePtr pQueue;
544 if ((pQueue = EvdevNextInQueue(pInfo)))
546 pQueue->type = EV_QUEUE_TOUCH;
547 pQueue->detail.touch = touch;
548 valuator_mask_copy(pQueue->touchMask, mask);
549 pQueue->val = evtype;
555 * Post button event right here, right now.
556 * Interface for MB emulation since these need to post immediately.
559 EvdevPostButtonEvent(InputInfoPtr pInfo, int button, enum ButtonAction act)
561 xf86PostButtonEvent(pInfo->dev, Relative, button,
562 (act == BUTTON_PRESS) ? 1 : 0, 0, 0);
566 EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
570 for (i = 0; i < count; i++) {
571 EvdevQueueButtonEvent(pInfo, button, 1);
572 EvdevQueueButtonEvent(pInfo, button, 0);
576 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
578 EvdevMappingGamepadAbsToKey(InputInfoPtr pInfo, struct input_event *ev)
580 EvdevPtr pEvdev = pInfo->private;
582 if (pEvdev->support_directional_key == FALSE)
585 if (ev->type != EV_ABS)
587 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid evtype(%d)\n", ev->type);
591 if (ev->code == ABS_HAT0X)
597 ev->code = KEY_RIGHT;
598 ev->value = EVDEV_PRESS;
599 pEvdev->pre_hatx = 1;
600 EvdevProcessEvent(pInfo, ev);
605 ev->value = EVDEV_PRESS;
606 pEvdev->pre_hatx = -1;
607 EvdevProcessEvent(pInfo, ev);
611 ev->code = ( (pEvdev->pre_hatx == 1)? KEY_RIGHT : KEY_LEFT);
612 ev->value = EVDEV_RELEASE;
613 pEvdev->pre_hatx = 0;
614 EvdevProcessEvent(pInfo, ev);
617 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid value\n");
622 else if(ev->code == ABS_HAT0Y)
629 ev->value = EVDEV_PRESS;
630 pEvdev->pre_haty = 1;
631 EvdevProcessEvent(pInfo, ev);
636 ev->value = EVDEV_PRESS;
637 pEvdev->pre_haty = -1;
638 EvdevProcessEvent(pInfo, ev);
642 ev->code = ( (pEvdev->pre_haty == 1)? KEY_DOWN : KEY_UP);
643 ev->value = EVDEV_RELEASE;
644 pEvdev->pre_haty = 0;
645 EvdevProcessEvent(pInfo, ev);
648 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid value\n");
653 else if(ev->code == ABS_X)
660 ev->value = EVDEV_PRESS;
662 EvdevProcessEvent(pInfo, ev);
665 if( pEvdev->pre_x == 255 || pEvdev->pre_x == 0 )
668 ev->code = ( (pEvdev->pre_x == 255)? KEY_RIGHT : KEY_LEFT);
669 ev->value = EVDEV_RELEASE;
671 EvdevProcessEvent(pInfo, ev);
676 ev->code = KEY_RIGHT;
677 ev->value = EVDEV_PRESS;
679 EvdevProcessEvent(pInfo, ev);
682 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid value\n");
687 else if(ev->code == ABS_Y)
694 ev->value = EVDEV_PRESS;
696 EvdevProcessEvent(pInfo, ev);
699 if( pEvdev->pre_y == 255 || pEvdev->pre_y == 0 )
702 ev->code = ( (pEvdev->pre_y == 255)? KEY_DOWN : KEY_UP);
703 ev->value = EVDEV_RELEASE;
705 EvdevProcessEvent(pInfo, ev);
711 ev->value = EVDEV_PRESS;
713 EvdevProcessEvent(pInfo, ev);
716 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid value\n");
724 EvdevMappingGamepadKeyToKey(InputInfoPtr pInfo, struct input_event *ev)
726 EvdevPtr pEvdev = pInfo->private;
727 if(ev->type != EV_KEY)
729 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid type (%d)\n", ev->type);
732 if(ev->code == BTN_A)
734 if (pEvdev->keycode_btnA == 0)
736 ev->code = pEvdev->keycode_btnA;
743 ev->code = pEvdev->keycode_btnA;
744 ev->value = EVDEV_PRESS;
748 ev->code = pEvdev->keycode_btnA;
749 ev->value = EVDEV_RELEASE;
752 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
757 else if(ev->code == BTN_B)
759 if (pEvdev->keycode_btnB == 0)
761 ev->code = pEvdev->keycode_btnB;
768 ev->code = pEvdev->keycode_btnB;
769 ev->value = EVDEV_PRESS;
773 ev->code = pEvdev->keycode_btnB;
774 ev->value = EVDEV_RELEASE;
777 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
782 else if(ev->code == BTN_SELECT)
784 if (pEvdev->keycode_btnSelect == 0)
786 ev->code = pEvdev->keycode_btnSelect;
793 ev->code = pEvdev->keycode_btnSelect;
794 ev->value = EVDEV_PRESS;
798 ev->code = pEvdev->keycode_btnSelect;
799 ev->value = EVDEV_RELEASE;
802 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
807 else if(ev->code == BTN_START)
809 if (pEvdev->keycode_btnStart == 0)
811 ev->code = pEvdev->keycode_btnStart;
818 ev->code = pEvdev->keycode_btnStart;
819 ev->value = EVDEV_PRESS;
823 ev->code = pEvdev->keycode_btnStart;
824 ev->value = EVDEV_RELEASE;
827 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
832 else if(ev->code == 319)
834 if (pEvdev->keycode_btnPlay== 0)
836 ev->code = pEvdev->keycode_btnPlay;
843 ev->code = pEvdev->keycode_btnPlay;
844 ev->value = EVDEV_PRESS;
848 ev->code = pEvdev->keycode_btnPlay;
849 ev->value = EVDEV_RELEASE;
852 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
857 else if(ev->code == BTN_X)
859 if (pEvdev->keycode_btnX == 0)
861 ev->code = pEvdev->keycode_btnX;
868 ev->code = pEvdev->keycode_btnX;
869 ev->value = EVDEV_PRESS;
873 ev->code = pEvdev->keycode_btnX;
874 ev->value = EVDEV_RELEASE;
877 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
882 else if(ev->code == BTN_Y)
884 if (pEvdev->keycode_btnY == 0)
886 ev->code = pEvdev->keycode_btnY;
893 ev->code = pEvdev->keycode_btnY;
894 ev->value = EVDEV_PRESS;
898 ev->code = pEvdev->keycode_btnY;
899 ev->value = EVDEV_RELEASE;
902 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
907 else if(ev->code == BTN_TL)
909 if (pEvdev->keycode_btnTL== 0)
911 ev->code = pEvdev->keycode_btnTL;
918 ev->code = pEvdev->keycode_btnTL;
919 ev->value = EVDEV_PRESS;
923 ev->code = pEvdev->keycode_btnTL;
924 ev->value = EVDEV_RELEASE;
927 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
932 else if(ev->code == BTN_TR)
934 if (pEvdev->keycode_btnTR == 0)
936 ev->code = pEvdev->keycode_btnTR;
943 ev->code = pEvdev->keycode_btnTR;
944 ev->value = EVDEV_PRESS;
948 ev->code = pEvdev->keycode_btnTR;
949 ev->value = EVDEV_RELEASE;
952 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
958 #endif//_F_EVDEV_SUPPORT_GAMEPAD
961 * Take the valuators and process them accordingly.
964 EvdevProcessValuators(InputInfoPtr pInfo)
967 EvdevPtr pEvdev = pInfo->private;
968 int *delta = pEvdev->delta;
970 /* convert to relative motion for touchpads */
971 if (pEvdev->abs_queued && (pEvdev->flags & EVDEV_RELATIVE_MODE)) {
972 if (pEvdev->in_proximity) {
973 if (valuator_mask_isset(pEvdev->vals, 0))
975 if (valuator_mask_isset(pEvdev->old_vals, 0))
976 delta[REL_X] = valuator_mask_get(pEvdev->vals, 0) -
977 valuator_mask_get(pEvdev->old_vals, 0);
978 valuator_mask_set(pEvdev->old_vals, 0,
979 valuator_mask_get(pEvdev->vals, 0));
981 if (valuator_mask_isset(pEvdev->vals, 1))
983 if (valuator_mask_isset(pEvdev->old_vals, 1))
984 delta[REL_Y] = valuator_mask_get(pEvdev->vals, 1) -
985 valuator_mask_get(pEvdev->old_vals, 1);
986 valuator_mask_set(pEvdev->old_vals, 1,
987 valuator_mask_get(pEvdev->vals, 1));
990 valuator_mask_zero(pEvdev->old_vals);
992 valuator_mask_zero(pEvdev->vals);
993 pEvdev->abs_queued = 0;
994 pEvdev->rel_queued = 1;
997 if (pEvdev->rel_queued) {
1000 if (pEvdev->swap_axes) {
1001 tmp = pEvdev->delta[REL_X];
1002 pEvdev->delta[REL_X] = pEvdev->delta[REL_Y];
1003 pEvdev->delta[REL_Y] = tmp;
1004 if (pEvdev->delta[REL_X] == 0)
1005 valuator_mask_unset(pEvdev->vals, REL_X);
1006 if (pEvdev->delta[REL_Y] == 0)
1007 valuator_mask_unset(pEvdev->vals, REL_Y);
1009 if (pEvdev->invert_x)
1010 pEvdev->delta[REL_X] *= -1;
1011 if (pEvdev->invert_y)
1012 pEvdev->delta[REL_Y] *= -1;
1015 Evdev3BEmuProcessRelMotion(pInfo,
1016 pEvdev->delta[REL_X],
1017 pEvdev->delta[REL_Y]);
1019 for (i = 0; i < REL_CNT; i++)
1021 int map = pEvdev->axis_map[i];
1022 if (pEvdev->delta[i] && map != -1)
1023 valuator_mask_set(pEvdev->vals, map, pEvdev->delta[i]);
1027 * Some devices only generate valid abs coords when BTN_TOOL_PEN is
1028 * pressed. On wacom tablets, this means that the pen is in
1029 * proximity of the tablet. After the pen is removed, BTN_TOOL_PEN is
1030 * released, and a (0, 0) absolute event is generated. Checking
1031 * pEvdev->in_proximity here lets us ignore that event. pEvdev is
1032 * initialized to 1 so devices that don't use this scheme still
1035 else if (pEvdev->abs_queued && pEvdev->in_proximity) {
1038 if (pEvdev->swap_axes) {
1039 int swapped_isset[2] = {0, 0};
1040 int swapped_values[2];
1042 for(i = 0; i <= 1; i++)
1043 if (valuator_mask_isset(pEvdev->vals, i)) {
1044 swapped_isset[1 - i] = 1;
1045 swapped_values[1 - i] =
1046 xf86ScaleAxis(valuator_mask_get(pEvdev->vals, i),
1047 pEvdev->absinfo[1 - i].maximum,
1048 pEvdev->absinfo[1 - i].minimum,
1049 pEvdev->absinfo[i].maximum,
1050 pEvdev->absinfo[i].minimum);
1053 for (i = 0; i <= 1; i++)
1054 if (swapped_isset[i])
1055 valuator_mask_set(pEvdev->vals, i, swapped_values[i]);
1057 valuator_mask_unset(pEvdev->vals, i);
1060 for (i = 0; i <= 1; i++) {
1065 if (!valuator_mask_isset(pEvdev->vals, i))
1068 val = valuator_mask_get(pEvdev->vals, i);
1071 calib_min = pEvdev->calibration.min_x;
1072 calib_max = pEvdev->calibration.max_x;
1074 calib_min = pEvdev->calibration.min_y;
1075 calib_max = pEvdev->calibration.max_y;
1078 if (pEvdev->flags & EVDEV_CALIBRATED)
1079 val = xf86ScaleAxis(val, pEvdev->absinfo[i].maximum,
1080 pEvdev->absinfo[i].minimum, calib_max,
1083 if ((i == 0 && pEvdev->invert_x) || (i == 1 && pEvdev->invert_y))
1084 val = (pEvdev->absinfo[i].maximum - val +
1085 pEvdev->absinfo[i].minimum);
1087 valuator_mask_set(pEvdev->vals, i, val);
1089 Evdev3BEmuProcessAbsMotion(pInfo, pEvdev->vals);
1094 EvdevProcessProximityEvent(InputInfoPtr pInfo, struct input_event *ev)
1096 EvdevPtr pEvdev = pInfo->private;
1098 if (!pEvdev->use_proximity)
1101 pEvdev->prox_queued = 1;
1103 EvdevQueueProximityEvent(pInfo, ev->value);
1107 * Proximity handling is rather weird because of tablet-specific issues.
1108 * Some tablets, notably Wacoms, send a 0/0 coordinate in the same EV_SYN as
1109 * the out-of-proximity notify. We need to ignore those, hence we only
1110 * actually post valuator events when we're in proximity.
1112 * Other tablets send the x/y coordinates, then EV_SYN, then the proximity
1113 * event. For those, we need to remember x/y to post it when the proximity
1116 * If we're not in proximity and we get valuator events, remember that, they
1117 * won't be posted though. If we move into proximity without valuators, use
1118 * the last ones we got and let the rest of the code post them.
1121 EvdevProcessProximityState(InputInfoPtr pInfo)
1123 EvdevPtr pEvdev = pInfo->private;
1127 /* Does this device have any proximity axes? */
1131 /* no proximity change in the queue */
1132 if (!pEvdev->prox_queued)
1134 if (pEvdev->abs_queued && !pEvdev->in_proximity)
1135 for (i = 0; i < valuator_mask_size(pEvdev->vals); i++)
1136 if (valuator_mask_isset(pEvdev->vals, i))
1137 valuator_mask_set(pEvdev->prox, i,
1138 valuator_mask_get(pEvdev->vals, i));
1142 for (i = 0; i < pEvdev->num_queue; i++)
1144 if (pEvdev->queue[i].type == EV_QUEUE_PROXIMITY)
1146 prox_state = pEvdev->queue[i].val;
1151 if ((prox_state && !pEvdev->in_proximity) ||
1152 (!prox_state && pEvdev->in_proximity))
1154 /* We're about to go into/out of proximity but have no abs events
1155 * within the EV_SYN. Use the last coordinates we have. */
1156 for (i = 0; i < valuator_mask_size(pEvdev->prox); i++)
1157 if (!valuator_mask_isset(pEvdev->vals, i) &&
1158 valuator_mask_isset(pEvdev->prox, i))
1159 valuator_mask_set(pEvdev->vals, i,
1160 valuator_mask_get(pEvdev->prox, i));
1161 valuator_mask_zero(pEvdev->prox);
1163 pEvdev->abs_queued = valuator_mask_size(pEvdev->vals);
1166 pEvdev->in_proximity = prox_state;
1171 * Take a button input event and process it accordingly.
1174 EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
1176 unsigned int button;
1178 EvdevPtr pEvdev = pInfo->private;
1180 button = EvdevUtilButtonEventToButtonNumber(pEvdev, ev->code);
1182 /* Get the signed value, earlier kernels had this as unsigned */
1185 /* Handle drag lock */
1186 if (EvdevDragLockFilterEvent(pInfo, button, value))
1189 if (EvdevWheelEmuFilterButton(pInfo, button, value))
1192 if (EvdevMBEmuFilterEvent(pInfo, button, value))
1196 EvdevQueueButtonEvent(pInfo, button, value);
1198 EvdevQueueKbdEvent(pInfo, ev, value);
1202 * Take the relative motion input event and process it accordingly.
1205 EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
1208 EvdevPtr pEvdev = pInfo->private;
1211 /* Get the signed value, earlier kernels had this as unsigned */
1215 #ifndef HAVE_SMOOTH_SCROLLING
1218 EvdevQueueButtonClicks(pInfo, wheel_up_button, value);
1220 EvdevQueueButtonClicks(pInfo, wheel_down_button, -value);
1226 EvdevQueueButtonClicks(pInfo, wheel_right_button, value);
1228 EvdevQueueButtonClicks(pInfo, wheel_left_button, -value);
1230 /* We don't post wheel events as axis motion. */
1233 /* Ignore EV_REL events if we never set up for them. */
1234 if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS))
1237 /* Handle mouse wheel emulation */
1238 if (EvdevWheelEmuFilterMotion(pInfo, ev))
1241 pEvdev->rel_queued = 1;
1242 pEvdev->delta[ev->code] += value;
1243 map = pEvdev->axis_map[ev->code];
1244 valuator_mask_set(pEvdev->vals, map, value);
1251 EvdevProcessTouch(InputInfoPtr pInfo)
1253 EvdevPtr pEvdev = pInfo->private;
1256 if (pEvdev->cur_slot < 0 || !pEvdev->mt_mask)
1259 /* If the ABS_MT_SLOT is the first event we get after EV_SYN, skip this */
1260 if (pEvdev->slot_state == SLOTSTATE_EMPTY)
1263 if (pEvdev->slot_state == SLOTSTATE_CLOSE)
1265 else if (pEvdev->slot_state == SLOTSTATE_OPEN)
1266 type = XI_TouchBegin;
1268 type = XI_TouchUpdate;
1271 EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, type);
1273 pEvdev->slot_state = SLOTSTATE_EMPTY;
1275 valuator_mask_zero(pEvdev->mt_mask);
1279 num_slots(EvdevPtr pEvdev)
1281 int value = pEvdev->absinfo[ABS_MT_SLOT].maximum -
1282 pEvdev->absinfo[ABS_MT_SLOT].minimum + 1;
1284 /* If we don't know how many slots there are, assume at least 10 */
1285 return value > 1 ? value : 10;
1289 last_mt_vals_slot(EvdevPtr pEvdev)
1291 int value = pEvdev->cur_slot - pEvdev->absinfo[ABS_MT_SLOT].minimum;
1293 return value < num_slots(pEvdev) ? value : -1;
1297 EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
1299 EvdevPtr pEvdev = pInfo->private;
1302 if (ev->code == ABS_MT_SLOT) {
1303 EvdevProcessTouch(pInfo);
1304 pEvdev->cur_slot = ev->value;
1307 int slot_index = last_mt_vals_slot(pEvdev);
1309 if (pEvdev->slot_state == SLOTSTATE_EMPTY)
1310 pEvdev->slot_state = SLOTSTATE_UPDATE;
1311 if (ev->code == ABS_MT_TRACKING_ID) {
1312 if (ev->value >= 0) {
1313 pEvdev->slot_state = SLOTSTATE_OPEN;
1315 if (slot_index >= 0)
1316 valuator_mask_copy(pEvdev->mt_mask,
1317 pEvdev->last_mt_vals[slot_index]);
1319 xf86IDrvMsg(pInfo, X_WARNING,
1320 "Attempted to copy values from out-of-range "
1321 "slot, touch events may be incorrect.\n");
1323 pEvdev->slot_state = SLOTSTATE_CLOSE;
1325 map = pEvdev->axis_map[ev->code];
1326 valuator_mask_set(pEvdev->mt_mask, map, ev->value);
1327 if (slot_index >= 0)
1328 valuator_mask_set(pEvdev->last_mt_vals[slot_index], map,
1334 #define EvdevProcessTouch(pInfo)
1335 #define EvdevProcessTouchEvent(pInfo, ev)
1336 #endif /* MULTITOUCH */
1339 * Take the absolute motion input event and process it accordingly.
1342 EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
1345 EvdevPtr pEvdev = pInfo->private;
1348 /* Get the signed value, earlier kernels had this as unsigned */
1350 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
1351 if(pEvdev->flags & EVDEV_GAMEPAD)
1353 EvdevMappingGamepadAbsToKey(pInfo, ev);
1356 #endif//_F_EVDEV_SUPPORT_GAMEPAD
1358 /* Ignore EV_ABS events if we never set up for them. */
1359 if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
1362 if (ev->code > ABS_MAX)
1365 if (EvdevWheelEmuFilterMotion(pInfo, ev))
1368 if (ev->code >= ABS_MT_SLOT) {
1369 EvdevProcessTouchEvent(pInfo, ev);
1370 pEvdev->abs_queued = 1;
1371 } else if (!pEvdev->mt_mask) {
1372 map = pEvdev->axis_map[ev->code];
1376 xf86IDrvMsg(pInfo, X_INFO, "[EvdevProcessAbsoluteMotionEvent] Invalid valuator (=%d), value=%d\nThis is going to be skipped.", map, value);
1380 valuator_mask_set(pEvdev->vals, map, value);
1381 pEvdev->abs_queued = 1;
1386 * Take the key press/release input event and process it accordingly.
1389 EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
1392 EvdevPtr pEvdev = pInfo->private;
1394 /* Get the signed value, earlier kernels had this as unsigned */
1397 /* don't repeat mouse buttons */
1398 if (ev->code >= BTN_MOUSE && ev->code < KEY_OK)
1402 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
1403 if(pEvdev->flags & EVDEV_GAMEPAD)
1405 EvdevMappingGamepadKeyToKey(pInfo, ev);
1409 #endif//_F_EVDEV_SUPPORT_GAMEPAD
1412 for (i = 0; i < ArrayLength(proximity_bits); i++)
1414 if (ev->code == proximity_bits[i])
1416 EvdevProcessProximityEvent(pInfo, ev);
1423 /* For devices that have but don't use proximity, use
1424 * BTN_TOUCH as the proximity notifier */
1425 if (!pEvdev->use_proximity)
1426 pEvdev->in_proximity = value ? ev->code : 0;
1427 if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)) ||
1430 /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
1432 ev->code = BTN_LEFT;
1433 /* Intentional fallthrough! */
1436 EvdevProcessButtonEvent(pInfo, ev);
1441 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
1443 EvdevRelativeMoveTimer(OsTimerPtr timer, CARD32 time, pointer arg)
1445 InputInfoPtr pInfo = (InputInfoPtr)arg;
1448 if(pInfo) pEvdev = pInfo->private;
1451 if(!pEvdev) return 0;
1452 if(pEvdev->rel_move_timer)
1453 TimerCancel(pEvdev->rel_move_timer);
1454 pEvdev->rel_move_timer = NULL;
1456 pEvdev->rel_move_status = 0;
1457 pEvdev->rel_move_ack = 0;
1458 int rc = XIDeleteDeviceProperty(pInfo->dev, prop_relative_move_status, TRUE);
1462 xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to delete device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, prop_relative_move_status);
1465 ErrorF("[%s] pEvdev->rel_move_status=%d\n", __FUNCTION__, pEvdev->rel_move_status);
1469 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
1471 #ifdef _F_GESTURE_EXTENSION_
1472 static BOOL EvdevMTStatusGet(InputInfoPtr pInfo, MTSyncType sync)
1477 const int first_press = XI_TouchEnd - XI_TouchBegin;
1478 EvdevPtr pEvdev = pInfo->private;
1480 if (!pEvdev || !pEvdev->mt_status )
1483 nslots = num_slots(pEvdev);
1484 for(i = 0; i < nslots; i++)
1486 pressed += pEvdev->mt_status[i];
1488 if (pressed > first_press)
1492 if ((sync == MTOUCH_FRAME_SYNC_BEGIN) && (pressed == first_press))
1495 if ((sync == MTOUCH_FRAME_SYNC_END) && !pressed)
1501 static void EvdevMTSync(InputInfoPtr pInfo, MTSyncType sync)
1505 memset(&event, 0, sizeof(event));
1506 event.header = ET_Internal;
1507 event.type = ET_MTSync;
1508 event.length = sizeof(event);
1509 event.time = GetTimeInMillis();
1510 event.deviceid = pInfo->dev->id;
1513 mieqEnqueue (pInfo->dev, (InternalEvent*)&event);
1515 #ifdef __MTSYNC_DEBUG__
1516 xf86IDrvMsg(pInfo, X_INFO, "[EvdevMTSync] %s has been sent !\n",
1517 (sync==MTOUCH_FRAME_SYNC_BEGIN) ? "MTOUCH_FRAME_SYNC_BEGIN" : "MTOUCH_FRAME_SYNC_END");
1518 #endif /* #ifdef __MTSYNC_DEBUG__ */
1520 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
1523 EvdevBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
1525 InputInfoPtr pInfo = (InputInfoPtr)data;
1526 EvdevPtr pEvdev = pInfo->private;
1528 RemoveBlockAndWakeupHandlers(EvdevBlockHandler,
1529 (WakeupHandlerProcPtr)NoopDDA,
1531 pEvdev->block_handler_registered = FALSE;
1532 ErrorF("Block Handler Called, [%d]pEvdev->rel_move_status %d, pEvdev->rel_move_status_ack %d\n", pInfo->dev->id, pEvdev->rel_move_status, pEvdev->rel_move_ack);
1535 int rc = XIChangeDeviceProperty(pInfo->dev, prop_relative_move_status, XA_INTEGER, 8,
1536 PropModeReplace, 1, &pEvdev->rel_move_status, TRUE);
1540 xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, prop_relative_move_status);
1545 * Post the relative motion events.
1548 EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
1549 int v[MAX_VALUATORS])
1551 EvdevPtr pEvdev = pInfo->private;
1553 if (pEvdev->rel_queued) {
1554 #ifdef _F_EVDEV_SUPPORT_ROTARY_
1555 if (pEvdev->flags & EVDEV_OFM) {
1556 pEvdev->extra_rel_post_ofm(pInfo, num_v, first_v, v);
1560 if (pEvdev->flags & EVDEV_HALLIC) {
1561 pEvdev->extra_rel_post_hallic(pInfo, num_v, first_v, v);
1564 #endif //_F_EVDEV_SUPPORT_ROTARY_
1565 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
1566 if(!pEvdev->rel_move_prop_set)
1567 pEvdev->rel_move_prop_set = 1;
1569 if((!pEvdev->block_handler_registered) && (!pEvdev->rel_move_status || !pEvdev->rel_move_ack))
1571 pEvdev->rel_move_status = 1;
1572 pEvdev->block_handler_registered = TRUE;
1573 RegisterBlockAndWakeupHandlers(EvdevBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
1576 TimerCancel(pEvdev->rel_move_timer);
1577 pEvdev->rel_move_timer = NULL;
1578 pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, 15000, EvdevRelativeMoveTimer, pInfo);
1579 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
1580 xf86PostMotionEventM(pInfo->dev, Relative, pEvdev->vals);
1585 * Post the absolute motion events.
1588 EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
1589 int v[MAX_VALUATORS])
1591 EvdevPtr pEvdev = pInfo->private;
1594 * Some devices only generate valid abs coords when BTN_TOOL_PEN is
1595 * pressed. On wacom tablets, this means that the pen is in
1596 * proximity of the tablet. After the pen is removed, BTN_TOOL_PEN is
1597 * released, and a (0, 0) absolute event is generated. Checking
1598 * pEvdev->in_proximity here lets us ignore that event.
1599 * pEvdev->in_proximity is initialized to 1 so devices that don't use
1600 * this scheme still just work.
1602 if (pEvdev->abs_queued && pEvdev->in_proximity) {
1603 xf86PostMotionEventM(pInfo->dev, Absolute, pEvdev->vals);
1608 EvdevPostProximityEvents(InputInfoPtr pInfo, int which, int num_v, int first_v,
1609 int v[MAX_VALUATORS])
1612 EvdevPtr pEvdev = pInfo->private;
1614 for (i = 0; pEvdev->prox_queued && i < pEvdev->num_queue; i++) {
1615 switch (pEvdev->queue[i].type) {
1619 case EV_QUEUE_TOUCH:
1622 case EV_QUEUE_PROXIMITY:
1623 if (pEvdev->queue[i].val == which)
1624 xf86PostProximityEventP(pInfo->dev, which, first_v, num_v,
1632 * Post the queued key/button events.
1634 static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v,
1635 int v[MAX_VALUATORS])
1638 #ifdef _F_GESTURE_EXTENSION_
1643 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
1644 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
1648 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
1650 EvdevPtr pEvdev = pInfo->private;
1652 for (i = 0; i < pEvdev->num_queue; i++) {
1653 switch (pEvdev->queue[i].type) {
1655 xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].detail.key,
1656 pEvdev->queue[i].val);
1659 if (Evdev3BEmuFilterEvent(pInfo,
1660 pEvdev->queue[i].detail.key,
1661 pEvdev->queue[i].val))
1664 if (pEvdev->abs_queued && pEvdev->in_proximity) {
1665 xf86PostButtonEventP(pInfo->dev, Absolute, pEvdev->queue[i].detail.key,
1666 pEvdev->queue[i].val, first_v, num_v,
1670 xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].detail.key,
1671 pEvdev->queue[i].val, 0, 0);
1673 case EV_QUEUE_PROXIMITY:
1676 case EV_QUEUE_TOUCH:
1677 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
1678 if( pEvdev->use_transform )
1682 x = valuator_mask_get(pEvdev->queue[i].touchMask, 0);
1683 y = valuator_mask_get(pEvdev->queue[i].touchMask, 1);
1687 slot = pEvdev->queue[i].detail.touch;
1688 x = valuator_mask_get(pEvdev->last_mt_vals[slot], 0);
1689 y = valuator_mask_get(pEvdev->last_mt_vals[slot], 1);
1691 p.vector[0] = pixman_int_to_fixed(x);
1692 p.vector[1] = pixman_int_to_fixed(y);
1693 p.vector[2] = pixman_int_to_fixed(1);
1695 pixman_transform_point(&pEvdev->inv_transform, &p);
1697 valuator_mask_set(pEvdev->queue[i].touchMask, 0, pixman_fixed_to_int(p.vector[0]));
1698 valuator_mask_set(pEvdev->queue[i].touchMask, 1, pixman_fixed_to_int(p.vector[1]));
1701 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
1702 #ifdef _F_GESTURE_EXTENSION_
1704 event_type = pEvdev->queue[i].val;
1705 slot_idx = pEvdev->queue[i].detail.touch;
1707 if (pEvdev->mt_status)
1709 pEvdev->mt_status[slot_idx] = XI_TouchEnd - event_type;
1711 if ((XI_TouchBegin == event_type) && (slot_idx == 0))
1713 if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_BEGIN))
1715 sync_value = MTOUCH_FRAME_SYNC_BEGIN;
1716 EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN);
1720 xf86PostTouchEvent(pInfo->dev, slot_idx,
1722 pEvdev->queue[i].touchMask);
1724 if ((sync_value < 0) && (XI_TouchEnd == event_type))
1726 if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_END))
1728 EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_END);
1732 #else /* #ifdef _F_GESTURE_EXTENSION_ */
1733 xf86PostTouchEvent(pInfo->dev, pEvdev->queue[i].detail.touch,
1734 pEvdev->queue[i].val, 0,
1735 pEvdev->queue[i].touchMask);
1736 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
1744 * Take the synchronization input event and process it accordingly; the motion
1745 * notify events are sent first, then any button/key press/release events.
1748 EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
1751 int num_v = 0, first_v = 0;
1752 int v[MAX_VALUATORS] = {};
1753 EvdevPtr pEvdev = pInfo->private;
1755 EvdevProcessProximityState(pInfo);
1757 EvdevProcessValuators(pInfo);
1758 EvdevProcessTouch(pInfo);
1760 EvdevPostProximityEvents(pInfo, TRUE, num_v, first_v, v);
1761 EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v);
1762 EvdevPostAbsoluteMotionEvents(pInfo, num_v, first_v, v);
1763 EvdevPostQueuedEvents(pInfo, num_v, first_v, v);
1764 EvdevPostProximityEvents(pInfo, FALSE, num_v, first_v, v);
1766 memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
1767 for (i = 0; i < ArrayLength(pEvdev->queue); i++)
1769 EventQueuePtr queue = &pEvdev->queue[i];
1770 queue->detail.key = 0;
1773 /* don't reset the touchMask */
1777 valuator_mask_zero(pEvdev->vals);
1778 pEvdev->num_queue = 0;
1779 pEvdev->abs_queued = 0;
1780 pEvdev->rel_queued = 0;
1781 pEvdev->prox_queued = 0;
1786 * Process the events from the device; nothing is actually posted to the server
1787 * until an EV_SYN event is received.
1790 EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
1794 EvdevProcessRelativeMotionEvent(pInfo, ev);
1797 EvdevProcessAbsoluteMotionEvent(pInfo, ev);
1800 EvdevProcessKeyEvent(pInfo, ev);
1803 EvdevProcessSyncEvent(pInfo, ev);
1813 EvdevFreeMasks(EvdevPtr pEvdev)
1817 valuator_mask_free(&pEvdev->vals);
1818 valuator_mask_free(&pEvdev->old_vals);
1819 valuator_mask_free(&pEvdev->prox);
1821 valuator_mask_free(&pEvdev->mt_mask);
1822 if (pEvdev->last_mt_vals)
1824 for (i = 0; i < num_slots(pEvdev); i++)
1825 valuator_mask_free(&pEvdev->last_mt_vals[i]);
1826 free(pEvdev->last_mt_vals);
1827 pEvdev->last_mt_vals = NULL;
1829 for (i = 0; i < EVDEV_MAXQUEUE; i++)
1830 valuator_mask_free(&pEvdev->queue[i].touchMask);
1834 /* just a magic number to reduce the number of reads */
1835 #define NUM_EVENTS 16
1838 EvdevReadInput(InputInfoPtr pInfo)
1840 struct input_event ev[NUM_EVENTS];
1841 int i, len = sizeof(ev);
1843 while (len == sizeof(ev))
1846 EvdevPtr pEvdev = pInfo->private;
1849 len = mtdev_get(pEvdev->mtdev, pInfo->fd, ev, NUM_EVENTS) *
1850 sizeof(struct input_event);
1853 len = read(pInfo->fd, &ev, sizeof(ev));
1857 if (errno == ENODEV) /* May happen after resume */
1859 EvdevMBEmuFinalize(pInfo);
1860 Evdev3BEmuFinalize(pInfo);
1861 xf86RemoveEnabledDevice(pInfo);
1864 } else if (errno != EAGAIN)
1866 /* We use X_NONE here because it doesn't alloc */
1867 xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
1873 /* The kernel promises that we always only read a complete
1874 * event, so len != sizeof ev is an error. */
1875 if (len % sizeof(ev[0])) {
1876 /* We use X_NONE here because it doesn't alloc */
1877 xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, strerror(errno));
1881 for (i = 0; i < len/sizeof(ev[0]); i++)
1882 EvdevProcessEvent(pInfo, &ev[i]);
1887 EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
1889 /* Nothing to do, dix handles all settings */
1893 EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
1895 static struct { int xbit, code; } bits[] = {
1896 { CAPSFLAG, LED_CAPSL },
1897 { NUMFLAG, LED_NUML },
1898 { SCROLLFLAG, LED_SCROLLL },
1899 { MODEFLAG, LED_KANA },
1900 { COMPOSEFLAG, LED_COMPOSE }
1904 struct input_event ev[ArrayLength(bits)];
1907 memset(ev, 0, sizeof(ev));
1909 pInfo = device->public.devicePrivate;
1910 for (i = 0; i < ArrayLength(bits); i++) {
1911 ev[i].type = EV_LED;
1912 ev[i].code = bits[i].code;
1913 ev[i].value = (ctrl->leds & bits[i].xbit) > 0;
1916 write(pInfo->fd, ev, sizeof ev);
1919 #ifdef _F_USE_DEFAULT_XKB_RULES_
1921 EvdevGetXkbRules(DeviceIntPtr device, XkbRMLVOSet * rmlvo)
1923 WindowPtr root=NULL;
1927 if(screenInfo.numScreens > 0 && screenInfo.screens[0])
1929 root = screenInfo.screens[0]->root;
1934 if( prop_xkb_rules == None )
1935 prop_xkb_rules = MakeAtom("_XKB_RULES_NAMES", strlen("_XKB_RULES_NAMES"), TRUE);
1937 rc = dixLookupProperty (&pProp, root, prop_xkb_rules, serverClient, DixReadAccess);
1938 if (rc == Success && pProp->data){
1939 keymap = (char *)pProp->data;
1940 rmlvo->rules = keymap;
1941 keymap = keymap+strlen(keymap)+1;
1942 rmlvo->model = keymap;
1943 keymap = keymap+strlen(keymap)+1;
1944 rmlvo->layout = keymap;
1945 keymap = keymap+strlen(keymap)+1;
1946 rmlvo->variant = keymap;
1947 keymap = keymap+strlen(keymap)+1;
1948 rmlvo->options = keymap;
1952 XkbGetRulesDflts(rmlvo);
1955 #endif //_F_USE_DEFAULT_XKB_RULES_
1958 EvdevAddKeyClass(DeviceIntPtr device)
1963 pInfo = device->public.devicePrivate;
1964 pEvdev = pInfo->private;
1966 #ifdef _F_USE_DEFAULT_XKB_RULES_
1967 XkbRMLVOSet dflts = { NULL };
1969 if (pEvdev->use_default_xkb_rmlvo)
1971 EvdevGetXkbRules(device, &dflts);
1973 pEvdev->rmlvo.rules = (dflts.rules) ? strdup(dflts.rules) : NULL;
1974 pEvdev->rmlvo.model = (dflts.model) ? strdup(dflts.model) : NULL;
1975 pEvdev->rmlvo.layout = (dflts.layout) ? strdup(dflts.layout) : NULL;
1976 pEvdev->rmlvo.variant = (dflts.variant) ? strdup(dflts.variant) : NULL;
1977 pEvdev->rmlvo.options = (dflts.options) ? strdup(dflts.options) : NULL;
1979 ErrorF("[%s] Set default XKB RMLVO !\n", __FUNCTION__);
1981 ErrorF("[%s] pEvdev->rmlvo.rules=%s\n", __FUNCTION__, pEvdev->rmlvo.rules ? pEvdev->rmlvo.rules : "NULL");
1982 ErrorF("[%s] pEvdev->rmlvo.model=%s\n", __FUNCTION__, pEvdev->rmlvo.model ? pEvdev->rmlvo.model : "NULL");
1983 ErrorF("[%s] pEvdev->rmlvo.layout=%s\n", __FUNCTION__, pEvdev->rmlvo.layout ? pEvdev->rmlvo.layout : "NULL");
1984 ErrorF("[%s] pEvdev->rmlvo.variant=%s\n", __FUNCTION__, pEvdev->rmlvo.variant ? pEvdev->rmlvo.variant : "NULL");
1985 ErrorF("[%s] pEvdev->rmlvo.options=%s\n", __FUNCTION__, pEvdev->rmlvo.options ? pEvdev->rmlvo.options : "NULL");
1990 /* sorry, no rules change allowed for you */
1991 xf86ReplaceStrOption(pInfo->options, "xkb_rules", "evdev");
1992 SetXkbOption(pInfo, "xkb_rules", &pEvdev->rmlvo.rules);
1993 SetXkbOption(pInfo, "xkb_model", &pEvdev->rmlvo.model);
1994 if (!pEvdev->rmlvo.model)
1995 SetXkbOption(pInfo, "XkbModel", &pEvdev->rmlvo.model);
1996 SetXkbOption(pInfo, "xkb_layout", &pEvdev->rmlvo.layout);
1997 if (!pEvdev->rmlvo.layout)
1998 SetXkbOption(pInfo, "XkbLayout", &pEvdev->rmlvo.layout);
1999 SetXkbOption(pInfo, "xkb_variant", &pEvdev->rmlvo.variant);
2000 if (!pEvdev->rmlvo.variant)
2001 SetXkbOption(pInfo, "XkbVariant", &pEvdev->rmlvo.variant);
2002 SetXkbOption(pInfo, "xkb_options", &pEvdev->rmlvo.options);
2003 if (!pEvdev->rmlvo.options)
2004 SetXkbOption(pInfo, "XkbOptions", &pEvdev->rmlvo.options);
2005 #ifdef _F_USE_DEFAULT_XKB_RULES_
2009 if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl))
2012 #ifdef _F_REMAP_KEYS_
2013 SetRemapOption(pInfo,"event_key_remap");
2014 #endif //_F_REMAP_KEYS_
2020 /* MT axes are counted twice - once as ABS_X (which the kernel keeps for
2021 * backwards compatibility), once as ABS_MT_POSITION_X. So we need to keep a
2022 * mapping of those axes to make sure we only count them once
2024 struct mt_axis_mappings {
2027 Bool needs_mapping; /* TRUE if both code and mt_code are present */
2028 int mapping; /* Logical mapping of 'code' axis */
2031 static struct mt_axis_mappings mt_axis_mappings[] = {
2032 {ABS_MT_POSITION_X, ABS_X},
2033 {ABS_MT_POSITION_Y, ABS_Y},
2034 {ABS_MT_PRESSURE, ABS_PRESSURE},
2035 {ABS_MT_DISTANCE, ABS_DISTANCE},
2040 * return TRUE if the axis is not one we should count as true axis
2043 is_blacklisted_axis(int axis)
2048 case ABS_MT_TRACKING_ID:
2057 EvdevAddAbsValuatorClass(DeviceIntPtr device)
2061 int num_axes, axis, i = 0;
2062 int num_mt_axes = 0, /* number of MT-only axes */
2063 num_mt_axes_total = 0; /* total number of MT axes, including
2064 double-counted ones, excluding blacklisted */
2067 pInfo = device->public.devicePrivate;
2068 pEvdev = pInfo->private;
2070 if (!EvdevBitIsSet(pEvdev->bitmask, EV_ABS))
2073 num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
2078 for (axis = ABS_MT_SLOT; axis < ABS_MAX; axis++)
2080 if (EvdevBitIsSet(pEvdev->abs_bitmask, axis))
2085 for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
2087 if (mt_axis_mappings[j].mt_code == axis &&
2088 BitIsOn(pEvdev->abs_bitmask, mt_axis_mappings[j].code))
2090 mt_axis_mappings[j].needs_mapping = TRUE;
2095 if (!is_blacklisted_axis(axis))
2097 num_mt_axes_total++;
2105 if (num_axes + num_mt_axes > MAX_VALUATORS) {
2106 xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS);
2107 num_axes = MAX_VALUATORS;
2110 if (num_axes < 1 && num_mt_axes_total < 1) {
2111 xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n",
2116 pEvdev->num_vals = num_axes;
2118 pEvdev->vals = valuator_mask_new(num_axes);
2119 pEvdev->old_vals = valuator_mask_new(num_axes);
2120 if (!pEvdev->vals || !pEvdev->old_vals) {
2121 xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate valuator masks.\n");
2126 if (num_mt_axes_total > 0) {
2127 pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total);
2128 if (!pEvdev->mt_mask) {
2129 xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n",
2134 pEvdev->last_mt_vals = calloc(num_slots(pEvdev), sizeof(ValuatorMask *));
2135 if (!pEvdev->last_mt_vals) {
2136 xf86IDrvMsg(pInfo, X_ERROR,
2137 "%s: failed to allocate MT last values mask array.\n",
2142 for (i = 0; i < num_slots(pEvdev); i++) {
2143 pEvdev->last_mt_vals[i] = valuator_mask_new(num_mt_axes_total);
2144 if (!pEvdev->last_mt_vals[i]) {
2145 xf86IDrvMsg(pInfo, X_ERROR,
2146 "%s: failed to allocate MT last values mask.\n",
2152 for (i = 0; i < EVDEV_MAXQUEUE; i++) {
2153 pEvdev->queue[i].touchMask =
2154 valuator_mask_new(num_mt_axes_total);
2155 if (!pEvdev->queue[i].touchMask) {
2156 xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for "
2157 "evdev event queue.\n", device->name);
2163 atoms = malloc((pEvdev->num_vals + num_mt_axes) * sizeof(Atom));
2166 for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
2169 pEvdev->axis_map[axis] = -1;
2170 if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) ||
2171 is_blacklisted_axis(axis))
2177 for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
2179 if (mt_axis_mappings[j].code == axis)
2180 mt_axis_mappings[j].mapping = mapping;
2181 else if (mt_axis_mappings[j].mt_code == axis &&
2182 mt_axis_mappings[j].needs_mapping)
2183 mapping = mt_axis_mappings[j].mapping;
2186 pEvdev->axis_map[axis] = mapping;
2191 EvdevInitAxesLabels(pEvdev, Absolute, pEvdev->num_vals + num_mt_axes, atoms);
2193 if (!InitValuatorClassDeviceStruct(device, num_axes + num_mt_axes, atoms,
2194 GetMotionHistorySize(), Absolute)) {
2195 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize valuator class device.\n");
2200 if (num_mt_axes_total > 0)
2202 int num_touches = 0;
2203 int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
2204 XIDependentTouch : XIDirectTouch;
2206 if (pEvdev->mtdev && pEvdev->mtdev->caps.slot.maximum > 0)
2207 num_touches = pEvdev->mtdev->caps.slot.maximum;
2209 if (!InitTouchClassDeviceStruct(device, num_touches, mode,
2210 num_mt_axes_total)) {
2211 xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n",
2216 for (i = 0; i < num_slots(pEvdev); i++) {
2217 for (axis = ABS_MT_TOUCH_MAJOR; axis < ABS_MAX; axis++) {
2218 if (pEvdev->axis_map[axis] >= 0) {
2219 /* XXX: read initial values from mtdev when it adds support
2221 valuator_mask_set(pEvdev->last_mt_vals[i],
2222 pEvdev->axis_map[axis], 0);
2229 for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) {
2230 int axnum = pEvdev->axis_map[axis];
2236 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30)
2237 /* Kernel provides units/mm, X wants units/m */
2238 if (pEvdev->absinfo[axis].resolution)
2239 resolution = pEvdev->absinfo[axis].resolution * 1000;
2242 xf86InitValuatorAxisStruct(device, axnum,
2244 pEvdev->absinfo[axis].minimum,
2245 pEvdev->absinfo[axis].maximum,
2246 resolution, 0, resolution, Absolute);
2247 xf86InitValuatorDefaults(device, axnum);
2251 for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) {
2252 int axnum = pEvdev->axis_map[axis];
2260 for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
2261 if (mt_axis_mappings[j].mt_code == axis &&
2262 mt_axis_mappings[j].needs_mapping)
2268 /* MT axis is mapped, don't set up twice */
2272 if (pEvdev->absinfo[axis].resolution)
2273 resolution = pEvdev->absinfo[axis].resolution * 1000;
2275 xf86InitValuatorAxisStruct(device, axnum,
2277 pEvdev->absinfo[axis].minimum,
2278 pEvdev->absinfo[axis].maximum,
2279 resolution, 0, resolution,
2287 for (i = 0; i < ArrayLength(proximity_bits); i++)
2289 if (!pEvdev->use_proximity)
2292 if (EvdevBitIsSet(pEvdev->key_bitmask, proximity_bits[i]))
2294 InitProximityClassDeviceStruct(device);
2295 pEvdev->prox = valuator_mask_new(num_axes);
2296 if (!pEvdev->prox) {
2297 xf86IDrvMsg(pInfo, X_ERROR,
2298 "failed to allocate proximity valuator " "mask.\n");
2305 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
2306 xf86IDrvMsg(pInfo, X_ERROR,
2307 "failed to initialize pointer feedback class device.\n");
2311 if (pEvdev->flags & EVDEV_TOUCHPAD)
2312 pEvdev->flags |= EVDEV_RELATIVE_MODE;
2314 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
2316 if (xf86FindOption(pInfo->options, "Mode"))
2319 mode = xf86SetStrOption(pInfo->options, "Mode", NULL);
2320 if (!strcasecmp("absolute", mode))
2321 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
2322 else if (!strcasecmp("relative", mode))
2323 pEvdev->flags |= EVDEV_RELATIVE_MODE;
2325 xf86IDrvMsg(pInfo, X_INFO, "unknown mode, use default\n");
2332 EvdevFreeMasks(pEvdev);
2339 EvdevAddRelValuatorClass(DeviceIntPtr device)
2343 int num_axes, axis, i = 0;
2346 pInfo = device->public.devicePrivate;
2347 pEvdev = pInfo->private;
2349 if (!EvdevBitIsSet(pEvdev->bitmask, EV_REL))
2352 num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX));
2356 #ifndef HAVE_SMOOTH_SCROLLING
2357 /* Wheels are special, we post them as button events. So let's ignore them
2358 * in the axes list too */
2359 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL))
2361 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL))
2363 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL))
2370 if (num_axes > MAX_VALUATORS) {
2371 xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS);
2372 num_axes = MAX_VALUATORS;
2375 pEvdev->num_vals = num_axes;
2377 pEvdev->vals = valuator_mask_new(num_axes);
2381 atoms = malloc(pEvdev->num_vals * sizeof(Atom));
2383 for (axis = REL_X; i < MAX_VALUATORS && axis <= REL_MAX; axis++)
2385 pEvdev->axis_map[axis] = -1;
2386 #ifndef HAVE_SMOOTH_SCROLLING
2387 /* We don't post wheel events, so ignore them here too */
2388 if (axis == REL_WHEEL || axis == REL_HWHEEL || axis == REL_DIAL)
2391 if (!EvdevBitIsSet(pEvdev->rel_bitmask, axis))
2393 pEvdev->axis_map[axis] = i;
2397 EvdevInitAxesLabels(pEvdev, Relative, pEvdev->num_vals, atoms);
2399 if (!InitValuatorClassDeviceStruct(device, num_axes, atoms,
2400 GetMotionHistorySize(), Relative)) {
2401 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize valuator class device.\n");
2405 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
2406 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize pointer feedback class "
2411 for (axis = REL_X; axis <= REL_MAX; axis++)
2413 int axnum = pEvdev->axis_map[axis];
2417 xf86InitValuatorAxisStruct(device, axnum, atoms[axnum], -1, -1, 1, 0, 1,
2419 xf86InitValuatorDefaults(device, axnum);
2420 #ifdef HAVE_SMOOTH_SCROLLING
2421 if (axis == REL_WHEEL)
2422 SetScrollValuator(device, axnum, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED);
2423 else if (axis == REL_DIAL)
2424 SetScrollValuator(device, axnum, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_NONE);
2425 else if (axis == REL_HWHEEL)
2426 SetScrollValuator(device, axnum, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE);
2435 valuator_mask_free(&pEvdev->vals);
2442 EvdevAddButtonClass(DeviceIntPtr device)
2446 Atom *labels = NULL;
2448 pInfo = device->public.devicePrivate;
2449 pEvdev = pInfo->private;
2451 labels = malloc(pEvdev->num_buttons * sizeof(Atom));
2452 if (!labels) return BadAlloc;
2453 EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels);
2455 if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons, labels,
2467 * Init the button mapping for the device. By default, this is a 1:1 mapping,
2468 * i.e. Button 1 maps to Button 1, Button 2 to 2, etc.
2470 * If a mapping has been specified, the mapping is the default, with the
2471 * user-defined ones overwriting the defaults.
2472 * i.e. a user-defined mapping of "3 2 1" results in a mapping of 3 2 1 4 5 6 ...
2474 * Invalid button mappings revert to the default.
2476 * Note that index 0 is unused, button 0 does not exist.
2477 * This mapping is initialised for all devices, but only applied if the device
2478 * has buttons (in EvdevAddButtonClass).
2481 EvdevInitButtonMapping(InputInfoPtr pInfo)
2483 int i, nbuttons = 1;
2484 char *mapping = NULL;
2485 EvdevPtr pEvdev = pInfo->private;
2487 /* Check for user-defined button mapping */
2488 if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL)))
2490 char *map, *s = " ";
2493 xf86IDrvMsg(pInfo, X_CONFIG, "ButtonMapping '%s'\n", mapping);
2495 while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS)
2497 btn = strtol(map, &s, 10);
2499 if (s == map || btn < 0 || btn > EVDEV_MAXBUTTONS)
2501 xf86IDrvMsg(pInfo, X_ERROR,
2502 "... Invalid button mapping. Using defaults\n");
2503 nbuttons = 1; /* ensure defaults start at 1 */
2507 pEvdev->btnmap[nbuttons++] = btn;
2513 for (i = nbuttons; i < ArrayLength(pEvdev->btnmap); i++)
2514 pEvdev->btnmap[i] = i;
2519 EvdevInitAnyValuators(DeviceIntPtr device, EvdevPtr pEvdev)
2521 InputInfoPtr pInfo = device->public.devicePrivate;
2523 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS &&
2524 EvdevAddRelValuatorClass(device) == Success)
2525 xf86IDrvMsg(pInfo, X_INFO, "initialized for relative axes.\n");
2526 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS &&
2527 EvdevAddAbsValuatorClass(device) == Success)
2528 xf86IDrvMsg(pInfo, X_INFO, "initialized for absolute axes.\n");
2532 EvdevInitAbsValuators(DeviceIntPtr device, EvdevPtr pEvdev)
2534 InputInfoPtr pInfo = device->public.devicePrivate;
2536 if (EvdevAddAbsValuatorClass(device) == Success) {
2537 xf86IDrvMsg(pInfo, X_INFO,"initialized for absolute axes.\n");
2539 xf86IDrvMsg(pInfo, X_ERROR,"failed to initialize for absolute axes.\n");
2540 pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
2545 EvdevInitRelValuators(DeviceIntPtr device, EvdevPtr pEvdev)
2547 InputInfoPtr pInfo = device->public.devicePrivate;
2548 int has_abs_axes = pEvdev->flags & EVDEV_ABSOLUTE_EVENTS;
2549 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
2550 if ( (pEvdev->flags & EVDEV_GAMEPAD) && (has_abs_axes) ) {
2551 xf86IDrvMsg(pInfo, X_INFO,"initialized for game pad axes. Ignore relative axes.\n");
2553 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
2555 EvdevInitAbsValuators(device, pEvdev);
2556 } else if (EvdevAddRelValuatorClass(device) == Success) {
2558 if (EvdevAddRelValuatorClass(device) == Success) {
2559 #endif//_F_EVDEV_SUPPORT_GAMEPAD
2560 xf86IDrvMsg(pInfo, X_INFO,"initialized for relative axes.\n");
2563 xf86IDrvMsg(pInfo, X_WARNING,"ignoring absolute axes.\n");
2564 pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
2568 xf86IDrvMsg(pInfo, X_ERROR,"failed to initialize for relative axes.\n");
2570 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
2573 EvdevInitAbsValuators(device, pEvdev);
2578 EvdevInitTouchDevice(DeviceIntPtr device, EvdevPtr pEvdev)
2580 InputInfoPtr pInfo = device->public.devicePrivate;
2582 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) {
2583 xf86IDrvMsg(pInfo, X_WARNING, "touchpads, tablets and touchscreens "
2584 "ignore relative axes.\n");
2585 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
2588 EvdevInitAbsValuators(device, pEvdev);
2591 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
2593 EvdevIsGamePad(InputInfoPtr pInfo)
2596 EvdevPtr pEvdev = pInfo->private;
2599 for(i=0; i<MAX_GAMEPAD_DEFINITION_ABS; i++)
2601 if(pEvdev->abs_gamepad_labels[i] == 0)
2604 if(!EvdevBitIsSet(pEvdev->abs_bitmask, pEvdev->abs_gamepad_labels[i]))
2606 ErrorF("[EvdevIsGamePad] %s device doesn't support abs code(%d)\n", pInfo->name, pEvdev->abs_gamepad_labels[i]);
2612 for(i=0; i<MAX_GAMEPAD_DEFINITION_KEY; i++)
2614 if(pEvdev->key_gamepad_labels[i] == 0)
2617 if(!EvdevBitIsSet(pEvdev->key_bitmask, pEvdev->key_gamepad_labels[i]))
2619 ErrorF("[EvdevIsGamePad] %s device doesn't support key code(%d)\n", pInfo->name, pEvdev->key_gamepad_labels[i]);
2626 #endif//_F_EVDEV_SUPPORT_GAMEPAD
2629 EvdevInit(DeviceIntPtr device)
2635 pInfo = device->public.devicePrivate;
2636 pEvdev = pInfo->private;
2638 /* clear all axis_map entries */
2639 for(i = 0; i < max(ABS_CNT,REL_CNT); i++)
2640 pEvdev->axis_map[i]=-1;
2642 if (pEvdev->flags & EVDEV_KEYBOARD_EVENTS)
2643 EvdevAddKeyClass(device);
2644 if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
2645 EvdevAddButtonClass(device);
2647 /* We don't allow relative and absolute axes on the same device. The
2648 * reason is that some devices (MS Optical Desktop 2000) register both
2649 * rel and abs axes for x/y.
2651 * The abs axes register min/max; this min/max then also applies to the
2652 * relative device (the mouse) and caps it at 0..255 for both axes.
2653 * So, unless you have a small screen, you won't be enjoying it much;
2654 * consequently, absolute axes are generally ignored.
2656 * However, currenly only a device with absolute axes can be registered
2657 * as a touch{pad,screen}. Thus, given such a device, absolute axes are
2658 * used and relative axes are ignored.
2661 if (pEvdev->flags & (EVDEV_UNIGNORE_RELATIVE | EVDEV_UNIGNORE_ABSOLUTE))
2662 EvdevInitAnyValuators(device, pEvdev);
2663 else if (pEvdev->flags & (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET))
2664 EvdevInitTouchDevice(device, pEvdev);
2665 else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
2666 EvdevInitRelValuators(device, pEvdev);
2668 #ifdef _F_INIT_ABS_ONLY_FOR_POINTER_
2669 else if ( !(pEvdev->flags & EVDEV_KEYBOARD_EVENTS) && (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) )
2670 #else /* #ifdef _F_INIT_ABS_ONLY_FOR_POINTER_ */
2671 else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
2672 #endif /* #ifdef _F_INIT_ABS_ONLY_FOR_POINTER_ */
2673 EvdevInitAbsValuators(device, pEvdev);
2675 /* We drop the return value, the only time we ever want the handlers to
2676 * unregister is when the device dies. In which case we don't have to
2677 * unregister anyway */
2678 EvdevInitProperty(device);
2679 XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
2680 EvdevMBEmuInitProperty(device);
2681 Evdev3BEmuInitProperty(device);
2682 EvdevWheelEmuInitProperty(device);
2683 EvdevDragLockInitProperty(device);
2684 EvdevAppleInitProperty(device);
2685 #ifdef _F_EVDEV_SUPPORT_ROTARY_
2686 EvdevRotaryInit(device);
2687 #endif //_F_EVDEV_SUPPORT_ROTARY_
2693 * Init all extras (wheel emulation, etc.) and grab the device.
2696 EvdevOn(DeviceIntPtr device)
2702 pInfo = device->public.devicePrivate;
2703 pEvdev = pInfo->private;
2704 /* after PreInit fd is still open */
2705 rc = EvdevOpenDevice(pInfo);
2709 EvdevGrabDevice(pInfo, 1, 0);
2711 xf86FlushInput(pInfo->fd);
2712 xf86AddEnabledDevice(pInfo);
2713 EvdevMBEmuOn(pInfo);
2714 Evdev3BEmuOn(pInfo);
2715 pEvdev->flags |= EVDEV_INITIALIZED;
2716 device->public.on = TRUE;
2723 EvdevProc(DeviceIntPtr device, int what)
2727 #ifdef _F_EVDEV_CONFINE_REGION_
2728 int region[6] = { 0, };
2729 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
2731 pInfo = device->public.devicePrivate;
2732 pEvdev = pInfo->private;
2737 return EvdevInit(device);
2740 return EvdevOn(device);
2743 if (pEvdev->flags & EVDEV_INITIALIZED)
2745 EvdevMBEmuFinalize(pInfo);
2746 Evdev3BEmuFinalize(pInfo);
2748 if (pInfo->fd != -1)
2750 EvdevGrabDevice(pInfo, 0, 1);
2751 xf86RemoveEnabledDevice(pInfo);
2756 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
2757 if (pEvdev->rel_move_timer)
2759 TimerCancel(pEvdev->rel_move_timer);
2760 pEvdev->rel_move_timer = NULL;
2761 pEvdev->rel_move_status = 0;
2762 pEvdev->rel_move_ack = 0;
2763 ErrorF("[%s][dev:%d] DEVICE_OFF (rel_move_status=%d, rel_move_prop_set=%d)\n", __FUNCTION__, pInfo->dev->id, pEvdev->rel_move_status,
2764 pEvdev->rel_move_prop_set);
2766 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
2768 pEvdev->min_maj = 0;
2769 pEvdev->flags &= ~EVDEV_INITIALIZED;
2770 device->public.on = FALSE;
2774 #ifdef _F_EVDEV_CONFINE_REGION_
2775 if(pEvdev->pointer_confine_region && pEvdev->confined_id)
2776 EvdevSetConfineRegion(pInfo, 1, ®ion[0]);
2777 #endif /* _F_EVDEV_CONFINE_REGION_ */
2778 xf86IDrvMsg(pInfo, X_INFO, "Close\n");
2779 if (pInfo->fd != -1) {
2783 EvdevFreeMasks(pEvdev);
2784 EvdevRemoveDevice(pInfo);
2785 #ifdef _F_REMAP_KEYS_
2787 #endif //_F_REMAP_KEYS_
2788 pEvdev->min_maj = 0;
2799 * Get as much information as we can from the fd and cache it.
2801 * @return Success if the information was cached, or !Success otherwise.
2804 EvdevCache(InputInfoPtr pInfo)
2806 EvdevPtr pEvdev = pInfo->private;
2810 char name[1024] = {0};
2811 unsigned long bitmask[NLONGS(EV_CNT)] = {0};
2812 unsigned long key_bitmask[NLONGS(KEY_CNT)] = {0};
2813 unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0};
2814 unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0};
2815 unsigned long led_bitmask[NLONGS(LED_CNT)] = {0};
2818 if (ioctl(pInfo->fd, EVIOCGID, &id) < 0)
2820 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGID failed: %s\n", strerror(errno));
2824 pEvdev->id_vendor = id.vendor;
2825 pEvdev->id_product = id.product;
2827 if (ioctl(pInfo->fd, EVIOCGNAME(sizeof(name) - 1), name) < 0) {
2828 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
2832 strcpy(pEvdev->name, name);
2834 len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask);
2836 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
2841 memcpy(pEvdev->bitmask, bitmask, len);
2843 len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask);
2845 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
2850 memcpy(pEvdev->rel_bitmask, rel_bitmask, len);
2852 len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
2854 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
2859 memcpy(pEvdev->abs_bitmask, abs_bitmask, len);
2861 len = ioctl(pInfo->fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask);
2863 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
2868 memcpy(pEvdev->led_bitmask, led_bitmask, len);
2871 * Do not try to validate absinfo data since it is not expected
2872 * to be static, always refresh it in evdev structure.
2874 for (i = ABS_X; i <= ABS_MAX; i++) {
2875 if (EvdevBitIsSet(abs_bitmask, i)) {
2876 len = ioctl(pInfo->fd, EVIOCGABS(i), &pEvdev->absinfo[i]);
2878 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGABSi(%d) failed: %s\n",
2879 i, strerror(errno));
2882 xf86IDrvMsgVerb(pInfo, X_PROBED, 6, "absolute axis %#x [%d..%d]\n",
2883 i, pEvdev->absinfo[i].maximum, pEvdev->absinfo[i].minimum);
2887 len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
2889 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
2894 /* Copy the data so we have reasonably up-to-date info */
2895 memcpy(pEvdev->key_bitmask, key_bitmask, len);
2905 * Issue an EVIOCGRAB on the device file, either as a grab or to ungrab, or
2906 * both. Return TRUE on success, otherwise FALSE. Failing the release is a
2907 * still considered a success, because it's not as if you could do anything
2911 EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab)
2913 EvdevPtr pEvdev = pInfo->private;
2915 if (pEvdev->grabDevice)
2917 if (grab && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
2918 xf86IDrvMsg(pInfo, X_WARNING, "Grab failed (%s)\n",
2921 } else if (ungrab && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
2922 xf86IDrvMsg(pInfo, X_WARNING, "Release failed (%s)\n",
2930 * Some devices only have other axes (e.g. wheels), but we
2931 * still need x/y for these. The server relies on devices having
2932 * x/y as axes 0/1 and core/XI 1.x clients expect it too (#44655)
2935 EvdevForceXY(InputInfoPtr pInfo, int mode)
2937 EvdevPtr pEvdev = pInfo->private;
2939 xf86IDrvMsg(pInfo, X_INFO, "Forcing %s x/y axes to exist.\n",
2940 (mode == Relative) ? "relative" : "absolute");
2942 if (mode == Relative)
2944 EvdevSetBit(pEvdev->rel_bitmask, REL_X);
2945 EvdevSetBit(pEvdev->rel_bitmask, REL_Y);
2946 } else if (mode == Absolute)
2948 EvdevSetBit(pEvdev->abs_bitmask, ABS_X);
2949 EvdevSetBit(pEvdev->abs_bitmask, ABS_Y);
2950 pEvdev->absinfo[ABS_X].minimum = 0;
2951 pEvdev->absinfo[ABS_X].maximum = 1000;
2952 pEvdev->absinfo[ABS_X].value = 0;
2953 pEvdev->absinfo[ABS_X].resolution = 0;
2954 pEvdev->absinfo[ABS_Y].minimum = 0;
2955 pEvdev->absinfo[ABS_Y].maximum = 1000;
2956 pEvdev->absinfo[ABS_Y].value = 0;
2957 pEvdev->absinfo[ABS_Y].resolution = 0;
2962 EvdevProbe(InputInfoPtr pInfo)
2964 int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll;
2965 int has_lmr; /* left middle right */
2966 int has_mt; /* multitouch */
2967 int ignore_abs = 0, ignore_rel = 0;
2968 EvdevPtr pEvdev = pInfo->private;
2971 xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n",
2972 pEvdev->id_vendor, pEvdev->id_product);
2974 /* Trinary state for ignoring axes:
2975 - unset: do the normal thing.
2976 - TRUE: explicitly ignore them.
2977 - FALSE: unignore axes, use them at all cost if they're present.
2979 if (xf86FindOption(pInfo->options, "IgnoreRelativeAxes"))
2981 if (xf86SetBoolOption(pInfo->options, "IgnoreRelativeAxes", FALSE))
2984 pEvdev->flags |= EVDEV_UNIGNORE_RELATIVE;
2987 if (xf86FindOption(pInfo->options, "IgnoreAbsoluteAxes"))
2989 if (xf86SetBoolOption(pInfo->options, "IgnoreAbsoluteAxes", FALSE))
2992 pEvdev->flags |= EVDEV_UNIGNORE_ABSOLUTE;
2995 has_rel_axes = FALSE;
2996 has_abs_axes = FALSE;
3003 /* count all buttons */
3004 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
3005 for (i = BTN_MISC; i < BTN_THUMBR; i++)
3007 for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
3008 #endif//_F_EVDEV_SUPPORT_GAMEPAD
3011 if (EvdevBitIsSet(pEvdev->key_bitmask, i))
3013 mapping = EvdevUtilButtonEventToButtonNumber(pEvdev, i);
3014 if (mapping > num_buttons)
3015 num_buttons = mapping;
3019 has_lmr = EvdevBitIsSet(pEvdev->key_bitmask, BTN_LEFT) ||
3020 EvdevBitIsSet(pEvdev->key_bitmask, BTN_MIDDLE) ||
3021 EvdevBitIsSet(pEvdev->key_bitmask, BTN_RIGHT);
3025 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3026 pEvdev->num_buttons = num_buttons;
3027 xf86IDrvMsg(pInfo, X_PROBED, "Found %d mouse buttons\n", num_buttons);
3030 for (i = 0; i < REL_MAX; i++) {
3031 if (EvdevBitIsSet(pEvdev->rel_bitmask, i)) {
3032 has_rel_axes = TRUE;
3038 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL) ||
3039 EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL) ||
3040 EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL)) {
3041 xf86IDrvMsg(pInfo, X_PROBED, "Found scroll wheel(s)\n");
3044 xf86IDrvMsg(pInfo, X_INFO,
3045 "Forcing buttons for scroll wheel(s)\n");
3046 num_buttons = (num_buttons < 3) ? 7 : num_buttons + 4;
3047 pEvdev->num_buttons = num_buttons;
3052 xf86IDrvMsg(pInfo, X_PROBED, "Found relative axes\n");
3053 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
3055 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) &&
3056 EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y)) {
3057 xf86IDrvMsg(pInfo, X_PROBED, "Found x and y relative axes\n");
3058 } else if (!EvdevBitIsSet(pEvdev->abs_bitmask, ABS_X) ||
3059 !EvdevBitIsSet(pEvdev->abs_bitmask, ABS_Y))
3060 EvdevForceXY(pInfo, Relative);
3062 xf86IDrvMsg(pInfo, X_INFO, "Relative axes present but ignored.\n");
3063 has_rel_axes = FALSE;
3067 for (i = 0; i < ABS_MAX; i++) {
3068 if (EvdevBitIsSet(pEvdev->abs_bitmask, i)) {
3069 has_abs_axes = TRUE;
3075 for (i = ABS_MT_SLOT; i < ABS_MAX; i++) {
3076 if (EvdevBitIsSet(pEvdev->abs_bitmask, i)) {
3083 if (ignore_abs && has_abs_axes)
3085 xf86IDrvMsg(pInfo, X_INFO, "Absolute axes present but ignored.\n");
3086 has_abs_axes = FALSE;
3087 } else if (has_abs_axes) {
3088 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute axes\n");
3089 pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
3092 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute multitouch axes\n");
3094 if ((EvdevBitIsSet(pEvdev->abs_bitmask, ABS_X) &&
3095 EvdevBitIsSet(pEvdev->abs_bitmask, ABS_Y))) {
3096 xf86IDrvMsg(pInfo, X_PROBED, "Found x and y absolute axes\n");
3097 if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOOL_PEN) ||
3098 EvdevBitIsSet(pEvdev->key_bitmask, BTN_STYLUS) ||
3099 EvdevBitIsSet(pEvdev->key_bitmask, BTN_STYLUS2))
3101 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute tablet.\n");
3102 pEvdev->flags |= EVDEV_TABLET;
3103 if (!pEvdev->num_buttons)
3105 pEvdev->num_buttons = 7; /* LMR + scroll wheels */
3106 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3108 } else if (EvdevBitIsSet(pEvdev->abs_bitmask, ABS_PRESSURE) ||
3109 EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOUCH)) {
3110 if (has_lmr || EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOOL_FINGER)) {
3111 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchpad.\n");
3112 pEvdev->flags |= EVDEV_TOUCHPAD;
3114 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchscreen\n");
3115 pEvdev->flags |= EVDEV_TOUCHSCREEN;
3116 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3118 } else if (!(EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) &&
3119 EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y)) && has_lmr) {
3120 /* some touchscreens use BTN_LEFT rather than BTN_TOUCH */
3121 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchscreen\n");
3122 pEvdev->flags |= EVDEV_TOUCHSCREEN;
3123 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3124 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
3125 } else if(EvdevIsGamePad(pInfo)) {
3126 xf86IDrvMsg(pInfo, X_PROBED, "Found gamepad\n");
3127 pEvdev->flags |= EVDEV_GAMEPAD;
3128 #endif // _F_EVDEV_SUPPORT_GAMEPAD
3132 if (!EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_POSITION_X) ||
3133 !EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_POSITION_Y))
3135 EvdevForceXY(pInfo, Absolute);
3139 for (i = 0; i < BTN_MISC; i++) {
3140 if (EvdevBitIsSet(pEvdev->key_bitmask, i)) {
3141 xf86IDrvMsg(pInfo, X_PROBED, "Found keys\n");
3142 pEvdev->flags |= EVDEV_KEYBOARD_EVENTS;
3148 if (has_rel_axes || has_abs_axes)
3151 int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
3153 pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
3154 pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
3155 pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
3157 str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
3159 num_calibration = sscanf(str, "%d %d %d %d",
3160 &calibration[0], &calibration[1],
3161 &calibration[2], &calibration[3]);
3163 if (num_calibration == 4)
3164 EvdevSetCalibration(pInfo, num_calibration, calibration);
3166 xf86IDrvMsg(pInfo, X_ERROR,
3167 "Insufficient calibration factors (%d). Ignoring calibration\n",
3172 if (has_rel_axes || has_abs_axes || num_buttons) {
3173 pInfo->flags |= XI86_SEND_DRAG_EVENTS;
3174 if (pEvdev->flags & EVDEV_TOUCHPAD) {
3175 xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchpad\n");
3176 pInfo->type_name = XI_TOUCHPAD;
3177 pEvdev->use_proximity = 0;
3178 } else if (pEvdev->flags & EVDEV_TABLET) {
3179 xf86IDrvMsg(pInfo, X_INFO, "Configuring as tablet\n");
3180 pInfo->type_name = XI_TABLET;
3181 } else if (pEvdev->flags & EVDEV_TOUCHSCREEN) {
3182 xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchscreen\n");
3183 pInfo->type_name = XI_TOUCHSCREEN;
3185 xf86IDrvMsg(pInfo, X_INFO, "Configuring as mouse\n");
3186 pInfo->type_name = XI_MOUSE;
3193 xf86IDrvMsg(pInfo, X_INFO, "Configuring as keyboard\n");
3194 pInfo->type_name = XI_KEYBOARD;
3199 (has_rel_axes || has_abs_axes || num_buttons || has_keys))
3201 xf86IDrvMsg(pInfo, X_INFO, "Adding scrollwheel support\n");
3202 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3203 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
3206 #ifdef _F_EVDEV_SUPPORT_ROTARY_
3207 if ((!strncmp(pInfo->name, "tizen_rotary", sizeof("tizen_rotary"))) && (pEvdev->flags & EVDEV_RELATIVE_EVENTS)) {
3208 xf86IDrvMsg(pInfo, X_PROBED, "Found rotary device.\n");
3209 pEvdev->flags |= EVDEV_OFM;
3211 EvdevSetBit(pEvdev->rel_bitmask, REL_Z);
3214 if ((!strncmp(pInfo->name, "tizen_detent", sizeof("tizen_detent"))) && (pEvdev->flags & EVDEV_RELATIVE_EVENTS)) {
3215 xf86IDrvMsg(pInfo, X_PROBED, "Found hall device.\n");
3216 pEvdev->flags |= EVDEV_HALLIC;
3218 #endif //_F_EVDEV_SUPPORT_ROTARY_
3221 xf86IDrvMsg(pInfo, X_WARNING, "Don't know how to use device\n");
3227 EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
3229 EvdevPtr pEvdev = pInfo->private;
3231 if (num_calibration == 0) {
3232 pEvdev->flags &= ~EVDEV_CALIBRATED;
3233 pEvdev->calibration.min_x = 0;
3234 pEvdev->calibration.max_x = 0;
3235 pEvdev->calibration.min_y = 0;
3236 pEvdev->calibration.max_y = 0;
3237 } else if (num_calibration == 4) {
3238 pEvdev->flags |= EVDEV_CALIBRATED;
3239 pEvdev->calibration.min_x = calibration[0];
3240 pEvdev->calibration.max_x = calibration[1];
3241 pEvdev->calibration.min_y = calibration[2];
3242 pEvdev->calibration.max_y = calibration[3];
3247 EvdevOpenDevice(InputInfoPtr pInfo)
3249 EvdevPtr pEvdev = pInfo->private;
3250 char *device = pEvdev->device;
3254 device = xf86CheckStrOption(pInfo->options, "Device", NULL);
3256 xf86IDrvMsg(pInfo, X_ERROR, "No device specified.\n");
3260 pEvdev->device = device;
3261 xf86IDrvMsg(pInfo, X_CONFIG, "Device: \"%s\"\n", device);
3267 pInfo->fd = open(device, O_RDWR | O_NONBLOCK, 0);
3268 } while (pInfo->fd < 0 && errno == EINTR);
3270 if (pInfo->fd < 0) {
3271 xf86IDrvMsg(pInfo, X_ERROR, "Unable to open evdev device \"%s\".\n", device);
3277 /* Check major/minor of device node to avoid adding duplicate devices. */
3278 pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
3279 if (EvdevIsDuplicate(pInfo))
3281 xf86IDrvMsg(pInfo, X_WARNING, "device file is duplicate. Ignoring.\n");
3284 mtdev_close_delete(pEvdev->mtdev);
3285 pEvdev->mtdev = NULL;
3293 #ifdef _F_EVDEV_CONFINE_REGION_
3295 GetMasterPointerFromId(int deviceid)
3297 DeviceIntPtr pDev = inputInfo.devices;
3300 if( pDev->id == deviceid && pDev->master )
3302 return pDev->master;
3311 IsMaster(DeviceIntPtr dev)
3313 return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
3317 GetPairedDevice(DeviceIntPtr dev)
3319 if (!IsMaster(dev) && dev->master)
3322 return dev->spriteInfo->paired;
3326 GetMaster(DeviceIntPtr dev, int which)
3328 DeviceIntPtr master;
3333 master = dev->master;
3337 if (which == MASTER_KEYBOARD)
3339 if (master->type != MASTER_KEYBOARD)
3340 master = GetPairedDevice(master);
3343 if (master->type != MASTER_POINTER)
3344 master = GetPairedDevice(master);
3352 EvdevHookPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
3353 BoxPtr pHotBox, BoxPtr pTopLeftBox)
3355 *pTopLeftBox = *pHotBox;
3359 EvdevHookPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
3365 pInfo = pDev->public.devicePrivate;
3366 if(!pInfo || !pInfo->private) return;
3367 pEvdev = pInfo->private;
3369 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor] Enter !\n");
3371 miPointerPtr pPointer;
3372 pPointer = MIPOINTER(pDev);
3374 pConfineBox = pEvdev->pointer_confine_region;
3375 if(pConfineBox && pEvdev->confined_id)
3377 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor][before] pBox (%d, %d, %d, %d), pPointer->limits (%d, %d, %d, %d), confined=%d\n",
3378 pBox->x1, pBox->y1, pBox->x2, pBox->y2, pPointer->limits.x1, pPointer->limits.y1, pPointer->limits.x2, pPointer->limits.y2, pPointer->confined);
3380 if( IsMaster(pDev) && GetMasterPointerFromId(pEvdev->confined_id) == pDev )
3382 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor] confine routine --begin (pDev->id=%d)\n", pDev->id);
3383 if( pBox->x1 < pConfineBox->x1 )
3384 pBox->x1 = pConfineBox->x1;
3385 if( pBox->y1 < pConfineBox->y1 )
3386 pBox->y1 = pConfineBox->y1;
3387 if( pBox->x2 > pConfineBox->x2 )
3388 pBox->x2 = pConfineBox->x2;
3389 if( pBox->y2 > pConfineBox->y2 )
3390 pBox->y2 = pConfineBox->y2;
3391 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor] confine routine --end (pDev->id=%d)\n", pDev->id);
3395 pPointer->limits = *pBox;
3396 pPointer->confined = PointerConfinedToScreen(pDev);
3398 if(pEvdev->confined_id)
3400 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor][after] pBox (%d, %d, %d, %d), pPointer->limits (%d, %d, %d, %d), confined=%d\n",
3401 pBox->x1, pBox->y1, pBox->x2, pBox->y2, pPointer->limits.x1, pPointer->limits.y1, pPointer->limits.x2, pPointer->limits.y2, pPointer->confined);
3404 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor] Leave !\n");
3408 EvdevSetCursorLimits(InputInfoPtr pInfo, int region[6], int isSet)
3410 EvdevPtr pEvdev = pInfo->private;
3411 BoxPtr pConfineBox = pEvdev->pointer_confine_region;
3415 ScreenPtr pCursorScreen = NULL;
3417 pCursorScreen = miPointerGetScreen(pInfo->dev);
3419 if( !pCursorScreen )
3421 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetCursorLimits] Failed to get screen information for pointer !\n");
3427 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] isSet = TRUE !!\n");
3429 //Clip confine region with screen's width/height
3432 if( region[2] >= pCursorScreen->width )
3433 region[2] = pCursorScreen->width - 1;
3434 if( region [1] < 0 )
3436 if( region[3] >= pCursorScreen->height )
3437 region[3] = pCursorScreen->height - 1;
3439 //Do pointerwarp if region[4] is not zero and region[5] is zero
3440 if(region[4] && !region[5])
3443 pConfineBox->x1 = region[0];
3444 pConfineBox->y1 = region[1];
3445 pConfineBox->x2 = region[2];
3446 pConfineBox->y2 = region[3];
3447 pEvdev->confined_id = pInfo->dev->id;
3449 pCursorScreen->ConstrainCursor(inputInfo.pointer, pCursorScreen, pConfineBox);
3450 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] Constrain information for cursor was set to TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) !\n",
3451 region[0], region[1], region[2], region[3]);
3453 if( pCursorScreen->CursorLimits != EvdevHookPointerCursorLimits &&
3454 pCursorScreen->ConstrainCursor != EvdevHookPointerConstrainCursor)
3456 //Backup original function pointer(s)
3457 pEvdev->pOrgConstrainCursor = pCursorScreen->ConstrainCursor;
3458 pEvdev->pOrgCursorLimits = pCursorScreen->CursorLimits;
3460 //Overriding function pointer(s)
3461 pCursorScreen->CursorLimits = EvdevHookPointerCursorLimits;
3462 pCursorScreen->ConstrainCursor = EvdevHookPointerConstrainCursor;
3465 //Skip pointer warp if region[4] is zero
3468 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] region[4]=%d NOT pointer warp !\n", region[4]);
3473 v[0] = region[0] + (int)((float)(region[2]-region[0])/2);
3474 v[1] = region[1] + (int)((float)(region[3]-region[1])/2);
3476 xf86PostMotionEventP(pInfo->dev, TRUE, REL_X, 2, v);
3477 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] Cursor was warped to (%d, %d) !\n", v[0], v[1]);
3478 miPointerGetPosition(pInfo->dev, &x, &y);
3479 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] Cursor is located at (%d, %d) !\n", x, y);
3483 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] isSet = FALSE !!\n");
3485 pConfineBox->x1 = 0;
3486 pConfineBox->y1 = 0;
3487 pConfineBox->x2 = pCursorScreen->width - 1;
3488 pConfineBox->y2 = pCursorScreen->height - 1;
3489 pEvdev->confined_id = 0;
3491 pCursorScreen->ConstrainCursor(inputInfo.pointer, pCursorScreen, pConfineBox);
3492 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] Constrain information for cursor was restored ! TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) !\n",
3493 pConfineBox->x1, pConfineBox->y1,
3494 pConfineBox->x2, pConfineBox->y2);
3496 //Restore original function pointer(s)
3497 pCursorScreen->CursorLimits = pEvdev->pOrgCursorLimits;
3498 pCursorScreen->ConstrainCursor = pEvdev->pOrgConstrainCursor;
3503 EvdevSetConfineRegion(InputInfoPtr pInfo, int num_item, int region[6])
3505 EvdevPtr pEvdev = pInfo ? pInfo->private : NULL;
3509 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetConfineRegion] num_item != 6 && num_item != 1 !!\n");
3513 if ((num_item != 6) && (num_item != 1) )
3515 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetConfineRegion] num_item != 6 && num_item != 1 !!\n");
3519 if (!pEvdev->pointer_confine_region)
3521 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetConfineRegion] pEvdev->pointer_confine_region is NULL\n");
3522 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetConfineRegion] num_item=%d\n", num_item);
3528 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetConfineRegion] num_item == 6\n");
3529 if ( (region[2]-region[0]>0) && (region[3]-region[1]>0) )
3531 EvdevSetCursorLimits(pInfo, ®ion[0], 1);
3532 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetConfineRegion] Confine region was set to TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) pointerwarp=%d, confine=%d\n",
3533 region[0], region[1], region[2], region[3], region[4], region[5]);
3534 pEvdev->flags |= EVDEV_CONFINE_REGION;
3537 else//if( num_item == 1 )
3539 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetConfineRegion] num_item == 1\n");
3540 if( !region[0] && (pEvdev->flags & EVDEV_CONFINE_REGION) )
3542 EvdevSetCursorLimits(pInfo, ®ion[0], 0);
3543 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetConfineRegion] Confine region was unset !\n");
3544 pEvdev->flags &= ~EVDEV_CONFINE_REGION;
3548 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
3550 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
3552 EvdevSetTransformMatrix(InputInfoPtr pInfo, int num_transform, float *tmatrix)
3555 struct pixman_transform tr;
3556 EvdevPtr pEvdev = pInfo ? pInfo->private : NULL;
3561 if( (num_transform != 9) && (num_transform != 1) )
3563 pEvdev->use_transform = FALSE;
3567 if( num_transform == 9 )
3569 pEvdev->use_transform = TRUE;
3571 memcpy(pEvdev->transform, tmatrix, sizeof(pEvdev->transform));
3574 tr.matrix[y][x] = pixman_double_to_fixed((double)*tmatrix++);
3576 pixman_transform_invert(&pEvdev->inv_transform, &tr);
3577 ErrorF("[X11][EvdevSetTransformMatrix] Touch transform has been enabled !\n");
3579 else if( (num_transform == 1) && (tmatrix[0] == 0) )
3581 pEvdev->use_transform = FALSE;
3582 ErrorF("[X11][EvdevSetTransformMatrix] Touch transform has been disabled !\n");
3585 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
3588 EvdevUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
3590 EvdevPtr pEvdev = pInfo ? pInfo->private : NULL;
3593 #ifdef _F_EVDEV_SUPPORT_ROTARY_
3594 EvdevRotaryUnInit(pEvdev);
3595 #endif //_F_EVDEV_SUPPORT_ROTARY_
3597 /* Release strings allocated in EvdevAddKeyClass. */
3598 XkbFreeRMLVOSet(&pEvdev->rmlvo, FALSE);
3599 /* Release string allocated in EvdevOpenDevice. */
3600 free(pEvdev->device);
3601 pEvdev->device = NULL;
3603 xf86DeleteInput(pInfo, flags);
3607 EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
3611 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
3613 int num_transform = 0;
3615 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
3617 if (!(pEvdev = calloc(sizeof(EvdevRec), 1)))
3619 xf86IDrvMsg(pInfo, X_ERROR, "Failed to allocate memory for private member of pInfo !\n");
3623 pInfo->private = pEvdev;
3624 pInfo->type_name = "UNKNOWN";
3625 pInfo->device_control = EvdevProc;
3626 pInfo->read_input = EvdevReadInput;
3627 pInfo->switch_mode = EvdevSwitchMode;
3628 #ifdef _F_EVDEV_SUPPORT_ROTARY_
3629 pEvdev->extra_rel_post_hallic= NULL;
3630 pEvdev->extra_rel_post_ofm= NULL;
3631 #endif //_F_EVDEV_SUPPORT_ROTARY_
3633 rc = EvdevOpenDevice(pInfo);
3638 pEvdev->cur_slot = -1;
3642 * We initialize pEvdev->in_proximity to 1 so that device that doesn't use
3643 * proximity will still report events.
3645 pEvdev->in_proximity = 1;
3646 pEvdev->use_proximity = 1;
3648 /* Grabbing the event device stops in-kernel event forwarding. In other
3649 words, it disables rfkill and the "Macintosh mouse button emulation".
3650 Note that this needs a server that sets the console to RAW mode. */
3651 pEvdev->grabDevice = xf86CheckBoolOption(pInfo->options, "GrabDevice", 0);
3653 /* If grabDevice is set, ungrab immediately since we only want to grab
3654 * between DEVICE_ON and DEVICE_OFF. If we never get DEVICE_ON, don't
3656 if (!EvdevGrabDevice(pInfo, 1, 1))
3658 xf86IDrvMsg(pInfo, X_WARNING, "Device may already be configured.\n");
3663 EvdevInitButtonMapping(pInfo);
3665 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
3670 memset(&pEvdev->abs_gamepad_labels, 0, sizeof(pEvdev->abs_gamepad_labels));
3672 for(i = 0 ; i < MAX_GAMEPAD_DEFINITION_ABS ; i++)
3674 snprintf(tmp, sizeof(tmp), "GamePad_Condition_ABS%d", i+1);
3675 pEvdev->abs_gamepad_labels[i] = xf86SetIntOption(pInfo->options, tmp, 0);
3683 memset(&pEvdev->key_gamepad_labels, 0, sizeof(pEvdev->key_gamepad_labels));
3685 for(i = 0 ; i < MAX_GAMEPAD_DEFINITION_KEY ; i++)
3687 snprintf(tmp, sizeof(tmp), "GamePad_Condition_KEY%d", i+1);
3689 pEvdev->key_gamepad_labels[i] = xf86SetIntOption(pInfo->options, tmp, BTN_GAMEPAD);
3691 pEvdev->key_gamepad_labels[i] = xf86SetIntOption(pInfo->options, tmp, 0);
3694 #endif//_F_EVDEV_SUPPORT_GAMEPAD
3696 #ifdef _F_USE_DEFAULT_XKB_RULES_
3697 pEvdev->use_default_xkb_rmlvo = xf86SetBoolOption(pInfo->options, "UseDefaultXkbRMLVO", FALSE);
3700 #ifdef _F_EVDEV_SUPPORT_ROTARY_
3701 pEvdev->HW_Calibration = xf86SetIntOption(pInfo->options, "HW_ROTARY_MAX", DEFAULT_HW_ROTARY_MAX);
3702 #endif //_F_EVDEV_SUPPORT_ROTARY_
3704 if (EvdevCache(pInfo) || EvdevProbe(pInfo)) {
3709 EvdevAddDevice(pInfo);
3711 if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
3713 EvdevMBEmuPreInit(pInfo);
3714 Evdev3BEmuPreInit(pInfo);
3715 EvdevWheelEmuPreInit(pInfo);
3716 EvdevDragLockPreInit(pInfo);
3720 if (strstr(pInfo->type_name, XI_TOUCHSCREEN))
3722 pEvdev->mtdev = mtdev_new_open(pInfo->fd);
3726 pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
3730 xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
3736 pEvdev->mtdev = NULL;
3740 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
3741 pEvdev->use_transform = FALSE;
3743 if (strstr(pInfo->type_name, XI_TOUCHSCREEN))
3745 str = xf86CheckStrOption(pInfo->options, "Transform", NULL);
3749 num_transform = sscanf(str, "%f %f %f %f %f %f %f %f %f",
3750 &tr[0], &tr[1], &tr[2],
3751 &tr[3], &tr[4], &tr[5],
3752 &tr[6], &tr[7], &tr[8]);
3753 if (num_transform == 9)
3754 EvdevSetTransformMatrix(pInfo, num_transform, tr);
3757 xf86Msg(X_ERROR, "%s: Insufficient transform factors (%d). Ignoring transform\n",
3758 pInfo->name, num_transform);
3762 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
3764 #ifdef _F_EVDEV_CONFINE_REGION_
3765 pEvdev->confined_id = 0;
3766 pEvdev->pointer_confine_region = NULL;
3768 if (strstr(pInfo->name, XI_TOUCHPAD)
3769 || strstr(pInfo->type_name, XI_MOUSE)
3770 || strstr(pInfo->name, "Virtual Touchpad"))
3772 pEvdev->pointer_confine_region = (BoxPtr)malloc(sizeof(BoxRec));
3774 if (!pEvdev->pointer_confine_region)
3776 xf86IDrvMsg(pInfo, X_ERROR, "Failed to allocate memory for pointer confine region\nConfine feature may not work properly.");
3782 xf86IDrvMsg(pInfo, X_INFO, "Succeed to allocate memory for pointer confine region\nConfine feature will work properly.");
3785 memset(pEvdev->pointer_confine_region, 0, sizeof(BoxRec));
3787 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
3789 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
3790 pEvdev->rel_move_timer = NULL;
3791 pEvdev->rel_move_prop_set = 0;
3792 pEvdev->rel_move_status = 0;
3793 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
3795 #ifdef _F_GESTURE_EXTENSION_
3796 int alloc_size = sizeof(int)*num_slots(pEvdev);
3797 pEvdev->mt_status = NULL;
3799 if (strstr(pInfo->type_name, XI_TOUCHSCREEN))
3801 pEvdev->mt_status = (int *)malloc(alloc_size);
3803 if (!pEvdev->mt_status)
3805 xf86IDrvMsg(pInfo, X_ERROR, "Failed to allocate memory to maintain multitouch status !\nX Gesture driver may not work properly.\n");
3810 memset(pEvdev->mt_status, 0, alloc_size);
3812 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
3813 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
3814 pEvdev->pre_x = 128;
3815 pEvdev->pre_y = 128;
3817 pEvdev->support_directional_key = xf86SetBoolOption(pInfo->options, "Support_Directional_Keys", FALSE);
3819 pEvdev->keycode_btnA = xf86SetIntOption(pInfo->options, "GamePad_ButtonA", 0);
3820 pEvdev->keycode_btnB = xf86SetIntOption(pInfo->options, "GamePad_ButtonB", 0);
3821 pEvdev->keycode_btnX = xf86SetIntOption(pInfo->options, "GamePad_ButtonX", 0);
3822 pEvdev->keycode_btnY = xf86SetIntOption(pInfo->options, "GamePad_ButtonY", 0);
3823 pEvdev->keycode_btnTL = xf86SetIntOption(pInfo->options, "GamePad_ButtonTL", 0);
3824 pEvdev->keycode_btnTR = xf86SetIntOption(pInfo->options, "GamePad_ButtonTR", 0);
3825 pEvdev->keycode_btnStart = xf86SetIntOption(pInfo->options, "GamePad_ButtonStart", 0);
3826 pEvdev->keycode_btnSelect = xf86SetIntOption(pInfo->options, "GamePad_ButtonSelect", 0);
3827 pEvdev->keycode_btnPlay = xf86SetIntOption(pInfo->options, "GamePad_ButtonPlay", 0);
3828 #endif//_F_EVDEV_SUPPORT_GAMEPAD
3833 if ((pInfo) && (pInfo->fd >= 0))
3838 _X_EXPORT InputDriverRec EVDEV = {
3849 EvdevUnplug(pointer p)
3854 EvdevPlug(pointer module,
3859 xf86AddInputDriver(&EVDEV, module, 0);
3863 static XF86ModuleVersionInfo EvdevVersionRec =
3869 XORG_VERSION_CURRENT,
3870 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
3877 _X_EXPORT XF86ModuleData evdevModuleData =
3885 /* Return an index value for a given button event code
3886 * returns 0 on non-button event.
3889 EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code)
3900 case BTN_SIDE ... BTN_JOYSTICK - 1:
3901 return 8 + code - BTN_SIDE;
3903 /* Generic buttons */
3904 case BTN_0 ... BTN_2:
3905 return 1 + code - BTN_0;
3906 case BTN_3 ... BTN_MOUSE - 1:
3907 return 8 + code - BTN_3;
3909 /* Tablet stylus buttons */
3910 case BTN_TOUCH ... BTN_STYLUS2:
3911 return 1 + code - BTN_TOUCH;
3912 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
3913 /* Game pad buttons */
3914 case BTN_A ... BTN_THUMBR:
3915 return 8 + code - BTN_A;
3916 #endif//_F_EVDEV_SUPPORT_GAMEPAD
3925 /* Aligned with linux/input.h.
3926 Note that there are holes in the ABS_ range, these are simply replaced with
3928 static char* abs_labels[] = {
3929 AXIS_LABEL_PROP_ABS_X, /* 0x00 */
3930 AXIS_LABEL_PROP_ABS_Y, /* 0x01 */
3931 AXIS_LABEL_PROP_ABS_Z, /* 0x02 */
3932 AXIS_LABEL_PROP_ABS_RX, /* 0x03 */
3933 AXIS_LABEL_PROP_ABS_RY, /* 0x04 */
3934 AXIS_LABEL_PROP_ABS_RZ, /* 0x05 */
3935 AXIS_LABEL_PROP_ABS_THROTTLE, /* 0x06 */
3936 AXIS_LABEL_PROP_ABS_RUDDER, /* 0x07 */
3937 AXIS_LABEL_PROP_ABS_WHEEL, /* 0x08 */
3938 AXIS_LABEL_PROP_ABS_GAS, /* 0x09 */
3939 AXIS_LABEL_PROP_ABS_BRAKE, /* 0x0a */
3940 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3941 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3942 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3943 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3944 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3945 AXIS_LABEL_PROP_ABS_HAT0X, /* 0x10 */
3946 AXIS_LABEL_PROP_ABS_HAT0Y, /* 0x11 */
3947 AXIS_LABEL_PROP_ABS_HAT1X, /* 0x12 */
3948 AXIS_LABEL_PROP_ABS_HAT1Y, /* 0x13 */
3949 AXIS_LABEL_PROP_ABS_HAT2X, /* 0x14 */
3950 AXIS_LABEL_PROP_ABS_HAT2Y, /* 0x15 */
3951 AXIS_LABEL_PROP_ABS_HAT3X, /* 0x16 */
3952 AXIS_LABEL_PROP_ABS_HAT3Y, /* 0x17 */
3953 AXIS_LABEL_PROP_ABS_PRESSURE, /* 0x18 */
3954 AXIS_LABEL_PROP_ABS_DISTANCE, /* 0x19 */
3955 AXIS_LABEL_PROP_ABS_TILT_X, /* 0x1a */
3956 AXIS_LABEL_PROP_ABS_TILT_Y, /* 0x1b */
3957 AXIS_LABEL_PROP_ABS_TOOL_WIDTH, /* 0x1c */
3958 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3959 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3960 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3961 AXIS_LABEL_PROP_ABS_VOLUME /* 0x20 */
3962 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3963 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3964 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3965 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3966 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3967 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3968 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3969 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3970 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3971 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3972 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3973 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3974 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3975 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3976 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3977 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3978 AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR, /* 0x30 */
3979 AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR, /* 0x31 */
3980 AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR, /* 0x32 */
3981 AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR, /* 0x33 */
3982 AXIS_LABEL_PROP_ABS_MT_ORIENTATION, /* 0x34 */
3983 AXIS_LABEL_PROP_ABS_MT_POSITION_X, /* 0x35 */
3984 AXIS_LABEL_PROP_ABS_MT_POSITION_Y, /* 0x36 */
3985 AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE, /* 0x37 */
3986 AXIS_LABEL_PROP_ABS_MT_BLOB_ID, /* 0x38 */
3987 AXIS_LABEL_PROP_ABS_MT_TRACKING_ID, /* 0x39 */
3988 AXIS_LABEL_PROP_ABS_MT_PRESSURE, /* 0x3a */
3991 static char* rel_labels[] = {
3992 AXIS_LABEL_PROP_REL_X,
3993 AXIS_LABEL_PROP_REL_Y,
3994 AXIS_LABEL_PROP_REL_Z,
3995 AXIS_LABEL_PROP_REL_RX,
3996 AXIS_LABEL_PROP_REL_RY,
3997 AXIS_LABEL_PROP_REL_RZ,
3998 AXIS_LABEL_PROP_REL_HWHEEL,
3999 AXIS_LABEL_PROP_REL_DIAL,
4000 AXIS_LABEL_PROP_REL_WHEEL,
4001 AXIS_LABEL_PROP_REL_MISC
4004 static char* btn_labels[][16] = {
4005 { /* BTN_MISC group offset 0x100*/
4006 BTN_LABEL_PROP_BTN_0, /* 0x00 */
4007 BTN_LABEL_PROP_BTN_1, /* 0x01 */
4008 BTN_LABEL_PROP_BTN_2, /* 0x02 */
4009 BTN_LABEL_PROP_BTN_3, /* 0x03 */
4010 BTN_LABEL_PROP_BTN_4, /* 0x04 */
4011 BTN_LABEL_PROP_BTN_5, /* 0x05 */
4012 BTN_LABEL_PROP_BTN_6, /* 0x06 */
4013 BTN_LABEL_PROP_BTN_7, /* 0x07 */
4014 BTN_LABEL_PROP_BTN_8, /* 0x08 */
4015 BTN_LABEL_PROP_BTN_9 /* 0x09 */
4017 { /* BTN_MOUSE group offset 0x110 */
4018 BTN_LABEL_PROP_BTN_LEFT, /* 0x00 */
4019 BTN_LABEL_PROP_BTN_RIGHT, /* 0x01 */
4020 BTN_LABEL_PROP_BTN_MIDDLE, /* 0x02 */
4021 BTN_LABEL_PROP_BTN_SIDE, /* 0x03 */
4022 BTN_LABEL_PROP_BTN_EXTRA, /* 0x04 */
4023 BTN_LABEL_PROP_BTN_FORWARD, /* 0x05 */
4024 BTN_LABEL_PROP_BTN_BACK, /* 0x06 */
4025 BTN_LABEL_PROP_BTN_TASK /* 0x07 */
4027 { /* BTN_JOYSTICK group offset 0x120 */
4028 BTN_LABEL_PROP_BTN_TRIGGER, /* 0x00 */
4029 BTN_LABEL_PROP_BTN_THUMB, /* 0x01 */
4030 BTN_LABEL_PROP_BTN_THUMB2, /* 0x02 */
4031 BTN_LABEL_PROP_BTN_TOP, /* 0x03 */
4032 BTN_LABEL_PROP_BTN_TOP2, /* 0x04 */
4033 BTN_LABEL_PROP_BTN_PINKIE, /* 0x05 */
4034 BTN_LABEL_PROP_BTN_BASE, /* 0x06 */
4035 BTN_LABEL_PROP_BTN_BASE2, /* 0x07 */
4036 BTN_LABEL_PROP_BTN_BASE3, /* 0x08 */
4037 BTN_LABEL_PROP_BTN_BASE4, /* 0x09 */
4038 BTN_LABEL_PROP_BTN_BASE5, /* 0x0a */
4039 BTN_LABEL_PROP_BTN_BASE6, /* 0x0b */
4043 BTN_LABEL_PROP_BTN_DEAD /* 0x0f */
4045 { /* BTN_GAMEPAD group offset 0x130 */
4046 BTN_LABEL_PROP_BTN_A, /* 0x00 */
4047 BTN_LABEL_PROP_BTN_B, /* 0x01 */
4048 BTN_LABEL_PROP_BTN_C, /* 0x02 */
4049 BTN_LABEL_PROP_BTN_X, /* 0x03 */
4050 BTN_LABEL_PROP_BTN_Y, /* 0x04 */
4051 BTN_LABEL_PROP_BTN_Z, /* 0x05 */
4052 BTN_LABEL_PROP_BTN_TL, /* 0x06 */
4053 BTN_LABEL_PROP_BTN_TR, /* 0x07 */
4054 BTN_LABEL_PROP_BTN_TL2, /* 0x08 */
4055 BTN_LABEL_PROP_BTN_TR2, /* 0x09 */
4056 BTN_LABEL_PROP_BTN_SELECT, /* 0x0a */
4057 BTN_LABEL_PROP_BTN_START, /* 0x0b */
4058 BTN_LABEL_PROP_BTN_MODE, /* 0x0c */
4059 BTN_LABEL_PROP_BTN_THUMBL, /* 0x0d */
4060 BTN_LABEL_PROP_BTN_THUMBR /* 0x0e */
4062 { /* BTN_DIGI group offset 0x140 */
4063 BTN_LABEL_PROP_BTN_TOOL_PEN, /* 0x00 */
4064 BTN_LABEL_PROP_BTN_TOOL_RUBBER, /* 0x01 */
4065 BTN_LABEL_PROP_BTN_TOOL_BRUSH, /* 0x02 */
4066 BTN_LABEL_PROP_BTN_TOOL_PENCIL, /* 0x03 */
4067 BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH, /* 0x04 */
4068 BTN_LABEL_PROP_BTN_TOOL_FINGER, /* 0x05 */
4069 BTN_LABEL_PROP_BTN_TOOL_MOUSE, /* 0x06 */
4070 BTN_LABEL_PROP_BTN_TOOL_LENS, /* 0x07 */
4073 BTN_LABEL_PROP_BTN_TOUCH, /* 0x0a */
4074 BTN_LABEL_PROP_BTN_STYLUS, /* 0x0b */
4075 BTN_LABEL_PROP_BTN_STYLUS2, /* 0x0c */
4076 BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP, /* 0x0d */
4077 BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP /* 0x0e */
4079 { /* BTN_WHEEL group offset 0x150 */
4080 BTN_LABEL_PROP_BTN_GEAR_DOWN, /* 0x00 */
4081 BTN_LABEL_PROP_BTN_GEAR_UP /* 0x01 */
4085 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int mode, int natoms, Atom *atoms)
4092 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
4093 if (mode == Absolute || pEvdev->flags & EVDEV_GAMEPAD)
4095 if (mode == Absolute)
4096 #endif//_F_EVDEV_SUPPORT_GAMEPAD
4098 labels = abs_labels;
4099 labels_len = ArrayLength(abs_labels);
4100 } else if (mode == Relative)
4102 labels = rel_labels;
4103 labels_len = ArrayLength(rel_labels);
4107 memset(atoms, 0, natoms * sizeof(Atom));
4109 /* Now fill the ones we know */
4110 for (axis = 0; axis < labels_len; axis++)
4112 if (pEvdev->axis_map[axis] == -1)
4115 atom = XIGetKnownProperty(labels[axis]);
4116 if (!atom) /* Should not happen */
4119 atoms[pEvdev->axis_map[axis]] = atom;
4123 static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
4128 /* First, make sure all atoms are initialized */
4129 atom = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN);
4130 for (button = 0; button < natoms; button++)
4131 atoms[button] = atom;
4133 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
4134 for (button = BTN_MISC; button < BTN_THUMBR; button++)
4136 for (button = BTN_MISC; button < BTN_JOYSTICK; button++)
4137 #endif//_F_EVDEV_SUPPORT_GAMEPAD
4139 if (EvdevBitIsSet(pEvdev->key_bitmask, button))
4141 int group = (button % 0x100)/16;
4142 int idx = button - ((button/16) * 16);
4144 if ((unsigned int)group >= sizeof(btn_labels)/sizeof(btn_labels[0]))
4147 if (!btn_labels[group][idx])
4150 atom = XIGetKnownProperty(btn_labels[group][idx]);
4154 /* Props are 0-indexed, button numbers start with 1 */
4155 bmap = EvdevUtilButtonEventToButtonNumber(pEvdev, button) - 1;
4163 /* wheel buttons, hardcoded anyway */
4165 atoms[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
4167 atoms[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
4169 atoms[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
4171 atoms[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
4175 EvdevInitProperty(DeviceIntPtr dev)
4177 InputInfoPtr pInfo = dev->public.devicePrivate;
4178 EvdevPtr pEvdev = pInfo->private;
4181 #ifdef _F_ENABLE_DEVICE_TYPE_PROP_
4183 #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
4184 #ifdef _F_EVDEV_CONFINE_REGION_
4185 int region[6] = { 0, };
4186 #endif /* _F_EVDEV_CONFINE_REGION_ */
4190 prop_product_id = MakeAtom(XI_PROP_PRODUCT_ID, strlen(XI_PROP_PRODUCT_ID), TRUE);
4191 product[0] = pEvdev->id_vendor;
4192 product[1] = pEvdev->id_product;
4193 rc = XIChangeDeviceProperty(dev, prop_product_id, XA_INTEGER, 32,
4194 PropModeReplace, 2, product, FALSE);
4198 XISetDevicePropertyDeletable(dev, prop_product_id, FALSE);
4200 /* Device node property */
4201 device_node = strdup(pEvdev->device);
4202 prop_device = MakeAtom(XI_PROP_DEVICE_NODE,
4203 strlen(XI_PROP_DEVICE_NODE), TRUE);
4204 rc = XIChangeDeviceProperty(dev, prop_device, XA_STRING, 8,
4206 (device_node?strlen(device_node):0), device_node,
4213 XISetDevicePropertyDeletable(dev, prop_device, FALSE);
4215 #ifdef _F_ENABLE_DEVICE_TYPE_PROP_
4216 /* Device node property */
4217 device_type = strdup(pInfo->type_name);
4218 prop_device_type = MakeAtom(XI_PROP_DEVICE_TYPE,
4219 strlen(XI_PROP_DEVICE_TYPE), TRUE);
4220 rc = XIChangeDeviceProperty(dev, prop_device_type, XA_STRING, 8,
4222 (device_type?strlen(device_type):0), device_type,
4228 #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
4230 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
4231 pEvdev->rel_move_status = 0;
4233 /* Relative movement property */
4234 prop_relative_move_status = MakeAtom(XI_PROP_REL_MOVE_STATUS,
4235 strlen(XI_PROP_REL_MOVE_STATUS), TRUE);
4236 prop_relative_move_ack = MakeAtom(XI_PROP_REL_MOVE_ACK,
4237 strlen(XI_PROP_REL_MOVE_ACK), TRUE);
4239 ErrorF("[%s] prop_relative_move_status = %d, prop_relative_move_ack = %d\n", __FUNCTION__, prop_relative_move_status, prop_relative_move_ack);
4240 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
4242 if (EvdevDeviceIsVirtual(pEvdev->device))
4245 prop_virtual = MakeAtom(XI_PROP_VIRTUAL_DEVICE,
4246 strlen(XI_PROP_VIRTUAL_DEVICE), TRUE);
4247 rc = XIChangeDeviceProperty(dev, prop_virtual, XA_INTEGER, 8,
4248 PropModeReplace, 1, &virtual, FALSE);
4249 XISetDevicePropertyDeletable(dev, prop_virtual, FALSE);
4252 XISetDevicePropertyDeletable(dev, prop_device, FALSE);
4254 #ifdef _F_EVDEV_CONFINE_REGION_
4255 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
4257 prop_confine_region = MakeAtom(EVDEV_PROP_CONFINE_REGION,
4258 strlen(EVDEV_PROP_CONFINE_REGION), TRUE);
4259 rc = XIChangeDeviceProperty(dev, prop_confine_region, XA_INTEGER,
4260 32, PropModeReplace, 4, region, FALSE);
4262 //32, PropModeReplace, 6, region, FALSE);
4267 XISetDevicePropertyDeletable(dev, prop_confine_region, FALSE);
4269 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
4271 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
4272 if (strstr(pInfo->type_name, XI_TOUCHSCREEN))
4274 /* matrix to transform */
4275 prop_transform = MakeAtom(EVDEV_PROP_TOUCH_TRANSFORM_MATRIX, strlen(EVDEV_PROP_TOUCH_TRANSFORM_MATRIX), TRUE);
4276 rc = XIChangeDeviceProperty(dev, prop_transform, XIGetKnownProperty(XATOM_FLOAT), 32, PropModeReplace, 9, pEvdev->transform, FALSE);
4281 XISetDevicePropertyDeletable(dev, prop_transform, FALSE);
4283 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
4286 if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS))
4289 invert[0] = pEvdev->invert_x;
4290 invert[1] = pEvdev->invert_y;
4292 prop_invert = MakeAtom(EVDEV_PROP_INVERT_AXES, strlen(EVDEV_PROP_INVERT_AXES), TRUE);
4294 rc = XIChangeDeviceProperty(dev, prop_invert, XA_INTEGER, 8,
4300 XISetDevicePropertyDeletable(dev, prop_invert, FALSE);
4302 prop_calibration = MakeAtom(EVDEV_PROP_CALIBRATION,
4303 strlen(EVDEV_PROP_CALIBRATION), TRUE);
4304 if (pEvdev->flags & EVDEV_CALIBRATED) {
4307 calibration[0] = pEvdev->calibration.min_x;
4308 calibration[1] = pEvdev->calibration.max_x;
4309 calibration[2] = pEvdev->calibration.min_y;
4310 calibration[3] = pEvdev->calibration.max_y;
4312 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
4313 32, PropModeReplace, 4, calibration,
4315 } else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) {
4316 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
4317 32, PropModeReplace, 0, NULL,
4323 XISetDevicePropertyDeletable(dev, prop_calibration, FALSE);
4325 prop_swap = MakeAtom(EVDEV_PROP_SWAP_AXES,
4326 strlen(EVDEV_PROP_SWAP_AXES), TRUE);
4328 rc = XIChangeDeviceProperty(dev, prop_swap, XA_INTEGER, 8,
4329 PropModeReplace, 1, &pEvdev->swap_axes, FALSE);
4333 XISetDevicePropertyDeletable(dev, prop_swap, FALSE);
4335 /* Axis labelling */
4336 if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
4339 Atom atoms[pEvdev->num_vals];
4341 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
4343 else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
4346 xf86IDrvMsg(pInfo, X_ERROR, "BUG: mode is neither absolute nor relative\n");
4350 EvdevInitAxesLabels(pEvdev, mode, pEvdev->num_vals, atoms);
4351 XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32,
4352 PropModeReplace, pEvdev->num_vals, atoms, FALSE);
4353 XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE);
4355 /* Button labelling */
4356 if ((pEvdev->num_buttons > 0) && (prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP)))
4358 Atom atoms[EVDEV_MAXBUTTONS];
4359 EvdevInitButtonLabels(pEvdev, EVDEV_MAXBUTTONS, atoms);
4360 XIChangeDeviceProperty(dev, prop_btn_label, XA_ATOM, 32,
4361 PropModeReplace, pEvdev->num_buttons, atoms, FALSE);
4362 XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE);
4368 EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
4371 InputInfoPtr pInfo = dev->public.devicePrivate;
4372 EvdevPtr pEvdev = pInfo->private;
4374 if (atom == prop_invert)
4377 if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
4382 data = (BOOL*)val->data;
4383 pEvdev->invert_x = data[0];
4384 pEvdev->invert_y = data[1];
4386 } else if (atom == prop_calibration)
4388 if (val->format != 32 || val->type != XA_INTEGER)
4390 if (val->size != 4 && val->size != 0)
4394 EvdevSetCalibration(pInfo, val->size, val->data);
4395 } else if (atom == prop_swap)
4397 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
4401 pEvdev->swap_axes = *((BOOL*)val->data);
4402 } else if (atom == prop_axis_label || atom == prop_btn_label ||
4403 atom == prop_product_id || atom == prop_device ||
4404 #ifdef _F_ENABLE_DEVICE_TYPE_PROP_
4405 atom == prop_virtual || atom == prop_device_type)
4406 #else /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
4407 atom == prop_virtual)
4408 #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
4409 return BadAccess; /* Read-only properties */
4410 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
4411 else if (atom == prop_transform)
4415 if (val->format != 32 || val->type != XIGetKnownProperty(XATOM_FLOAT)
4416 || ((val->size != 9) && (val->size != 1)))
4419 f = (float*)val->data;
4420 EvdevSetTransformMatrix(pInfo, val->size, f);
4423 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
4424 #ifdef _F_EVDEV_CONFINE_REGION_
4425 else if (atom == prop_confine_region)
4427 if (val->format != 32 || val->type != XA_INTEGER)
4429 if (val->size != 1 && val->size != 6)
4433 EvdevSetConfineRegion(pInfo, val->size, val->data);
4435 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
4436 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
4437 else if (atom == prop_relative_move_ack)
4439 if (val->format != 8 || val->type != XA_INTEGER)
4445 pEvdev->rel_move_ack = 1;
4447 #endif /* _F_ENABLE_REL_MOVE_STATUS_PROP_ */