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>
55 #ifdef _F_PROXY_DEVICE_ENABLED_
56 #include <xorg/optionstr.h>
57 #endif //_F_PROXY_DEVICE_ENABLED_
59 #include <xorgVersion.h>
62 #include <X11/Xatom.h>
63 #include <evdev-properties.h>
64 #include <xserver-properties.h>
66 #ifdef _F_EVDEV_CONFINE_REGION_
67 #include <xorg/mipointrst.h>
69 #define MIPOINTER(dev) \
70 ((!IsMaster(dev) && !dev->master) ? \
71 (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
72 (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
74 #endif /* _F_EVDEV_CONFINE_REGION_ */
76 #ifndef XI_PROP_PRODUCT_ID
77 #define XI_PROP_PRODUCT_ID "Device Product ID"
80 #ifndef XI_PROP_VIRTUAL_DEVICE
81 #define XI_PROP_VIRTUAL_DEVICE "Virtual Device"
84 #ifndef XI_PROP_DEVICE_TYPE
85 #define XI_PROP_DEVICE_TYPE "Device Type"
88 /* removed from server, purge when dropping support for server 1.10 */
89 #define XI86_SEND_DRAG_EVENTS 0x08
92 #include <inputstr.h> /* for MAX_DEVICES */
93 #define MAXDEVICES MAX_DEVICES
96 #ifdef _F_PICTURE_OFF_MODE_ENABLE_
97 #define XI_PROP_PICTURE_OFF_MODE "PICTURE_OFF_MODE"
98 static Atom atomPictureOffMode;
99 #endif //_F_PICTURE_OFF_MODE_ENABLE_
101 #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
103 #define MIN_KEYCODE 8
104 #define GLYPHS_PER_KEY 2
105 #define AltMask Mod1Mask
106 #define NumLockMask Mod2Mask
107 #define AltLangMask Mod3Mask
108 #define KanaMask Mod4Mask
109 #define ScrollLockMask Mod5Mask
115 #define COMPOSEFLAG 16
118 #define ABS_MT_SLOT 0x2f
121 #ifndef ABS_MT_TRACKING_ID
122 #define ABS_MT_TRACKING_ID 0x39
125 static char *evdevDefaults[] = {
132 /* Any of those triggers a proximity event */
133 static int proximity_bits[] = {
144 extern char * strcasestr(const char *haystack, const char *needle);
146 static int EvdevOn(DeviceIntPtr);
147 static int EvdevCache(InputInfoPtr pInfo);
148 static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
149 static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode);
150 static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab);
151 static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
152 static int EvdevOpenDevice(InputInfoPtr pInfo);
153 static void EvdevCloseDevice(InputInfoPtr pInfo);
155 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int mode, int natoms, Atom *atoms);
156 static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
157 static void EvdevInitProperty(DeviceIntPtr dev);
158 static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
159 XIPropertyValuePtr val, BOOL checkonly);
160 #ifdef _F_GESTURE_EXTENSION_
161 extern void mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e);
162 static void EvdevMTSync(InputInfoPtr pInfo, MTSyncType sync);
163 static BOOL EvdevMTStatusGet(InputInfoPtr pInfo, MTSyncType sync);
164 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
165 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
166 static void EvdevSetTransformMatrix(InputInfoPtr pInfo, int num_transform, float *tmatrix);
167 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
168 #ifdef _F_SUPPORT_ROTATION_ANGLE_
169 static void EvdevSetRotationAngle(EvdevPtr pEvdev, int angle);
170 #endif /* _F_SUPPORT_ROTATION_ANGLE_ */
171 #ifdef _F_EVDEV_CONFINE_REGION_
172 Bool IsMaster(DeviceIntPtr dev);
173 DeviceIntPtr GetPairedDevice(DeviceIntPtr dev);
174 DeviceIntPtr GetMaster(DeviceIntPtr dev, int which);
175 DeviceIntPtr GetMasterPointerFromId(int deviceid);
176 static void EvdevHookPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, BoxPtr pHotBox, BoxPtr pTopLeftBox);
177 static void EvdevHookPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox);
178 static void EvdevSetCursorLimits(InputInfoPtr pInfo, int region[6], int isSet);
179 static void EvdevSetConfineRegion(InputInfoPtr pInfo, int num_item, int region[6]);
182 static int num_slots(EvdevPtr pEvdev);
185 static Atom prop_confine_region = 0;
186 #endif /* _F_EVDEV_CONFINE_REGION_ */
187 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
188 static CARD32 EvdevRelativeMoveTimer(OsTimerPtr timer, CARD32 time, pointer arg);
189 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
190 #ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_
191 static BOOL isButtonPressed = FALSE;
192 #endif //_F_DONOT_SEND_RMA_BTN_RELEASE_
194 static Atom prop_product_id;
195 static Atom prop_invert;
196 static Atom prop_calibration;
197 static Atom prop_swap;
198 static Atom prop_axis_label;
199 static Atom prop_btn_label;
200 static Atom prop_device;
201 static Atom prop_virtual;
202 #ifdef _F_ENABLE_DEVICE_TYPE_PROP_
203 static Atom prop_device_type;
204 #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
205 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
206 static Atom prop_relative_move_status;
207 static Atom prop_relative_move_ack;
208 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
210 #ifdef _F_BLOCK_MOTION_DEVICE_
211 static Atom prop_block_motion_status; /* Atom to block motion device */
212 int block_motion_device = 0; /* Variable to set/unset of motion device */
213 #endif //_F_BLOCK_MOTION_DEVICE_
214 #ifdef _F_PICTURE_OFF_MODE_ENABLE_
216 #endif //_F_PICTURE_OFF_MODE_ENABLE_
217 #ifdef _F_BOOST_PULSE_
218 static int fd_boostpulse = 0;
219 #endif //_F_BOOST_PULSE_
221 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
222 static Atom prop_transform;
223 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
225 #ifdef _F_USE_DEFAULT_XKB_RULES_
226 static Atom prop_xkb_rules = None;
227 #endif //_F_USE_DEFAULT_XKB_RULES_
229 #ifdef _F_SUPPORT_ROTATION_ANGLE_
230 static Atom prop_rotation_angle = 0;
231 static Atom prop_rotation_node = 0;
232 #endif //_F_SUPPORT_ROTATION_ANGLE_
234 #ifdef _F_PROXY_DEVICE_ENABLED_
235 static Atom prop_use_proxy_slave_device;
236 static InputInfoPtr pCreatorInfo = NULL;
237 static InputInfoPtr pProxyDeviceInfo = NULL;
238 #define PROXY_DEV_NAME "HWKeys"
239 #define OPT_TYPE_VAL "ProxyDev"
241 static int EvdevSetProxyDevice(DeviceIntPtr dev, int val);
242 static InputOption *EvdevOptionDupConvert(pointer original);
243 static void EvdevFreeInputOpts(InputOption* opts);
244 static void EvdevReplaceOption(InputOption *opts,const char* key, char * value);
245 static InputInfoPtr EvdevCreateProxyDevice(InputInfoPtr pInfo);
246 static void EvdevProxydevReadInput(InputInfoPtr pInfo);
247 static void MakeClassesChangedEvent(DeviceChangedEvent *dce, DeviceIntPtr master, DeviceIntPtr slave, int flags);
248 #ifndef _F_PROXY_DEVICE_CHANGE_SOURCE_ID
249 static void EvdevPostDevChangeEvent(InputInfoPtr pInfo);
250 #else /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */
251 static void EvdevCheckDevChange(EvdevPtr pEvdev, int deviceid);
252 #endif /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */
253 #endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
255 /* All devices the evdev driver has allocated and knows about.
256 * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
257 * cannot be used by evdev, leaving us with a space of 2 at the end. */
258 static EvdevPtr evdev_devices[MAXDEVICES] = {NULL};
260 #ifdef _F_REMAP_KEYS_
262 remapKey(EvdevPtr ev, uint16_t code)
264 uint8_t slice=code/256;
265 uint8_t offs=code%256;
267 if (!ev->keyremap) return code;
268 if (!(ev->keyremap->sl[slice])) return code;
269 if (!(ev->keyremap->sl[slice]->cd[offs])) return code;
270 return ev->keyremap->sl[slice]->cd[offs];
274 addRemap(EvdevPtr ev,uint16_t code,uint8_t value)
276 uint8_t slice=code/256;
277 uint8_t offs=code%256;
280 ev->keyremap=(EvdevKeyRemapPtr)calloc(sizeof(EvdevKeyRemap),1);
281 if (!ev->keyremap) return;
283 if (!ev->keyremap->sl[slice]) {
284 ev->keyremap->sl[slice]=(EvdevKeyRemapSlice*)calloc(sizeof(EvdevKeyRemapSlice),1);
285 if (!ev->keyremap->sl[slice]) return;
287 ev->keyremap->sl[slice]->cd[offs]=value;
291 freeRemap(EvdevPtr ev)
294 if (!ev->keyremap) return;
295 for (slice=0;slice<256;++slice) {
296 if (!ev->keyremap->sl[slice]) continue;
297 free(ev->keyremap->sl[slice]);
302 #endif //_F_REMAP_KEYS_
304 static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode)
309 pInfo = device->public.devicePrivate;
310 pEvdev = pInfo->private;
312 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
314 if (mode == Relative)
322 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
326 pEvdev->flags |= EVDEV_RELATIVE_MODE;
336 static size_t EvdevCountBits(unsigned long *array, size_t nlongs)
341 for (i = 0; i < nlongs; i++) {
342 unsigned long x = array[i];
353 static inline int EvdevBitIsSet(const unsigned long *array, int bit)
355 return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
358 static inline void EvdevSetBit(unsigned long *array, int bit)
360 array[bit / LONG_BITS] |= (1LL << (bit % LONG_BITS));
364 EvdevGetMajorMinor(InputInfoPtr pInfo)
368 if (fstat(pInfo->fd, &st) == -1)
370 xf86IDrvMsg(pInfo, X_ERROR, "stat failed (%s). cannot check for duplicates.\n",
379 * Return TRUE if one of the devices we know about has the same min/maj
383 EvdevIsDuplicate(InputInfoPtr pInfo)
385 EvdevPtr pEvdev = pInfo->private;
386 EvdevPtr* dev = evdev_devices;
392 if ((*dev) != pEvdev &&
394 (*dev)->min_maj == pEvdev->min_maj)
403 * Add to internal device list.
406 EvdevAddDevice(InputInfoPtr pInfo)
408 EvdevPtr pEvdev = pInfo->private;
409 EvdevPtr* dev = evdev_devices;
418 * Remove from internal device list.
421 EvdevRemoveDevice(InputInfoPtr pInfo)
423 EvdevPtr pEvdev = pInfo->private;
424 EvdevPtr *dev = evdev_devices;
432 memmove(dev, dev + 1,
433 sizeof(evdev_devices) - (count * sizeof(EvdevPtr)));
442 SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
446 if ((s = xf86SetStrOption(pInfo->options, name, NULL))) {
457 EvdevDeviceIsVirtual(const char* devicenode)
459 struct udev *udev = NULL;
460 struct udev_device *device = NULL;
469 if (stat(devicenode, &st) < 0) {
470 ErrorF("Failed to get (%s)'s status (stat)\n", devicenode);
473 device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
479 devpath = udev_device_get_devpath(device);
483 if (strstr(devpath, "LNXSYSTM"))
487 udev_device_unref(device);
492 #ifndef HAVE_SMOOTH_SCROLLING
493 static int wheel_up_button = 4;
494 static int wheel_down_button = 5;
495 static int wheel_left_button = 6;
496 static int wheel_right_button = 7;
499 #ifdef _F_REMAP_KEYS_
501 SetRemapOption(InputInfoPtr pInfo,const char* name)
504 unsigned long int code,value;
506 EvdevPtr ev = pInfo->private;
508 s = xf86SetStrOption(pInfo->options, name, NULL);
516 while (sscanf(c," %li = %li %n",&code,&value,&consumed) > 1) {
519 xf86Msg(X_ERROR,"%s: input code %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,code);
522 if (value < MIN_KEYCODE || value > 255) {
523 xf86Msg(X_ERROR,"%s: output value %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,value);
526 xf86Msg(X_INFO,"%s: remapping %ld into %ld.\n",pInfo->name,code,value);
527 addRemap(ev,code,value-MIN_KEYCODE);
531 xf86Msg(X_ERROR, "%s: invalid input for option \"event_key_remap\" starting at '%s', ignoring.\n",
536 #endif //_F_REMAP_KEYS_
538 static EvdevEventQueuePtr
539 EvdevNextInQueue(InputInfoPtr pInfo)
541 EvdevPtr pEvdev = pInfo->private;
543 if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
545 xf86IDrvMsg(pInfo, X_NONE, "dropping event due to full queue!\n");
550 return &pEvdev->queue[pEvdev->num_queue - 1];
554 EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
556 #ifdef _F_REMAP_KEYS_
557 int code = remapKey((EvdevPtr)(pInfo->private),ev->code) + MIN_KEYCODE;
558 #else //_F_REMAP_KEYS_
559 int code = ev->code + MIN_KEYCODE;
560 #endif //_F_REMAP_KEYS_
561 EvdevEventQueuePtr pQueue;
563 /* Filter all repeated events from device.
564 We'll do softrepeat in the server, but only since 1.6 */
568 #ifdef _F_BOOST_PULSE_
569 if (fd_boostpulse && value == 1)
570 write(fd_boostpulse, (void *) "1", 1);
571 #endif //_F_BOOST_PULSE_
573 if ((pQueue = EvdevNextInQueue(pInfo)))
575 pQueue->type = EV_QUEUE_KEY;
576 pQueue->detail.key = code;
582 EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
584 EvdevEventQueuePtr pQueue;
586 #ifdef _F_BOOST_PULSE_
587 if (fd_boostpulse && value == 1)
588 write(fd_boostpulse, (void *) "1", 1);
589 #endif //_F_BOOST_PULSE_
591 if ((pQueue = EvdevNextInQueue(pInfo)))
593 pQueue->type = EV_QUEUE_BTN;
594 pQueue->detail.key = button;
600 EvdevQueueProximityEvent(InputInfoPtr pInfo, int value)
602 EvdevEventQueuePtr pQueue;
603 if ((pQueue = EvdevNextInQueue(pInfo)))
605 pQueue->type = EV_QUEUE_PROXIMITY;
606 pQueue->detail.key = 0;
613 EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask,
616 EvdevEventQueuePtr pQueue;
617 if ((pQueue = EvdevNextInQueue(pInfo)))
619 pQueue->type = EV_QUEUE_TOUCH;
620 pQueue->detail.touch = touch;
621 valuator_mask_copy(pQueue->touchMask, mask);
622 pQueue->val = evtype;
628 * Post button event right here, right now.
629 * Interface for MB emulation since these need to post immediately.
632 EvdevPostButtonEvent(InputInfoPtr pInfo, int button, enum ButtonAction act)
634 xf86PostButtonEvent(pInfo->dev, Relative, button,
635 (act == BUTTON_PRESS) ? 1 : 0, 0, 0);
639 EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
643 for (i = 0; i < count; i++) {
644 EvdevQueueButtonEvent(pInfo, button, 1);
645 EvdevQueueButtonEvent(pInfo, button, 0);
649 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
651 EvdevMappingGamepadAbsToKey(InputInfoPtr pInfo, struct input_event *ev)
653 EvdevPtr pEvdev = pInfo->private;
655 if (pEvdev->support_directional_key == FALSE)
658 if (ev->type != EV_ABS)
660 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid evtype(%d)\n", ev->type);
664 if (ev->code == ABS_HAT0X)
670 ev->code = KEY_RIGHT;
671 ev->value = EVDEV_PRESS;
672 pEvdev->pre_hatx = 1;
673 EvdevProcessEvent(pInfo, ev);
678 ev->value = EVDEV_PRESS;
679 pEvdev->pre_hatx = -1;
680 EvdevProcessEvent(pInfo, ev);
684 ev->code = ( (pEvdev->pre_hatx == 1)? KEY_RIGHT : KEY_LEFT);
685 ev->value = EVDEV_RELEASE;
686 pEvdev->pre_hatx = 0;
687 EvdevProcessEvent(pInfo, ev);
690 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid value\n");
695 else if(ev->code == ABS_HAT0Y)
702 ev->value = EVDEV_PRESS;
703 pEvdev->pre_haty = 1;
704 EvdevProcessEvent(pInfo, ev);
709 ev->value = EVDEV_PRESS;
710 pEvdev->pre_haty = -1;
711 EvdevProcessEvent(pInfo, ev);
715 ev->code = ( (pEvdev->pre_haty == 1)? KEY_DOWN : KEY_UP);
716 ev->value = EVDEV_RELEASE;
717 pEvdev->pre_haty = 0;
718 EvdevProcessEvent(pInfo, ev);
721 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid value\n");
726 else if(ev->code == ABS_X)
733 ev->value = EVDEV_PRESS;
735 EvdevProcessEvent(pInfo, ev);
738 if( pEvdev->pre_x == 255 || pEvdev->pre_x == 0 )
741 ev->code = ( (pEvdev->pre_x == 255)? KEY_RIGHT : KEY_LEFT);
742 ev->value = EVDEV_RELEASE;
744 EvdevProcessEvent(pInfo, ev);
749 ev->code = KEY_RIGHT;
750 ev->value = EVDEV_PRESS;
752 EvdevProcessEvent(pInfo, ev);
755 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid value\n");
760 else if(ev->code == ABS_Y)
767 ev->value = EVDEV_PRESS;
769 EvdevProcessEvent(pInfo, ev);
772 if( pEvdev->pre_y == 255 || pEvdev->pre_y == 0 )
775 ev->code = ( (pEvdev->pre_y == 255)? KEY_DOWN : KEY_UP);
776 ev->value = EVDEV_RELEASE;
778 EvdevProcessEvent(pInfo, ev);
784 ev->value = EVDEV_PRESS;
786 EvdevProcessEvent(pInfo, ev);
789 ErrorF("[EvdevMappingGamepadAbsToKey] Invalid value\n");
797 EvdevMappingGamepadKeyToKey(InputInfoPtr pInfo, struct input_event *ev)
799 EvdevPtr pEvdev = pInfo->private;
800 if(ev->type != EV_KEY)
802 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid type (%d)\n", ev->type);
805 if(ev->code == BTN_A)
807 if (pEvdev->keycode_btnA == 0)
809 ev->code = pEvdev->keycode_btnA;
816 ev->code = pEvdev->keycode_btnA;
817 ev->value = EVDEV_PRESS;
821 ev->code = pEvdev->keycode_btnA;
822 ev->value = EVDEV_RELEASE;
825 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
830 else if(ev->code == BTN_B)
832 if (pEvdev->keycode_btnB == 0)
834 ev->code = pEvdev->keycode_btnB;
841 ev->code = pEvdev->keycode_btnB;
842 ev->value = EVDEV_PRESS;
846 ev->code = pEvdev->keycode_btnB;
847 ev->value = EVDEV_RELEASE;
850 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
855 else if(ev->code == BTN_SELECT)
857 if (pEvdev->keycode_btnSelect == 0)
859 ev->code = pEvdev->keycode_btnSelect;
866 ev->code = pEvdev->keycode_btnSelect;
867 ev->value = EVDEV_PRESS;
871 ev->code = pEvdev->keycode_btnSelect;
872 ev->value = EVDEV_RELEASE;
875 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
880 else if(ev->code == BTN_START)
882 if (pEvdev->keycode_btnStart == 0)
884 ev->code = pEvdev->keycode_btnStart;
891 ev->code = pEvdev->keycode_btnStart;
892 ev->value = EVDEV_PRESS;
896 ev->code = pEvdev->keycode_btnStart;
897 ev->value = EVDEV_RELEASE;
900 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
905 else if(ev->code == 319)
907 if (pEvdev->keycode_btnPlay== 0)
909 ev->code = pEvdev->keycode_btnPlay;
916 ev->code = pEvdev->keycode_btnPlay;
917 ev->value = EVDEV_PRESS;
921 ev->code = pEvdev->keycode_btnPlay;
922 ev->value = EVDEV_RELEASE;
925 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
930 else if(ev->code == BTN_X)
932 if (pEvdev->keycode_btnX == 0)
934 ev->code = pEvdev->keycode_btnX;
941 ev->code = pEvdev->keycode_btnX;
942 ev->value = EVDEV_PRESS;
946 ev->code = pEvdev->keycode_btnX;
947 ev->value = EVDEV_RELEASE;
950 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
955 else if(ev->code == BTN_Y)
957 if (pEvdev->keycode_btnY == 0)
959 ev->code = pEvdev->keycode_btnY;
966 ev->code = pEvdev->keycode_btnY;
967 ev->value = EVDEV_PRESS;
971 ev->code = pEvdev->keycode_btnY;
972 ev->value = EVDEV_RELEASE;
975 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
980 else if(ev->code == BTN_TL)
982 if (pEvdev->keycode_btnTL== 0)
984 ev->code = pEvdev->keycode_btnTL;
991 ev->code = pEvdev->keycode_btnTL;
992 ev->value = EVDEV_PRESS;
996 ev->code = pEvdev->keycode_btnTL;
997 ev->value = EVDEV_RELEASE;
1000 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
1005 else if(ev->code == BTN_TR)
1007 if (pEvdev->keycode_btnTR == 0)
1009 ev->code = pEvdev->keycode_btnTR;
1016 ev->code = pEvdev->keycode_btnTR;
1017 ev->value = EVDEV_PRESS;
1021 ev->code = pEvdev->keycode_btnTR;
1022 ev->value = EVDEV_RELEASE;
1025 ErrorF("[EvdevMappingGamepadKeyToKey] Invalid value\n");
1031 #endif//_F_EVDEV_SUPPORT_GAMEPAD
1034 * Take the valuators and process them accordingly.
1037 EvdevProcessValuators(InputInfoPtr pInfo)
1040 EvdevPtr pEvdev = pInfo->private;
1041 int *delta = pEvdev->delta;
1043 /* convert to relative motion for touchpads */
1044 if (pEvdev->abs_queued && (pEvdev->flags & EVDEV_RELATIVE_MODE)) {
1045 if (pEvdev->in_proximity) {
1046 if (valuator_mask_isset(pEvdev->vals, 0))
1048 if (valuator_mask_isset(pEvdev->old_vals, 0))
1049 delta[REL_X] = valuator_mask_get(pEvdev->vals, 0) -
1050 valuator_mask_get(pEvdev->old_vals, 0);
1051 valuator_mask_set(pEvdev->old_vals, 0,
1052 valuator_mask_get(pEvdev->vals, 0));
1054 if (valuator_mask_isset(pEvdev->vals, 1))
1056 if (valuator_mask_isset(pEvdev->old_vals, 1))
1057 delta[REL_Y] = valuator_mask_get(pEvdev->vals, 1) -
1058 valuator_mask_get(pEvdev->old_vals, 1);
1059 valuator_mask_set(pEvdev->old_vals, 1,
1060 valuator_mask_get(pEvdev->vals, 1));
1063 valuator_mask_zero(pEvdev->old_vals);
1065 valuator_mask_zero(pEvdev->vals);
1066 pEvdev->abs_queued = 0;
1067 pEvdev->rel_queued = 1;
1070 if (pEvdev->rel_queued) {
1073 if (pEvdev->swap_axes) {
1074 tmp = pEvdev->delta[REL_X];
1075 pEvdev->delta[REL_X] = pEvdev->delta[REL_Y];
1076 pEvdev->delta[REL_Y] = tmp;
1077 if (pEvdev->delta[REL_X] == 0)
1078 valuator_mask_unset(pEvdev->vals, REL_X);
1079 if (pEvdev->delta[REL_Y] == 0)
1080 valuator_mask_unset(pEvdev->vals, REL_Y);
1082 if (pEvdev->invert_x)
1083 pEvdev->delta[REL_X] *= -1;
1084 if (pEvdev->invert_y)
1085 pEvdev->delta[REL_Y] *= -1;
1088 Evdev3BEmuProcessRelMotion(pInfo,
1089 pEvdev->delta[REL_X],
1090 pEvdev->delta[REL_Y]);
1092 for (i = 0; i < REL_CNT; i++)
1094 int map = pEvdev->axis_map[i];
1095 if (pEvdev->delta[i] && map != -1)
1096 valuator_mask_set(pEvdev->vals, map, pEvdev->delta[i]);
1100 * Some devices only generate valid abs coords when BTN_TOOL_PEN is
1101 * pressed. On wacom tablets, this means that the pen is in
1102 * proximity of the tablet. After the pen is removed, BTN_TOOL_PEN is
1103 * released, and a (0, 0) absolute event is generated. Checking
1104 * pEvdev->in_proximity here lets us ignore that event. pEvdev is
1105 * initialized to 1 so devices that don't use this scheme still
1108 else if (pEvdev->abs_queued && pEvdev->in_proximity) {
1111 if (pEvdev->swap_axes) {
1112 int swapped_isset[2] = {0, 0};
1113 int swapped_values[2];
1115 for(i = 0; i <= 1; i++)
1116 if (valuator_mask_isset(pEvdev->vals, i)) {
1117 swapped_isset[1 - i] = 1;
1118 swapped_values[1 - i] =
1119 xf86ScaleAxis(valuator_mask_get(pEvdev->vals, i),
1120 pEvdev->absinfo[1 - i].maximum,
1121 pEvdev->absinfo[1 - i].minimum,
1122 pEvdev->absinfo[i].maximum,
1123 pEvdev->absinfo[i].minimum);
1126 for (i = 0; i <= 1; i++)
1127 if (swapped_isset[i])
1128 valuator_mask_set(pEvdev->vals, i, swapped_values[i]);
1130 valuator_mask_unset(pEvdev->vals, i);
1133 for (i = 0; i <= 1; i++) {
1138 if (!valuator_mask_isset(pEvdev->vals, i))
1141 val = valuator_mask_get(pEvdev->vals, i);
1144 calib_min = pEvdev->calibration.min_x;
1145 calib_max = pEvdev->calibration.max_x;
1147 calib_min = pEvdev->calibration.min_y;
1148 calib_max = pEvdev->calibration.max_y;
1151 if (pEvdev->flags & EVDEV_CALIBRATED)
1152 val = xf86ScaleAxis(val, pEvdev->absinfo[i].maximum,
1153 pEvdev->absinfo[i].minimum, calib_max,
1156 if ((i == 0 && pEvdev->invert_x) || (i == 1 && pEvdev->invert_y))
1157 val = (pEvdev->absinfo[i].maximum - val +
1158 pEvdev->absinfo[i].minimum);
1160 valuator_mask_set(pEvdev->vals, i, val);
1162 Evdev3BEmuProcessAbsMotion(pInfo, pEvdev->vals);
1167 EvdevProcessProximityEvent(InputInfoPtr pInfo, struct input_event *ev)
1169 EvdevPtr pEvdev = pInfo->private;
1171 if (!pEvdev->use_proximity)
1174 pEvdev->prox_queued = 1;
1176 EvdevQueueProximityEvent(pInfo, ev->value);
1180 * Proximity handling is rather weird because of tablet-specific issues.
1181 * Some tablets, notably Wacoms, send a 0/0 coordinate in the same EV_SYN as
1182 * the out-of-proximity notify. We need to ignore those, hence we only
1183 * actually post valuator events when we're in proximity.
1185 * Other tablets send the x/y coordinates, then EV_SYN, then the proximity
1186 * event. For those, we need to remember x/y to post it when the proximity
1189 * If we're not in proximity and we get valuator events, remember that, they
1190 * won't be posted though. If we move into proximity without valuators, use
1191 * the last ones we got and let the rest of the code post them.
1194 EvdevProcessProximityState(InputInfoPtr pInfo)
1196 EvdevPtr pEvdev = pInfo->private;
1200 /* Does this device have any proximity axes? */
1204 /* no proximity change in the queue */
1205 if (!pEvdev->prox_queued)
1207 if (pEvdev->abs_queued && !pEvdev->in_proximity)
1208 for (i = 0; i < valuator_mask_size(pEvdev->vals); i++)
1209 if (valuator_mask_isset(pEvdev->vals, i))
1210 valuator_mask_set(pEvdev->prox, i,
1211 valuator_mask_get(pEvdev->vals, i));
1215 for (i = 0; i < pEvdev->num_queue; i++)
1217 if (pEvdev->queue[i].type == EV_QUEUE_PROXIMITY)
1219 prox_state = pEvdev->queue[i].val;
1224 if ((prox_state && !pEvdev->in_proximity) ||
1225 (!prox_state && pEvdev->in_proximity))
1227 /* We're about to go into/out of proximity but have no abs events
1228 * within the EV_SYN. Use the last coordinates we have. */
1229 for (i = 0; i < valuator_mask_size(pEvdev->prox); i++)
1230 if (!valuator_mask_isset(pEvdev->vals, i) &&
1231 valuator_mask_isset(pEvdev->prox, i))
1232 valuator_mask_set(pEvdev->vals, i,
1233 valuator_mask_get(pEvdev->prox, i));
1234 valuator_mask_zero(pEvdev->prox);
1236 pEvdev->abs_queued = valuator_mask_size(pEvdev->vals);
1239 pEvdev->in_proximity = prox_state;
1244 * Take a button input event and process it accordingly.
1247 EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
1249 unsigned int button;
1251 EvdevPtr pEvdev = pInfo->private;
1253 button = EvdevUtilButtonEventToButtonNumber(pEvdev, ev->code);
1255 /* Get the signed value, earlier kernels had this as unsigned */
1258 /* Handle drag lock */
1259 if (EvdevDragLockFilterEvent(pInfo, button, value))
1262 if (EvdevWheelEmuFilterButton(pInfo, button, value))
1265 if (EvdevMBEmuFilterEvent(pInfo, button, value))
1269 #ifdef _F_PICTURE_OFF_MODE_ENABLE_
1270 if((pictureOffMode == 1) && (button == 1)) {
1272 /* Send right button press and release instead of left button press/release */
1274 EvdevQueueButtonEvent(pInfo, button, 1);
1275 EvdevQueueButtonEvent(pInfo, button, 0);
1276 } else ; /* Do nothing Ignore the left button press event */
1279 /* When button is pressed, cancel timer for cursor hide*/
1281 isButtonPressed = TRUE;
1283 isButtonPressed = FALSE;
1284 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1285 TimerCancel(pEvdev->rel_move_timer);
1286 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1287 pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo);
1288 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1290 EvdevQueueButtonEvent(pInfo, button, value);
1292 #else //_F_PICTURE_OFF_MODE_ENABLE_
1293 EvdevQueueButtonEvent(pInfo, button, value);
1294 #endif //_F_PICTURE_OFF_MODE_ENABLE_
1297 EvdevQueueKbdEvent(pInfo, ev, value);
1301 * Take the relative motion input event and process it accordingly.
1304 EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
1307 EvdevPtr pEvdev = pInfo->private;
1310 TTRACE_BEGIN("XORG:EVDEV:PROCESS_REL_MOTION");
1312 /* Get the signed value, earlier kernels had this as unsigned */
1316 #ifndef HAVE_SMOOTH_SCROLLING
1319 EvdevQueueButtonClicks(pInfo, wheel_up_button, value);
1321 EvdevQueueButtonClicks(pInfo, wheel_down_button, -value);
1327 EvdevQueueButtonClicks(pInfo, wheel_right_button, value);
1329 EvdevQueueButtonClicks(pInfo, wheel_left_button, -value);
1331 /* We don't post wheel events as axis motion. */
1334 /* Ignore EV_REL events if we never set up for them. */
1335 if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS)) {
1340 /* Handle mouse wheel emulation */
1341 if (EvdevWheelEmuFilterMotion(pInfo, ev)) {
1346 pEvdev->rel_queued = 1;
1347 pEvdev->delta[ev->code] += value;
1348 map = pEvdev->axis_map[ev->code];
1349 valuator_mask_set(pEvdev->vals, map, value);
1357 EvdevProcessTouch(InputInfoPtr pInfo)
1359 EvdevPtr pEvdev = pInfo->private;
1362 if (pEvdev->cur_slot < 0 || !pEvdev->mt_mask)
1365 /* If the ABS_MT_SLOT is the first event we get after EV_SYN, skip this */
1366 if (pEvdev->slot_state == SLOTSTATE_EMPTY)
1369 if (pEvdev->slot_state == SLOTSTATE_CLOSE)
1371 else if (pEvdev->slot_state == SLOTSTATE_OPEN)
1372 type = XI_TouchBegin;
1374 type = XI_TouchUpdate;
1376 EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, type);
1378 pEvdev->slot_state = SLOTSTATE_EMPTY;
1380 valuator_mask_zero(pEvdev->mt_mask);
1384 num_slots(EvdevPtr pEvdev)
1388 if (pEvdev->mtdev) {
1389 value = pEvdev->mtdev->caps.slot.maximum + 1;
1392 value= pEvdev->absinfo[ABS_MT_SLOT].maximum -
1393 pEvdev->absinfo[ABS_MT_SLOT].minimum + 1;
1396 /* If we don't know how many slots there are, assume at least 10 */
1397 return value > 1 ? value : 10;
1401 last_mt_vals_slot(EvdevPtr pEvdev)
1403 int value = pEvdev->cur_slot - pEvdev->absinfo[ABS_MT_SLOT].minimum;
1405 return value < num_slots(pEvdev) ? value : -1;
1409 EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
1411 EvdevPtr pEvdev = pInfo->private;
1414 if (ev->code == ABS_MT_SLOT) {
1415 EvdevProcessTouch(pInfo);
1416 pEvdev->cur_slot = ev->value;
1419 int slot_index = last_mt_vals_slot(pEvdev);
1421 if (pEvdev->slot_state == SLOTSTATE_EMPTY)
1422 pEvdev->slot_state = SLOTSTATE_UPDATE;
1423 if (ev->code == ABS_MT_TRACKING_ID) {
1424 if (ev->value >= 0) {
1425 pEvdev->slot_state = SLOTSTATE_OPEN;
1427 if (slot_index >= 0)
1428 valuator_mask_copy(pEvdev->mt_mask,
1429 pEvdev->last_mt_vals[slot_index]);
1431 xf86IDrvMsg(pInfo, X_WARNING,
1432 "Attempted to copy values from out-of-range "
1433 "slot, touch events may be incorrect.\n");
1435 pEvdev->slot_state = SLOTSTATE_CLOSE;
1437 map = pEvdev->axis_map[ev->code];
1438 valuator_mask_set(pEvdev->mt_mask, map, ev->value);
1439 if (slot_index >= 0)
1440 valuator_mask_set(pEvdev->last_mt_vals[slot_index], map,
1446 #define EvdevProcessTouch(pInfo)
1447 #define EvdevProcessTouchEvent(pInfo, ev)
1448 #endif /* MULTITOUCH */
1451 * Take the absolute motion input event and process it accordingly.
1454 EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
1457 EvdevPtr pEvdev = pInfo->private;
1460 TTRACE_BEGIN("XORG:EVDEV:PROCESS_ABS_MOTION");
1462 /* Get the signed value, earlier kernels had this as unsigned */
1464 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
1465 if(pEvdev->flags & EVDEV_GAMEPAD)
1467 EvdevMappingGamepadAbsToKey(pInfo, ev);
1470 #endif//_F_EVDEV_SUPPORT_GAMEPAD
1472 /* Ignore EV_ABS events if we never set up for them. */
1473 if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
1476 if (ev->code > ABS_MAX)
1479 if (EvdevWheelEmuFilterMotion(pInfo, ev))
1482 if (ev->code >= ABS_MT_SLOT) {
1483 EvdevProcessTouchEvent(pInfo, ev);
1484 pEvdev->abs_queued = 1;
1485 } else if (!pEvdev->mt_mask) {
1486 map = pEvdev->axis_map[ev->code];
1490 xf86IDrvMsg(pInfo, X_INFO, "[EvdevProcessAbsoluteMotionEvent] Invalid valuator (=%d), value=%d\nThis is going to be skipped.", map, value);
1494 valuator_mask_set(pEvdev->vals, map, value);
1495 pEvdev->abs_queued = 1;
1502 * Take the key press/release input event and process it accordingly.
1505 EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
1508 EvdevPtr pEvdev = pInfo->private;
1510 TTRACE_BEGIN("XORG:EVDEV:PROCESS_KEY_MOTION");
1512 /* Get the signed value, earlier kernels had this as unsigned */
1515 /* don't repeat mouse buttons */
1516 if (ev->code >= BTN_MOUSE && ev->code < KEY_OK) {
1521 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
1522 if(pEvdev->flags & EVDEV_GAMEPAD)
1524 EvdevMappingGamepadKeyToKey(pInfo, ev);
1525 if (ev->code == 0) {
1529 #endif//_F_EVDEV_SUPPORT_GAMEPAD
1532 for (i = 0; i < ArrayLength(proximity_bits); i++)
1534 if (ev->code == proximity_bits[i])
1536 EvdevProcessProximityEvent(pInfo, ev);
1543 /* For devices that have but don't use proximity, use
1544 * BTN_TOUCH as the proximity notifier */
1545 if (!pEvdev->use_proximity)
1546 pEvdev->in_proximity = value ? ev->code : 0;
1547 if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)) ||
1550 /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
1552 ev->code = BTN_LEFT;
1553 /* Intentional fallthrough! */
1556 EvdevProcessButtonEvent(pInfo, ev);
1563 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
1565 EvdevRelativeMoveTimer(OsTimerPtr timer, CARD32 time, pointer arg)
1567 InputInfoPtr pInfo = (InputInfoPtr)arg;
1570 if(pInfo) pEvdev = pInfo->private;
1573 if(!pEvdev) return 0;
1574 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1575 if(pEvdev->rel_move_timer)
1576 TimerCancel(pEvdev->rel_move_timer);
1577 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1578 #ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_
1579 if(!isButtonPressed)
1581 #endif //_F_DONOT_SEND_RMA_BTN_RELEASE_
1582 pEvdev->rel_move_status = 0;
1583 if (pEvdev->rel_move_ack != 2)
1584 pEvdev->rel_move_ack = 0;
1585 int rc = XIDeleteDeviceProperty(pInfo->dev, prop_relative_move_status, TRUE);
1588 { if (pEvdev->rel_move_ack != 2)
1589 pEvdev->rel_move_ack = 0;
1590 xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to delete device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, prop_relative_move_status);
1592 #ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_
1594 #endif //_F_DONOT_SEND_RMA_BTN_RELEASE_
1598 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
1600 #ifdef _F_GESTURE_EXTENSION_
1601 static BOOL EvdevMTStatusGet(InputInfoPtr pInfo, MTSyncType sync)
1606 const int first_press = XI_TouchEnd - XI_TouchBegin;
1607 EvdevPtr pEvdev = pInfo->private;
1609 if (!pEvdev || !pEvdev->mt_status )
1612 nslots = num_slots(pEvdev);
1613 for(i = 0; i < nslots; i++)
1615 pressed += pEvdev->mt_status[i];
1617 if (pressed > first_press)
1621 if ((sync == MTOUCH_FRAME_SYNC_BEGIN) && (pressed == first_press))
1624 if ((sync == MTOUCH_FRAME_SYNC_END) && !pressed)
1630 static void EvdevMTSync(InputInfoPtr pInfo, MTSyncType sync)
1634 memset(&event, 0, sizeof(event));
1635 event.header = ET_Internal;
1636 event.type = ET_MTSync;
1637 event.length = sizeof(event);
1638 event.time = GetTimeInMillis();
1639 event.deviceid = pInfo->dev->id;
1642 mieqEnqueue (pInfo->dev, (InternalEvent*)&event);
1644 #ifdef __MTSYNC_DEBUG__
1645 xf86IDrvMsg(pInfo, X_INFO, "[EvdevMTSync] %s has been sent !\n",
1646 (sync==MTOUCH_FRAME_SYNC_BEGIN) ? "MTOUCH_FRAME_SYNC_BEGIN" : "MTOUCH_FRAME_SYNC_END");
1647 #endif /* #ifdef __MTSYNC_DEBUG__ */
1649 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
1652 EvdevBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
1654 InputInfoPtr pInfo = (InputInfoPtr)data;
1655 EvdevPtr pEvdev = pInfo->private;
1657 RemoveBlockAndWakeupHandlers(EvdevBlockHandler,
1658 (WakeupHandlerProcPtr)NoopDDA,
1660 pEvdev->block_handler_registered = FALSE;
1661 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);
1664 int rc = XIChangeDeviceProperty(pInfo->dev, prop_relative_move_status, XA_INTEGER, 8,
1665 PropModeReplace, 1, &pEvdev->rel_move_status, TRUE);
1669 xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, prop_relative_move_status);
1674 * Post the relative motion events.
1677 EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
1678 int v[MAX_VALUATORS])
1680 EvdevPtr pEvdev = pInfo->private;
1682 #ifdef _F_BLOCK_MOTION_DEVICE_
1683 if (pEvdev->rel_queued && (block_motion_device ==0)) {
1684 #else //_F_BLOCK_MOTION_DEVICE_
1685 if (pEvdev->rel_queued) {
1686 #endif //_F_BLOCK_MOTION_DEVICE_
1687 #ifdef _F_EVDEV_SUPPORT_ROTARY_
1688 if (pEvdev->flags & EVDEV_OFM) {
1689 pEvdev->extra_rel_post_ofm(pInfo, num_v, first_v, v);
1693 if (pEvdev->flags & EVDEV_HALLIC) {
1694 pEvdev->extra_rel_post_hallic(pInfo, num_v, first_v, v);
1697 #endif //_F_EVDEV_SUPPORT_ROTARY_
1698 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
1699 if(!pEvdev->rel_move_prop_set)
1700 pEvdev->rel_move_prop_set = 1;
1702 if((!pEvdev->block_handler_registered) && (!pEvdev->rel_move_status || !pEvdev->rel_move_ack))
1704 pEvdev->rel_move_status = 1;
1705 pEvdev->block_handler_registered = TRUE;
1706 RegisterBlockAndWakeupHandlers(EvdevBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
1709 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1710 TimerCancel(pEvdev->rel_move_timer);
1711 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1712 pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo);
1713 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1714 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
1715 xf86PostMotionEventM(pInfo->dev, Relative, pEvdev->vals);
1720 * Post the absolute motion events.
1723 EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
1724 int v[MAX_VALUATORS])
1726 EvdevPtr pEvdev = pInfo->private;
1729 * Some devices only generate valid abs coords when BTN_TOOL_PEN is
1730 * pressed. On wacom tablets, this means that the pen is in
1731 * proximity of the tablet. After the pen is removed, BTN_TOOL_PEN is
1732 * released, and a (0, 0) absolute event is generated. Checking
1733 * pEvdev->in_proximity here lets us ignore that event.
1734 * pEvdev->in_proximity is initialized to 1 so devices that don't use
1735 * this scheme still just work.
1737 #ifdef _F_BLOCK_MOTION_DEVICE_
1738 if (pEvdev->abs_queued && pEvdev->in_proximity && block_motion_device == 0 ) {
1739 #else //_F_BLOCK_MOTION_DEVICE_
1740 if (pEvdev->abs_queued && pEvdev->in_proximity) {
1741 #endif //_F_BLOCK_MOTION_DEVICE_
1742 xf86PostMotionEventM(pInfo->dev, Absolute, pEvdev->vals);
1747 EvdevPostProximityEvents(InputInfoPtr pInfo, int which, int num_v, int first_v,
1748 int v[MAX_VALUATORS])
1751 EvdevPtr pEvdev = pInfo->private;
1753 for (i = 0; pEvdev->prox_queued && i < pEvdev->num_queue; i++) {
1754 switch (pEvdev->queue[i].type) {
1758 case EV_QUEUE_TOUCH:
1761 case EV_QUEUE_PROXIMITY:
1762 if (pEvdev->queue[i].val == which)
1763 xf86PostProximityEventP(pInfo->dev, which, first_v, num_v,
1771 * Post the queued key/button events.
1773 static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v,
1774 int v[MAX_VALUATORS])
1777 #ifdef _F_GESTURE_EXTENSION_
1782 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
1783 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
1787 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
1789 EvdevPtr pEvdev = pInfo->private;
1791 #ifdef _F_PROXY_DEVICE_ENABLED_
1792 #ifdef _F_PROXY_DEVICE_CHANGE_SOURCE_ID
1798 EvdevCheckDevChange(pEvdev, pInfo->dev->id);
1800 if(pEvdev->proxy_device){
1801 EvdevPostDevChangeEvent(pEvdev->proxy_device);
1804 #endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
1806 for (i = 0; i < pEvdev->num_queue; i++) {
1807 switch (pEvdev->queue[i].type) {
1809 xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].detail.key,
1810 pEvdev->queue[i].val);
1813 if (Evdev3BEmuFilterEvent(pInfo,
1814 pEvdev->queue[i].detail.key,
1815 pEvdev->queue[i].val))
1818 if (pEvdev->abs_queued && pEvdev->in_proximity) {
1819 xf86PostButtonEventP(pInfo->dev, Absolute, pEvdev->queue[i].detail.key,
1820 pEvdev->queue[i].val, first_v, num_v,
1824 xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].detail.key,
1825 pEvdev->queue[i].val, 0, 0);
1828 case EV_QUEUE_PROXIMITY:
1831 case EV_QUEUE_TOUCH:
1832 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
1833 if( pEvdev->use_transform )
1837 x = valuator_mask_get(pEvdev->queue[i].touchMask, 0);
1838 y = valuator_mask_get(pEvdev->queue[i].touchMask, 1);
1842 slot = pEvdev->queue[i].detail.touch;
1843 x = valuator_mask_get(pEvdev->last_mt_vals[slot], 0);
1844 y = valuator_mask_get(pEvdev->last_mt_vals[slot], 1);
1846 p.vector[0] = pixman_int_to_fixed(x);
1847 p.vector[1] = pixman_int_to_fixed(y);
1848 p.vector[2] = pixman_int_to_fixed(1);
1850 pixman_transform_point(&pEvdev->inv_transform, &p);
1852 valuator_mask_set(pEvdev->queue[i].touchMask, 0, pixman_fixed_to_int(p.vector[0]));
1853 valuator_mask_set(pEvdev->queue[i].touchMask, 1, pixman_fixed_to_int(p.vector[1]));
1856 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
1857 #ifdef _F_GESTURE_EXTENSION_
1859 event_type = pEvdev->queue[i].val;
1860 slot_idx = pEvdev->queue[i].detail.touch;
1862 if (pEvdev->mt_status)
1864 pEvdev->mt_status[slot_idx] = XI_TouchEnd - event_type;
1866 if ((XI_TouchBegin == event_type) && (slot_idx == 0))
1868 if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_BEGIN))
1870 sync_value = MTOUCH_FRAME_SYNC_BEGIN;
1871 EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN);
1875 xf86PostTouchEvent(pInfo->dev, slot_idx,
1877 pEvdev->queue[i].touchMask);
1879 if ((sync_value < 0) && (XI_TouchEnd == event_type))
1881 if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_END))
1883 EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_END);
1887 EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_UPDATE);
1891 #else /* #ifdef _F_GESTURE_EXTENSION_ */
1892 xf86PostTouchEvent(pInfo->dev, pEvdev->queue[i].detail.touch,
1893 pEvdev->queue[i].val, 0,
1894 pEvdev->queue[i].touchMask);
1895 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
1903 * Take the synchronization input event and process it accordingly; the motion
1904 * notify events are sent first, then any button/key press/release events.
1907 EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
1910 int num_v = 0, first_v = 0;
1911 int v[MAX_VALUATORS] = {};
1912 EvdevPtr pEvdev = pInfo->private;
1913 TTRACE_BEGIN("XORG:EVDEV:PROCESS_SYNC_MOTION");
1915 EvdevProcessProximityState(pInfo);
1917 EvdevProcessValuators(pInfo);
1918 EvdevProcessTouch(pInfo);
1920 EvdevPostProximityEvents(pInfo, TRUE, num_v, first_v, v);
1921 EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v);
1922 EvdevPostAbsoluteMotionEvents(pInfo, num_v, first_v, v);
1923 EvdevPostQueuedEvents(pInfo, num_v, first_v, v);
1924 EvdevPostProximityEvents(pInfo, FALSE, num_v, first_v, v);
1926 memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
1927 for (i = 0; i < ArrayLength(pEvdev->queue); i++)
1929 EvdevEventQueuePtr queue = &pEvdev->queue[i];
1930 queue->detail.key = 0;
1933 /* don't reset the touchMask */
1937 valuator_mask_zero(pEvdev->vals);
1938 pEvdev->num_queue = 0;
1939 pEvdev->abs_queued = 0;
1940 pEvdev->rel_queued = 0;
1941 pEvdev->prox_queued = 0;
1947 * Process the events from the device; nothing is actually posted to the server
1948 * until an EV_SYN event is received.
1951 EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
1953 TTRACE_BEGIN("XORG:EVDEV:PROCESS_EVENT");
1955 EvdevPtr pEvdev = pInfo->private;
1958 #ifdef _F_EVDEV_SUPPORT_SMARTRC_
1959 if (pEvdev->extra_input_process) {
1960 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
1961 result = pEvdev->extra_input_process(&pInfo, ev);
1963 result = pEvdev->extra_input_process(pInfo, ev);
1969 #endif //_F_EVDEV_SUPPORT_SMARTRC_
1971 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
1972 if (pEvdev->rel_move_ack == 2) {
1973 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1974 TimerCancel(pEvdev->rel_move_timer);
1975 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
1976 pEvdev->rel_move_status = 0;
1980 #endif//_F_ENABLE_REL_MOVE_STATUS_PROP_
1983 EvdevProcessRelativeMotionEvent(pInfo, ev);
1986 EvdevProcessAbsoluteMotionEvent(pInfo, ev);
1989 EvdevProcessKeyEvent(pInfo, ev);
1992 EvdevProcessSyncEvent(pInfo, ev);
2003 EvdevFreeMasks(EvdevPtr pEvdev)
2009 valuator_mask_free(&pEvdev->vals);
2010 valuator_mask_free(&pEvdev->old_vals);
2011 valuator_mask_free(&pEvdev->prox);
2013 valuator_mask_free(&pEvdev->mt_mask);
2014 if (pEvdev->last_mt_vals)
2016 for (i = 0; i < num_slots(pEvdev); i++)
2017 valuator_mask_free(&pEvdev->last_mt_vals[i]);
2018 free(pEvdev->last_mt_vals);
2019 pEvdev->last_mt_vals = NULL;
2021 for (i = 0; i < EVDEV_MAXQUEUE; i++)
2022 valuator_mask_free(&pEvdev->queue[i].touchMask);
2026 /* just a magic number to reduce the number of reads */
2027 #define NUM_EVENTS 16
2030 EvdevReadInput(InputInfoPtr pInfo)
2032 struct input_event ev[NUM_EVENTS];
2033 int i, len = sizeof(ev);
2035 TTRACE_BEGIN("XORG:EVDEV:READ_INPUT");
2037 while (len == sizeof(ev))
2040 EvdevPtr pEvdev = pInfo->private;
2043 len = mtdev_get(pEvdev->mtdev, pInfo->fd, ev, NUM_EVENTS) *
2044 sizeof(struct input_event);
2047 len = read(pInfo->fd, &ev, sizeof(ev));
2051 if (errno == ENODEV) /* May happen after resume */
2053 EvdevMBEmuFinalize(pInfo);
2054 Evdev3BEmuFinalize(pInfo);
2055 xf86RemoveEnabledDevice(pInfo);
2057 else if (errno != EAGAIN)
2059 /* We use X_NONE here because it doesn't alloc */
2060 xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
2066 /* The kernel promises that we always only read a complete
2067 * event, so len != sizeof ev is an error. */
2068 if (len % sizeof(ev[0])) {
2069 /* We use X_NONE here because it doesn't alloc */
2070 xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, strerror(errno));
2074 for (i = 0; i < len/sizeof(ev[0]); i++)
2075 EvdevProcessEvent(pInfo, &ev[i]);
2081 EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
2083 /* Nothing to do, dix handles all settings */
2087 EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
2089 static struct { int xbit, code; } bits[] = {
2090 { CAPSFLAG, LED_CAPSL },
2091 { NUMFLAG, LED_NUML },
2092 { SCROLLFLAG, LED_SCROLLL },
2093 { MODEFLAG, LED_KANA },
2094 { COMPOSEFLAG, LED_COMPOSE }
2098 struct input_event ev[ArrayLength(bits)];
2101 memset(ev, 0, sizeof(ev));
2103 pInfo = device->public.devicePrivate;
2104 for (i = 0; i < ArrayLength(bits); i++) {
2105 ev[i].type = EV_LED;
2106 ev[i].code = bits[i].code;
2107 ev[i].value = (ctrl->leds & bits[i].xbit) > 0;
2110 write(pInfo->fd, ev, sizeof ev);
2113 #ifdef _F_USE_DEFAULT_XKB_RULES_
2115 EvdevGetXkbRules(DeviceIntPtr device, XkbRMLVOSet * rmlvo)
2117 WindowPtr root=NULL;
2121 if(screenInfo.numScreens > 0 && screenInfo.screens[0])
2123 root = screenInfo.screens[0]->root;
2128 if( prop_xkb_rules == None )
2129 prop_xkb_rules = MakeAtom("_XKB_RULES_NAMES", strlen("_XKB_RULES_NAMES"), TRUE);
2131 rc = dixLookupProperty (&pProp, root, prop_xkb_rules, serverClient, DixReadAccess);
2132 if (rc == Success && pProp->data){
2133 keymap = (char *)pProp->data;
2134 rmlvo->rules = keymap;
2135 keymap = keymap+strlen(keymap)+1;
2136 rmlvo->model = keymap;
2137 keymap = keymap+strlen(keymap)+1;
2138 rmlvo->layout = keymap;
2139 keymap = keymap+strlen(keymap)+1;
2140 rmlvo->variant = keymap;
2141 keymap = keymap+strlen(keymap)+1;
2142 rmlvo->options = keymap;
2146 XkbGetRulesDflts(rmlvo);
2149 #endif //_F_USE_DEFAULT_XKB_RULES_
2152 EvdevAddKeyClass(DeviceIntPtr device)
2157 pInfo = device->public.devicePrivate;
2158 pEvdev = pInfo->private;
2160 #ifdef _F_USE_DEFAULT_XKB_RULES_
2161 XkbRMLVOSet dflts = { NULL };
2163 if (pEvdev->use_default_xkb_rmlvo)
2165 EvdevGetXkbRules(device, &dflts);
2167 pEvdev->rmlvo.rules = (dflts.rules) ? strdup(dflts.rules) : NULL;
2168 pEvdev->rmlvo.model = (dflts.model) ? strdup(dflts.model) : NULL;
2169 pEvdev->rmlvo.layout = (dflts.layout) ? strdup(dflts.layout) : NULL;
2170 pEvdev->rmlvo.variant = (dflts.variant) ? strdup(dflts.variant) : NULL;
2171 pEvdev->rmlvo.options = (dflts.options) ? strdup(dflts.options) : NULL;
2173 ErrorF("[%s] Set default XKB RMLVO !\n", __FUNCTION__);
2175 ErrorF("[%s] pEvdev->rmlvo.rules=%s\n", __FUNCTION__, pEvdev->rmlvo.rules ? pEvdev->rmlvo.rules : "NULL");
2176 ErrorF("[%s] pEvdev->rmlvo.model=%s\n", __FUNCTION__, pEvdev->rmlvo.model ? pEvdev->rmlvo.model : "NULL");
2177 ErrorF("[%s] pEvdev->rmlvo.layout=%s\n", __FUNCTION__, pEvdev->rmlvo.layout ? pEvdev->rmlvo.layout : "NULL");
2178 ErrorF("[%s] pEvdev->rmlvo.variant=%s\n", __FUNCTION__, pEvdev->rmlvo.variant ? pEvdev->rmlvo.variant : "NULL");
2179 ErrorF("[%s] pEvdev->rmlvo.options=%s\n", __FUNCTION__, pEvdev->rmlvo.options ? pEvdev->rmlvo.options : "NULL");
2184 /* sorry, no rules change allowed for you */
2185 xf86ReplaceStrOption(pInfo->options, "xkb_rules", "evdev");
2186 SetXkbOption(pInfo, "xkb_rules", &pEvdev->rmlvo.rules);
2187 SetXkbOption(pInfo, "xkb_model", &pEvdev->rmlvo.model);
2188 if (!pEvdev->rmlvo.model)
2189 SetXkbOption(pInfo, "XkbModel", &pEvdev->rmlvo.model);
2190 SetXkbOption(pInfo, "xkb_layout", &pEvdev->rmlvo.layout);
2191 if (!pEvdev->rmlvo.layout)
2192 SetXkbOption(pInfo, "XkbLayout", &pEvdev->rmlvo.layout);
2193 SetXkbOption(pInfo, "xkb_variant", &pEvdev->rmlvo.variant);
2194 if (!pEvdev->rmlvo.variant)
2195 SetXkbOption(pInfo, "XkbVariant", &pEvdev->rmlvo.variant);
2196 SetXkbOption(pInfo, "xkb_options", &pEvdev->rmlvo.options);
2197 if (!pEvdev->rmlvo.options)
2198 SetXkbOption(pInfo, "XkbOptions", &pEvdev->rmlvo.options);
2199 #ifdef _F_USE_DEFAULT_XKB_RULES_
2203 if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl))
2206 #ifdef _F_REMAP_KEYS_
2207 SetRemapOption(pInfo,"event_key_remap");
2208 #endif //_F_REMAP_KEYS_
2214 /* MT axes are counted twice - once as ABS_X (which the kernel keeps for
2215 * backwards compatibility), once as ABS_MT_POSITION_X. So we need to keep a
2216 * mapping of those axes to make sure we only count them once
2218 struct mt_axis_mappings {
2221 Bool needs_mapping; /* TRUE if both code and mt_code are present */
2222 int mapping; /* Logical mapping of 'code' axis */
2225 static struct mt_axis_mappings mt_axis_mappings[] = {
2226 {ABS_MT_POSITION_X, ABS_X},
2227 {ABS_MT_POSITION_Y, ABS_Y},
2228 {ABS_MT_PRESSURE, ABS_PRESSURE},
2229 {ABS_MT_DISTANCE, ABS_DISTANCE},
2234 * return TRUE if the axis is not one we should count as true axis
2237 is_blacklisted_axis(int axis)
2242 case ABS_MT_TRACKING_ID:
2251 EvdevAddAbsValuatorClass(DeviceIntPtr device)
2255 int num_axes, axis, i = 0;
2256 int num_mt_axes = 0, /* number of MT-only axes */
2257 num_mt_axes_total = 0; /* total number of MT axes, including
2258 double-counted ones, excluding blacklisted */
2261 pInfo = device->public.devicePrivate;
2262 pEvdev = pInfo->private;
2264 if (!EvdevBitIsSet(pEvdev->bitmask, EV_ABS))
2267 num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
2272 for (axis = ABS_MT_SLOT; axis < ABS_MAX; axis++)
2274 if (EvdevBitIsSet(pEvdev->abs_bitmask, axis))
2279 for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
2281 if (mt_axis_mappings[j].mt_code == axis &&
2282 BitIsOn(pEvdev->abs_bitmask, mt_axis_mappings[j].code))
2284 mt_axis_mappings[j].needs_mapping = TRUE;
2289 if (!is_blacklisted_axis(axis))
2291 num_mt_axes_total++;
2299 if (num_axes + num_mt_axes > MAX_VALUATORS) {
2300 xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS);
2301 num_axes = MAX_VALUATORS;
2304 if (num_axes < 1 && num_mt_axes_total < 1) {
2305 xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n",
2310 pEvdev->num_vals = num_axes;
2312 pEvdev->vals = valuator_mask_new(num_axes);
2313 pEvdev->old_vals = valuator_mask_new(num_axes);
2314 if (!pEvdev->vals || !pEvdev->old_vals) {
2315 xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate valuator masks.\n");
2320 if (num_mt_axes_total > 0) {
2321 pEvdev->num_mt_vals = num_mt_axes_total;
2322 pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total);
2323 if (!pEvdev->mt_mask) {
2324 xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n",
2329 pEvdev->last_mt_vals = calloc(num_slots(pEvdev), sizeof(ValuatorMask *));
2330 if (!pEvdev->last_mt_vals) {
2331 xf86IDrvMsg(pInfo, X_ERROR,
2332 "%s: failed to allocate MT last values mask array.\n",
2337 for (i = 0; i < num_slots(pEvdev); i++) {
2338 pEvdev->last_mt_vals[i] = valuator_mask_new(num_mt_axes_total);
2339 if (!pEvdev->last_mt_vals[i]) {
2340 xf86IDrvMsg(pInfo, X_ERROR,
2341 "%s: failed to allocate MT last values mask.\n",
2347 for (i = 0; i < EVDEV_MAXQUEUE; i++) {
2348 pEvdev->queue[i].touchMask =
2349 valuator_mask_new(num_mt_axes_total);
2350 if (!pEvdev->queue[i].touchMask) {
2351 xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for "
2352 "evdev event queue.\n", device->name);
2358 atoms = malloc((pEvdev->num_vals + num_mt_axes) * sizeof(Atom));
2361 for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
2366 pEvdev->axis_map[axis] = -1;
2367 if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) ||
2368 is_blacklisted_axis(axis))
2374 for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
2376 if (mt_axis_mappings[j].code == axis)
2377 mt_axis_mappings[j].mapping = mapping;
2378 else if (mt_axis_mappings[j].mt_code == axis &&
2379 mt_axis_mappings[j].needs_mapping)
2380 mapping = mt_axis_mappings[j].mapping;
2383 pEvdev->axis_map[axis] = mapping;
2388 EvdevInitAxesLabels(pEvdev, Absolute, pEvdev->num_vals + num_mt_axes, atoms);
2390 if (!InitValuatorClassDeviceStruct(device, num_axes + num_mt_axes, atoms,
2391 GetMotionHistorySize(), Absolute)) {
2392 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize valuator class device.\n");
2397 if (num_mt_axes_total > 0)
2399 int num_touches = 0;
2400 int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
2401 XIDependentTouch : XIDirectTouch;
2403 num_touches = num_slots(pEvdev);
2405 if (!InitTouchClassDeviceStruct(device, num_touches, mode,
2406 num_mt_axes_total)) {
2407 xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n",
2412 for (i = 0; i < num_slots(pEvdev); i++) {
2413 for (axis = ABS_MT_TOUCH_MAJOR; axis < ABS_MAX; axis++) {
2414 if (pEvdev->axis_map[axis] >= 0) {
2415 /* XXX: read initial values from mtdev when it adds support
2417 valuator_mask_set(pEvdev->last_mt_vals[i],
2418 pEvdev->axis_map[axis], 0);
2425 for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) {
2426 int axnum = pEvdev->axis_map[axis];
2432 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30)
2433 /* Kernel provides units/mm, X wants units/m */
2434 if (pEvdev->absinfo[axis].resolution)
2435 resolution = pEvdev->absinfo[axis].resolution * 1000;
2438 xf86InitValuatorAxisStruct(device, axnum,
2440 pEvdev->absinfo[axis].minimum,
2441 pEvdev->absinfo[axis].maximum,
2442 resolution, 0, resolution, Absolute);
2443 xf86InitValuatorDefaults(device, axnum);
2447 for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) {
2448 int axnum = pEvdev->axis_map[axis];
2456 for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
2457 if (mt_axis_mappings[j].mt_code == axis &&
2458 mt_axis_mappings[j].needs_mapping)
2464 /* MT axis is mapped, don't set up twice */
2468 if (pEvdev->absinfo[axis].resolution)
2469 resolution = pEvdev->absinfo[axis].resolution * 1000;
2471 xf86InitValuatorAxisStruct(device, axnum,
2473 pEvdev->absinfo[axis].minimum,
2474 pEvdev->absinfo[axis].maximum,
2475 resolution, 0, resolution,
2483 for (i = 0; i < ArrayLength(proximity_bits); i++)
2485 if (!pEvdev->use_proximity)
2488 if (EvdevBitIsSet(pEvdev->key_bitmask, proximity_bits[i]))
2490 InitProximityClassDeviceStruct(device);
2491 pEvdev->prox = valuator_mask_new(num_axes);
2492 if (!pEvdev->prox) {
2493 xf86IDrvMsg(pInfo, X_ERROR,
2494 "failed to allocate proximity valuator " "mask.\n");
2501 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
2502 xf86IDrvMsg(pInfo, X_ERROR,
2503 "failed to initialize pointer feedback class device.\n");
2507 if (pEvdev->flags & EVDEV_TOUCHPAD)
2508 pEvdev->flags |= EVDEV_RELATIVE_MODE;
2510 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
2512 if (xf86FindOption(pInfo->options, "Mode"))
2515 mode = xf86SetStrOption(pInfo->options, "Mode", NULL);
2516 if (!strcasecmp("absolute", mode))
2517 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
2518 else if (!strcasecmp("relative", mode))
2519 pEvdev->flags |= EVDEV_RELATIVE_MODE;
2521 xf86IDrvMsg(pInfo, X_INFO, "unknown mode, use default\n");
2528 EvdevFreeMasks(pEvdev);
2535 EvdevAddRelValuatorClass(DeviceIntPtr device)
2539 int num_axes, axis, i = 0;
2542 pInfo = device->public.devicePrivate;
2543 pEvdev = pInfo->private;
2545 if (!EvdevBitIsSet(pEvdev->bitmask, EV_REL))
2548 num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX));
2552 #ifndef HAVE_SMOOTH_SCROLLING
2553 /* Wheels are special, we post them as button events. So let's ignore them
2554 * in the axes list too */
2555 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL))
2557 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL))
2559 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL))
2566 if (num_axes > MAX_VALUATORS) {
2567 xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS);
2568 num_axes = MAX_VALUATORS;
2571 pEvdev->num_vals = num_axes;
2573 pEvdev->vals = valuator_mask_new(num_axes);
2577 atoms = malloc(pEvdev->num_vals * sizeof(Atom));
2579 for (axis = REL_X; i < MAX_VALUATORS && axis <= REL_MAX; axis++)
2581 pEvdev->axis_map[axis] = -1;
2582 #ifndef HAVE_SMOOTH_SCROLLING
2583 /* We don't post wheel events, so ignore them here too */
2584 if (axis == REL_WHEEL || axis == REL_HWHEEL || axis == REL_DIAL)
2587 if (!EvdevBitIsSet(pEvdev->rel_bitmask, axis))
2589 pEvdev->axis_map[axis] = i;
2593 EvdevInitAxesLabels(pEvdev, Relative, pEvdev->num_vals, atoms);
2595 if (!InitValuatorClassDeviceStruct(device, num_axes, atoms,
2596 GetMotionHistorySize(), Relative)) {
2597 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize valuator class device.\n");
2601 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
2602 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize pointer feedback class "
2607 for (axis = REL_X; axis <= REL_MAX; axis++)
2609 int axnum = pEvdev->axis_map[axis];
2613 xf86InitValuatorAxisStruct(device, axnum, atoms[axnum], -1, -1, 1, 0, 1,
2615 xf86InitValuatorDefaults(device, axnum);
2616 #ifdef HAVE_SMOOTH_SCROLLING
2617 if (axis == REL_WHEEL)
2618 SetScrollValuator(device, axnum, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED);
2619 else if (axis == REL_DIAL)
2620 SetScrollValuator(device, axnum, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_NONE);
2621 else if (axis == REL_HWHEEL)
2622 SetScrollValuator(device, axnum, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE);
2631 valuator_mask_free(&pEvdev->vals);
2638 EvdevAddButtonClass(DeviceIntPtr device)
2642 Atom *labels = NULL;
2644 pInfo = device->public.devicePrivate;
2645 pEvdev = pInfo->private;
2647 labels = malloc(pEvdev->num_buttons * sizeof(Atom));
2648 if (!labels) return BadAlloc;
2649 EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels);
2651 if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons, labels,
2663 * Init the button mapping for the device. By default, this is a 1:1 mapping,
2664 * i.e. Button 1 maps to Button 1, Button 2 to 2, etc.
2666 * If a mapping has been specified, the mapping is the default, with the
2667 * user-defined ones overwriting the defaults.
2668 * i.e. a user-defined mapping of "3 2 1" results in a mapping of 3 2 1 4 5 6 ...
2670 * Invalid button mappings revert to the default.
2672 * Note that index 0 is unused, button 0 does not exist.
2673 * This mapping is initialised for all devices, but only applied if the device
2674 * has buttons (in EvdevAddButtonClass).
2677 EvdevInitButtonMapping(InputInfoPtr pInfo)
2679 int i, nbuttons = 1;
2680 char *mapping = NULL;
2681 EvdevPtr pEvdev = pInfo->private;
2683 /* Check for user-defined button mapping */
2684 if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL)))
2686 char *map, *s = NULL;
2689 xf86IDrvMsg(pInfo, X_CONFIG, "ButtonMapping '%s'\n", mapping);
2693 btn = strtol(map, &s, 10);
2695 if (s == map || btn < 0 || btn > EVDEV_MAXBUTTONS)
2697 xf86IDrvMsg(pInfo, X_ERROR,
2698 "... Invalid button mapping. Using defaults\n");
2699 nbuttons = 1; /* ensure defaults start at 1 */
2703 pEvdev->btnmap[nbuttons++] = btn;
2705 } while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS);
2709 for (i = nbuttons; i < ArrayLength(pEvdev->btnmap); i++)
2710 pEvdev->btnmap[i] = i;
2715 EvdevInitAnyValuators(DeviceIntPtr device, EvdevPtr pEvdev)
2717 InputInfoPtr pInfo = device->public.devicePrivate;
2719 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS &&
2720 EvdevAddRelValuatorClass(device) == Success)
2721 xf86IDrvMsg(pInfo, X_INFO, "initialized for relative axes.\n");
2722 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS &&
2723 EvdevAddAbsValuatorClass(device) == Success)
2724 xf86IDrvMsg(pInfo, X_INFO, "initialized for absolute axes.\n");
2728 EvdevInitAbsValuators(DeviceIntPtr device, EvdevPtr pEvdev)
2730 InputInfoPtr pInfo = device->public.devicePrivate;
2732 if (EvdevAddAbsValuatorClass(device) == Success) {
2733 xf86IDrvMsg(pInfo, X_INFO,"initialized for absolute axes.\n");
2735 xf86IDrvMsg(pInfo, X_ERROR,"failed to initialize for absolute axes.\n");
2736 pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
2741 EvdevInitRelValuators(DeviceIntPtr device, EvdevPtr pEvdev)
2743 InputInfoPtr pInfo = device->public.devicePrivate;
2744 int has_abs_axes = pEvdev->flags & EVDEV_ABSOLUTE_EVENTS;
2745 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
2746 if ( (pEvdev->flags & EVDEV_GAMEPAD) && (has_abs_axes) ) {
2747 xf86IDrvMsg(pInfo, X_INFO,"initialized for game pad axes. Ignore relative axes.\n");
2749 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
2751 EvdevInitAbsValuators(device, pEvdev);
2752 } else if (EvdevAddRelValuatorClass(device) == Success) {
2754 if (EvdevAddRelValuatorClass(device) == Success) {
2755 #endif//_F_EVDEV_SUPPORT_GAMEPAD
2756 xf86IDrvMsg(pInfo, X_INFO,"initialized for relative axes.\n");
2759 xf86IDrvMsg(pInfo, X_WARNING,"ignoring absolute axes.\n");
2760 pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
2764 xf86IDrvMsg(pInfo, X_ERROR,"failed to initialize for relative axes.\n");
2766 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
2769 EvdevInitAbsValuators(device, pEvdev);
2774 EvdevInitTouchDevice(DeviceIntPtr device, EvdevPtr pEvdev)
2776 InputInfoPtr pInfo = device->public.devicePrivate;
2778 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) {
2779 xf86IDrvMsg(pInfo, X_WARNING, "touchpads, tablets and touchscreens "
2780 "ignore relative axes.\n");
2781 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
2784 EvdevInitAbsValuators(device, pEvdev);
2787 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
2789 EvdevIsGamePad(InputInfoPtr pInfo)
2792 EvdevPtr pEvdev = pInfo->private;
2795 for(i=0; i<MAX_GAMEPAD_DEFINITION_ABS; i++)
2797 if(pEvdev->abs_gamepad_labels[i] == 0)
2800 if(!EvdevBitIsSet(pEvdev->abs_bitmask, pEvdev->abs_gamepad_labels[i]))
2802 ErrorF("[EvdevIsGamePad] %s device doesn't support abs code(%d)\n", pInfo->name, pEvdev->abs_gamepad_labels[i]);
2808 for(i=0; i<MAX_GAMEPAD_DEFINITION_KEY; i++)
2810 if(pEvdev->key_gamepad_labels[i] == 0)
2813 if(!EvdevBitIsSet(pEvdev->key_bitmask, pEvdev->key_gamepad_labels[i]))
2815 ErrorF("[EvdevIsGamePad] %s device doesn't support key code(%d)\n", pInfo->name, pEvdev->key_gamepad_labels[i]);
2822 #endif//_F_EVDEV_SUPPORT_GAMEPAD
2825 EvdevInit(DeviceIntPtr device)
2831 pInfo = device->public.devicePrivate;
2832 pEvdev = pInfo->private;
2833 TTRACE_BEGIN("XORG:EVDEV:INIT");
2835 /* clear all axis_map entries */
2836 for(i = 0; i < max(ABS_CNT,REL_CNT); i++)
2837 pEvdev->axis_map[i]=-1;
2839 if (pEvdev->flags & EVDEV_KEYBOARD_EVENTS)
2840 EvdevAddKeyClass(device);
2841 if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
2842 EvdevAddButtonClass(device);
2844 /* We don't allow relative and absolute axes on the same device. The
2845 * reason is that some devices (MS Optical Desktop 2000) register both
2846 * rel and abs axes for x/y.
2848 * The abs axes register min/max; this min/max then also applies to the
2849 * relative device (the mouse) and caps it at 0..255 for both axes.
2850 * So, unless you have a small screen, you won't be enjoying it much;
2851 * consequently, absolute axes are generally ignored.
2853 * However, currenly only a device with absolute axes can be registered
2854 * as a touch{pad,screen}. Thus, given such a device, absolute axes are
2855 * used and relative axes are ignored.
2858 if (pEvdev->flags & (EVDEV_UNIGNORE_RELATIVE | EVDEV_UNIGNORE_ABSOLUTE))
2859 EvdevInitAnyValuators(device, pEvdev);
2860 else if (pEvdev->flags & (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET))
2861 EvdevInitTouchDevice(device, pEvdev);
2862 else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
2863 EvdevInitRelValuators(device, pEvdev);
2865 #ifdef _F_INIT_ABS_ONLY_FOR_POINTER_
2866 else if ( !(pEvdev->flags & EVDEV_KEYBOARD_EVENTS) && (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) )
2867 #else /* #ifdef _F_INIT_ABS_ONLY_FOR_POINTER_ */
2868 else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
2869 #endif /* #ifdef _F_INIT_ABS_ONLY_FOR_POINTER_ */
2870 EvdevInitAbsValuators(device, pEvdev);
2872 /* We drop the return value, the only time we ever want the handlers to
2873 * unregister is when the device dies. In which case we don't have to
2874 * unregister anyway */
2875 EvdevInitProperty(device);
2876 #ifdef _F_PROXY_DEVICE_ENABLED_
2877 if (!strncmp(pInfo->name, PROXY_DEV_NAME, sizeof(PROXY_DEV_NAME))) {
2878 EvdevProxyInit(device);
2881 XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
2882 #else //_F_PROXY_DEVICE_ENABLED_
2883 XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
2884 #endif //_F_PROXY_DEVICE_ENABLED_
2885 EvdevMBEmuInitProperty(device);
2886 Evdev3BEmuInitProperty(device);
2887 EvdevWheelEmuInitProperty(device);
2888 EvdevDragLockInitProperty(device);
2889 EvdevAppleInitProperty(device);
2890 #ifdef _F_EVDEV_SUPPORT_ROTARY_
2891 EvdevRotaryInit(device);
2892 #endif //_F_EVDEV_SUPPORT_ROTARY_
2893 #ifdef _F_EVDEV_SUPPORT_SMARTRC_
2894 EvdevRCInit(device);
2895 #endif //_F_EVDEV_SUPPORT_SMARTRC_
2903 * Init all extras (wheel emulation, etc.) and grab the device.
2906 EvdevOn(DeviceIntPtr device)
2911 ErrorF("[EvdevOn][id:%d] find device (%s)\n", device->id, device->name);
2912 TTRACE_BEGIN("XORG:EVDEV:ON");
2914 pInfo = device->public.devicePrivate;
2915 pEvdev = pInfo->private;
2917 #ifdef _F_PROXY_DEVICE_ENABLED_
2918 /*Check if its proxy device.. in that case just set flag and return..*/
2919 if(pEvdev->b_proxy_device)
2921 pEvdev->flags |= EVDEV_INITIALIZED;
2922 device->public.on = TRUE;
2925 #endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
2927 /* after PreInit fd is still open */
2928 rc = EvdevOpenDevice(pInfo);
2929 if (rc != Success) {
2934 EvdevGrabDevice(pInfo, 1, 0);
2936 xf86FlushInput(pInfo->fd);
2937 xf86AddEnabledDevice(pInfo);
2938 EvdevMBEmuOn(pInfo);
2939 Evdev3BEmuOn(pInfo);
2940 pEvdev->flags |= EVDEV_INITIALIZED;
2941 device->public.on = TRUE;
2949 EvdevProc(DeviceIntPtr device, int what)
2953 #ifdef _F_EVDEV_CONFINE_REGION_
2954 int region[6] = { 0, };
2955 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
2957 pInfo = device->public.devicePrivate;
2958 pEvdev = pInfo->private;
2963 return EvdevInit(device);
2966 return EvdevOn(device);
2969 #ifdef _F_PROXY_DEVICE_ENABLED_
2970 if(pEvdev->b_proxy_device)
2972 if (pEvdev->flags & EVDEV_INITIALIZED)
2974 pEvdev->min_maj = 0;
2975 pEvdev->flags &= ~EVDEV_INITIALIZED;
2976 device->public.on = FALSE;
2978 if (pInfo->fd != -1)
2980 xf86RemoveEnabledDevice(pInfo);
2986 #endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
2987 if (pEvdev->flags & EVDEV_INITIALIZED)
2989 EvdevMBEmuFinalize(pInfo);
2990 Evdev3BEmuFinalize(pInfo);
2992 if (pInfo->fd != -1)
2994 EvdevGrabDevice(pInfo, 0, 1);
2995 xf86RemoveEnabledDevice(pInfo);
2996 EvdevCloseDevice(pInfo);
2999 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
3000 if (pEvdev->rel_move_timer)
3002 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
3003 TimerCancel(pEvdev->rel_move_timer);
3004 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
3005 pEvdev->rel_move_status = 0;
3006 pEvdev->rel_move_ack = 0;
3007 ErrorF("[%s][dev:%d] DEVICE_OFF (rel_move_status=%d, rel_move_prop_set=%d)\n", __FUNCTION__, pInfo->dev->id, pEvdev->rel_move_status,
3008 pEvdev->rel_move_prop_set);
3010 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
3012 pEvdev->min_maj = 0;
3013 pEvdev->flags &= ~EVDEV_INITIALIZED;
3014 device->public.on = FALSE;
3018 #ifdef _F_EVDEV_CONFINE_REGION_
3019 if(pEvdev->pointer_confine_region && pEvdev->confined_id)
3020 EvdevSetConfineRegion(pInfo, 1, ®ion[0]);
3021 #endif /* _F_EVDEV_CONFINE_REGION_ */
3022 xf86IDrvMsg(pInfo, X_INFO, "Close\n");
3023 EvdevCloseDevice(pInfo);
3024 EvdevFreeMasks(pEvdev);
3025 EvdevRemoveDevice(pInfo);
3026 #ifdef _F_REMAP_KEYS_
3028 #endif //_F_REMAP_KEYS_
3029 pEvdev->min_maj = 0;
3040 * Get as much information as we can from the fd and cache it.
3042 * @return Success if the information was cached, or !Success otherwise.
3045 EvdevCache(InputInfoPtr pInfo)
3047 EvdevPtr pEvdev = pInfo->private;
3051 char name[1024] = {0};
3052 unsigned long bitmask[NLONGS(EV_CNT)] = {0};
3053 unsigned long key_bitmask[NLONGS(KEY_CNT)] = {0};
3054 unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0};
3055 unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0};
3056 unsigned long led_bitmask[NLONGS(LED_CNT)] = {0};
3059 if (ioctl(pInfo->fd, EVIOCGID, &id) < 0)
3061 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGID failed: %s\n", strerror(errno));
3065 pEvdev->id_vendor = id.vendor;
3066 pEvdev->id_product = id.product;
3068 if (ioctl(pInfo->fd, EVIOCGNAME(sizeof(name) - 1), name) < 0) {
3069 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
3074 if (len < sizeof(pEvdev->name)) {
3075 strncpy(pEvdev->name, name, len+1);
3077 strncpy(pEvdev->name, name, sizeof(pEvdev->name)-1);
3078 xf86DrvMsg(pInfo, X_WARNING, "Device's name(%s) is too long. Restrict name to inside of buffer size\n", pEvdev->name);
3081 len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask);
3083 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
3088 memcpy(pEvdev->bitmask, bitmask, len);
3090 len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask);
3092 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
3097 memcpy(pEvdev->rel_bitmask, rel_bitmask, len);
3099 len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
3101 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
3106 memcpy(pEvdev->abs_bitmask, abs_bitmask, len);
3108 len = ioctl(pInfo->fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask);
3110 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
3115 memcpy(pEvdev->led_bitmask, led_bitmask, len);
3118 * Do not try to validate absinfo data since it is not expected
3119 * to be static, always refresh it in evdev structure.
3121 for (i = ABS_X; i <= ABS_MAX; i++) {
3122 if (EvdevBitIsSet(abs_bitmask, i)) {
3123 len = ioctl(pInfo->fd, EVIOCGABS(i), &pEvdev->absinfo[i]);
3125 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGABSi(%d) failed: %s\n",
3126 i, strerror(errno));
3129 xf86IDrvMsgVerb(pInfo, X_PROBED, 6, "absolute axis %#x [%d..%d]\n",
3130 i, pEvdev->absinfo[i].maximum, pEvdev->absinfo[i].minimum);
3134 len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
3136 xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGBIT failed: %s\n",
3141 /* Copy the data so we have reasonably up-to-date info */
3142 memcpy(pEvdev->key_bitmask, key_bitmask, len);
3152 * Issue an EVIOCGRAB on the device file, either as a grab or to ungrab, or
3153 * both. Return TRUE on success, otherwise FALSE. Failing the release is a
3154 * still considered a success, because it's not as if you could do anything
3158 EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab)
3160 EvdevPtr pEvdev = pInfo->private;
3162 if (pEvdev->grabDevice)
3164 if (grab && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
3165 xf86IDrvMsg(pInfo, X_WARNING, "Grab failed (%s)\n",
3168 } else if (ungrab && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
3169 xf86IDrvMsg(pInfo, X_WARNING, "Release failed (%s)\n",
3177 * Some devices only have other axes (e.g. wheels), but we
3178 * still need x/y for these. The server relies on devices having
3179 * x/y as axes 0/1 and core/XI 1.x clients expect it too (#44655)
3182 EvdevForceXY(InputInfoPtr pInfo, int mode)
3184 EvdevPtr pEvdev = pInfo->private;
3186 xf86IDrvMsg(pInfo, X_INFO, "Forcing %s x/y axes to exist.\n",
3187 (mode == Relative) ? "relative" : "absolute");
3189 if (mode == Relative)
3191 EvdevSetBit(pEvdev->rel_bitmask, REL_X);
3192 EvdevSetBit(pEvdev->rel_bitmask, REL_Y);
3193 } else if (mode == Absolute)
3195 EvdevSetBit(pEvdev->abs_bitmask, ABS_X);
3196 EvdevSetBit(pEvdev->abs_bitmask, ABS_Y);
3197 pEvdev->absinfo[ABS_X].minimum = 0;
3198 pEvdev->absinfo[ABS_X].maximum = 1000;
3199 pEvdev->absinfo[ABS_X].value = 0;
3200 pEvdev->absinfo[ABS_X].resolution = 0;
3201 pEvdev->absinfo[ABS_Y].minimum = 0;
3202 pEvdev->absinfo[ABS_Y].maximum = 1000;
3203 pEvdev->absinfo[ABS_Y].value = 0;
3204 pEvdev->absinfo[ABS_Y].resolution = 0;
3209 EvdevProbe(InputInfoPtr pInfo)
3211 int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll;
3212 int has_lmr; /* left middle right */
3213 int has_mt; /* multitouch */
3214 int ignore_abs = 0, ignore_rel = 0;
3215 EvdevPtr pEvdev = pInfo->private;
3218 xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n",
3219 pEvdev->id_vendor, pEvdev->id_product);
3221 /* Trinary state for ignoring axes:
3222 - unset: do the normal thing.
3223 - TRUE: explicitly ignore them.
3224 - FALSE: unignore axes, use them at all cost if they're present.
3226 if (xf86FindOption(pInfo->options, "IgnoreRelativeAxes"))
3228 if (xf86SetBoolOption(pInfo->options, "IgnoreRelativeAxes", FALSE))
3231 pEvdev->flags |= EVDEV_UNIGNORE_RELATIVE;
3234 if (xf86FindOption(pInfo->options, "IgnoreAbsoluteAxes"))
3236 if (xf86SetBoolOption(pInfo->options, "IgnoreAbsoluteAxes", FALSE))
3239 pEvdev->flags |= EVDEV_UNIGNORE_ABSOLUTE;
3242 has_rel_axes = FALSE;
3243 has_abs_axes = FALSE;
3250 /* count all buttons */
3251 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
3252 for (i = BTN_MISC; i < BTN_THUMBR; i++)
3254 for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
3255 #endif//_F_EVDEV_SUPPORT_GAMEPAD
3258 if (EvdevBitIsSet(pEvdev->key_bitmask, i))
3260 mapping = EvdevUtilButtonEventToButtonNumber(pEvdev, i);
3261 if (mapping > num_buttons)
3262 num_buttons = mapping;
3266 has_lmr = EvdevBitIsSet(pEvdev->key_bitmask, BTN_LEFT) ||
3267 EvdevBitIsSet(pEvdev->key_bitmask, BTN_MIDDLE) ||
3268 EvdevBitIsSet(pEvdev->key_bitmask, BTN_RIGHT);
3272 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3273 pEvdev->num_buttons = num_buttons;
3274 xf86IDrvMsg(pInfo, X_PROBED, "Found %d mouse buttons\n", num_buttons);
3277 for (i = 0; i < REL_MAX; i++) {
3278 if (EvdevBitIsSet(pEvdev->rel_bitmask, i)) {
3279 has_rel_axes = TRUE;
3285 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_WHEEL) ||
3286 EvdevBitIsSet(pEvdev->rel_bitmask, REL_HWHEEL) ||
3287 EvdevBitIsSet(pEvdev->rel_bitmask, REL_DIAL)) {
3288 xf86IDrvMsg(pInfo, X_PROBED, "Found scroll wheel(s)\n");
3291 xf86IDrvMsg(pInfo, X_INFO,
3292 "Forcing buttons for scroll wheel(s)\n");
3293 num_buttons = (num_buttons < 3) ? 7 : num_buttons + 4;
3294 pEvdev->num_buttons = num_buttons;
3299 xf86IDrvMsg(pInfo, X_PROBED, "Found relative axes\n");
3300 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
3302 if (EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) &&
3303 EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y)) {
3304 xf86IDrvMsg(pInfo, X_PROBED, "Found x and y relative axes\n");
3305 } else if (!EvdevBitIsSet(pEvdev->abs_bitmask, ABS_X) ||
3306 !EvdevBitIsSet(pEvdev->abs_bitmask, ABS_Y))
3307 EvdevForceXY(pInfo, Relative);
3309 xf86IDrvMsg(pInfo, X_INFO, "Relative axes present but ignored.\n");
3310 has_rel_axes = FALSE;
3314 for (i = 0; i < ABS_MAX; i++) {
3315 if (EvdevBitIsSet(pEvdev->abs_bitmask, i)) {
3316 has_abs_axes = TRUE;
3322 for (i = ABS_MT_SLOT; i < ABS_MAX; i++) {
3323 if (EvdevBitIsSet(pEvdev->abs_bitmask, i)) {
3329 #ifdef _F_EVDEV_SUPPORT_SMARTRC_
3330 if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_EXTRA))
3332 xf86IDrvMsg(pInfo, X_PROBED, "Found extra button\n");
3333 if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE)))
3335 xf86IDrvMsg(pInfo, X_PROBED, "... regarding smart rc\n");
3336 pEvdev->flags |= EVDEV_SMART_RC;
3339 if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_SIDE))
3341 xf86IDrvMsg(pInfo, X_PROBED, "Found extra button\n");
3342 if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE)))
3344 xf86IDrvMsg(pInfo, X_PROBED, "... regarding smart rc\n");
3345 pEvdev->flags |= EVDEV_SMART_RC;
3348 #endif //_F_EVDEV_SUPPORT_SMARTRC_
3349 if (ignore_abs && has_abs_axes)
3351 xf86IDrvMsg(pInfo, X_INFO, "Absolute axes present but ignored.\n");
3352 has_abs_axes = FALSE;
3353 } else if (has_abs_axes) {
3354 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute axes\n");
3355 pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
3358 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute multitouch axes\n");
3360 if ((EvdevBitIsSet(pEvdev->abs_bitmask, ABS_X) &&
3361 EvdevBitIsSet(pEvdev->abs_bitmask, ABS_Y))) {
3362 xf86IDrvMsg(pInfo, X_PROBED, "Found x and y absolute axes\n");
3363 if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOOL_PEN) ||
3364 EvdevBitIsSet(pEvdev->key_bitmask, BTN_STYLUS) ||
3365 EvdevBitIsSet(pEvdev->key_bitmask, BTN_STYLUS2))
3367 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute tablet.\n");
3368 pEvdev->flags |= EVDEV_TABLET;
3369 if (!pEvdev->num_buttons)
3371 pEvdev->num_buttons = 7; /* LMR + scroll wheels */
3372 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3374 } else if (EvdevBitIsSet(pEvdev->abs_bitmask, ABS_PRESSURE) ||
3375 EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOUCH)) {
3376 if (has_lmr || EvdevBitIsSet(pEvdev->key_bitmask, BTN_TOOL_FINGER)) {
3377 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchpad.\n");
3378 pEvdev->flags |= EVDEV_TOUCHPAD;
3380 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchscreen\n");
3381 pEvdev->flags |= EVDEV_TOUCHSCREEN;
3382 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3384 } else if (!(EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) &&
3385 EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y)) && has_lmr) {
3386 /* some touchscreens use BTN_LEFT rather than BTN_TOUCH */
3387 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchscreen\n");
3388 pEvdev->flags |= EVDEV_TOUCHSCREEN;
3389 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3390 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
3391 } else if(EvdevIsGamePad(pInfo)) {
3392 xf86IDrvMsg(pInfo, X_PROBED, "Found gamepad\n");
3393 pEvdev->flags |= EVDEV_GAMEPAD;
3394 #endif // _F_EVDEV_SUPPORT_GAMEPAD
3398 if (!EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_POSITION_X) ||
3399 !EvdevBitIsSet(pEvdev->abs_bitmask, ABS_MT_POSITION_Y))
3401 EvdevForceXY(pInfo, Absolute);
3405 for (i = 0; i < BTN_MISC; i++) {
3406 if (EvdevBitIsSet(pEvdev->key_bitmask, i)) {
3407 xf86IDrvMsg(pInfo, X_PROBED, "Found keys\n");
3408 pEvdev->flags |= EVDEV_KEYBOARD_EVENTS;
3414 if (has_rel_axes || has_abs_axes)
3417 int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
3419 pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
3420 pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
3421 pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
3423 str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
3425 num_calibration = sscanf(str, "%d %d %d %d",
3426 &calibration[0], &calibration[1],
3427 &calibration[2], &calibration[3]);
3429 if (num_calibration == 4)
3430 EvdevSetCalibration(pInfo, num_calibration, calibration);
3432 xf86IDrvMsg(pInfo, X_ERROR,
3433 "Insufficient calibration factors (%d). Ignoring calibration\n",
3438 if (has_rel_axes || has_abs_axes || num_buttons) {
3439 pInfo->flags |= XI86_SEND_DRAG_EVENTS;
3440 if (pEvdev->flags & EVDEV_TOUCHPAD) {
3441 xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchpad\n");
3442 pInfo->type_name = XI_TOUCHPAD;
3443 pEvdev->use_proximity = 0;
3444 } else if (pEvdev->flags & EVDEV_TABLET) {
3445 xf86IDrvMsg(pInfo, X_INFO, "Configuring as tablet\n");
3446 pInfo->type_name = XI_TABLET;
3447 } else if (pEvdev->flags & EVDEV_TOUCHSCREEN) {
3448 xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchscreen\n");
3449 pInfo->type_name = XI_TOUCHSCREEN;
3451 if (!EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) ||
3452 !EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y))
3453 EvdevForceXY(pInfo, Relative);
3454 xf86IDrvMsg(pInfo, X_INFO, "Configuring as mouse\n");
3455 pInfo->type_name = XI_MOUSE;
3462 xf86IDrvMsg(pInfo, X_INFO, "Configuring as keyboard\n");
3463 pInfo->type_name = XI_KEYBOARD;
3468 (has_rel_axes || has_abs_axes || num_buttons || has_keys))
3470 xf86IDrvMsg(pInfo, X_INFO, "Adding scrollwheel support\n");
3471 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
3472 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
3475 #ifdef _F_EVDEV_SUPPORT_ROTARY_
3476 if ((!strncmp(pInfo->name, "tizen_rotary", sizeof("tizen_rotary"))) && (pEvdev->flags & EVDEV_RELATIVE_EVENTS)) {
3477 xf86IDrvMsg(pInfo, X_PROBED, "Found rotary device.\n");
3478 pEvdev->flags |= EVDEV_OFM;
3480 EvdevSetBit(pEvdev->rel_bitmask, REL_Z);
3483 if ((!strncmp(pInfo->name, "tizen_detent", sizeof("tizen_detent"))) && (pEvdev->flags & EVDEV_RELATIVE_EVENTS)) {
3484 xf86IDrvMsg(pInfo, X_PROBED, "Found hall device.\n");
3485 pEvdev->flags |= EVDEV_HALLIC;
3487 #endif //_F_EVDEV_SUPPORT_ROTARY_
3488 #ifdef _F_EVDEV_SUPPORT_SMARTRC_
3489 if (pEvdev->flags & EVDEV_SMART_RC) {
3490 xf86IDrvMsg(pInfo, X_INFO, "Configuring as smart rc\n");
3491 pInfo->type_name = XI_MOUSE;
3493 EvdevSetBit(pEvdev->rel_bitmask, REL_WHEEL);
3494 EvdevSetBit(pEvdev->rel_bitmask, REL_HWHEEL);
3496 pEvdev->origin_input_process = EvdevProcessEvent;
3497 #endif //_F_EVDEV_SUPPORT_SMARTRC_
3499 xf86IDrvMsg(pInfo, X_WARNING, "Don't know how to use device\n");
3505 EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
3507 EvdevPtr pEvdev = pInfo->private;
3509 if (num_calibration == 0) {
3510 pEvdev->flags &= ~EVDEV_CALIBRATED;
3511 pEvdev->calibration.min_x = 0;
3512 pEvdev->calibration.max_x = 0;
3513 pEvdev->calibration.min_y = 0;
3514 pEvdev->calibration.max_y = 0;
3515 } else if (num_calibration == 4) {
3516 pEvdev->flags |= EVDEV_CALIBRATED;
3517 pEvdev->calibration.min_x = calibration[0];
3518 pEvdev->calibration.max_x = calibration[1];
3519 pEvdev->calibration.min_y = calibration[2];
3520 pEvdev->calibration.max_y = calibration[3];
3525 EvdevOpenDevice(InputInfoPtr pInfo)
3527 EvdevPtr pEvdev = pInfo->private;
3528 char *device = pEvdev->device;
3532 device = xf86CheckStrOption(pInfo->options, "Device", NULL);
3534 xf86IDrvMsg(pInfo, X_ERROR, "No device specified.\n");
3538 pEvdev->device = device;
3539 xf86IDrvMsg(pInfo, X_CONFIG, "Device: \"%s\"\n", device);
3545 pInfo->fd = open(device, O_RDWR | O_NONBLOCK, 0);
3546 } while (pInfo->fd < 0 && errno == EINTR);
3548 if (pInfo->fd < 0) {
3549 xf86IDrvMsg(pInfo, X_ERROR, "Unable to open evdev device \"%s\".\n", device);
3555 if (!pEvdev->mtdev) { /* after PreInit mtdev is still valid */
3556 pEvdev->mtdev = mtdev_new_open(pInfo->fd);
3557 if (!pEvdev->mtdev) {
3558 xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
3559 EvdevCloseDevice(pInfo);
3564 pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
3567 /* Check major/minor of device node to avoid adding duplicate devices. */
3568 pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
3569 if (EvdevIsDuplicate(pInfo))
3571 xf86IDrvMsg(pInfo, X_WARNING, "device file is duplicate. Ignoring.\n");
3572 EvdevCloseDevice(pInfo);
3580 EvdevCloseDevice(InputInfoPtr pInfo)
3582 EvdevPtr pEvdev = pInfo->private;
3592 mtdev_close_delete(pEvdev->mtdev);
3593 pEvdev->mtdev = NULL;
3599 #ifdef _F_EVDEV_CONFINE_REGION_
3601 GetMasterPointerFromId(int deviceid)
3603 DeviceIntPtr pDev = inputInfo.devices;
3606 if( pDev->id == deviceid && pDev->master )
3608 return pDev->master;
3617 IsMaster(DeviceIntPtr dev)
3619 return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
3623 GetPairedDevice(DeviceIntPtr dev)
3625 if (!IsMaster(dev) && dev->master)
3628 return dev->spriteInfo->paired;
3632 GetMaster(DeviceIntPtr dev, int which)
3634 DeviceIntPtr master;
3639 master = dev->master;
3643 if (which == MASTER_KEYBOARD)
3645 if (master->type != MASTER_KEYBOARD)
3646 master = GetPairedDevice(master);
3649 if (master->type != MASTER_POINTER)
3650 master = GetPairedDevice(master);
3658 EvdevHookPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
3659 BoxPtr pHotBox, BoxPtr pTopLeftBox)
3661 *pTopLeftBox = *pHotBox;
3665 EvdevHookPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
3671 pInfo = pDev->public.devicePrivate;
3672 if(!pInfo || !pInfo->private) return;
3673 pEvdev = pInfo->private;
3675 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor] Enter !\n");
3677 miPointerPtr pPointer;
3678 pPointer = MIPOINTER(pDev);
3680 pConfineBox = pEvdev->pointer_confine_region;
3681 if(pConfineBox && pEvdev->confined_id)
3683 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor][before] pBox (%d, %d, %d, %d), pPointer->limits (%d, %d, %d, %d), confined=%d\n",
3684 pBox->x1, pBox->y1, pBox->x2, pBox->y2, pPointer->limits.x1, pPointer->limits.y1, pPointer->limits.x2, pPointer->limits.y2, pPointer->confined);
3686 if( IsMaster(pDev) && GetMasterPointerFromId(pEvdev->confined_id) == pDev )
3688 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor] confine routine --begin (pDev->id=%d)\n", pDev->id);
3689 if( pBox->x1 < pConfineBox->x1 )
3690 pBox->x1 = pConfineBox->x1;
3691 if( pBox->y1 < pConfineBox->y1 )
3692 pBox->y1 = pConfineBox->y1;
3693 if( pBox->x2 > pConfineBox->x2 )
3694 pBox->x2 = pConfineBox->x2;
3695 if( pBox->y2 > pConfineBox->y2 )
3696 pBox->y2 = pConfineBox->y2;
3697 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor] confine routine --end (pDev->id=%d)\n", pDev->id);
3701 pPointer->limits = *pBox;
3702 pPointer->confined = PointerConfinedToScreen(pDev);
3704 if(pEvdev->confined_id)
3706 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor][after] pBox (%d, %d, %d, %d), pPointer->limits (%d, %d, %d, %d), confined=%d\n",
3707 pBox->x1, pBox->y1, pBox->x2, pBox->y2, pPointer->limits.x1, pPointer->limits.y1, pPointer->limits.x2, pPointer->limits.y2, pPointer->confined);
3710 xf86IDrvMsg(pInfo, X_INFO, "[X11][EvdevHookPointerConstrainCursor] Leave !\n");
3714 EvdevSetCursorLimits(InputInfoPtr pInfo, int region[6], int isSet)
3716 EvdevPtr pEvdev = pInfo->private;
3717 BoxPtr pConfineBox = pEvdev->pointer_confine_region;
3721 ScreenPtr pCursorScreen = NULL;
3723 pCursorScreen = miPointerGetScreen(pInfo->dev);
3725 if( !pCursorScreen )
3727 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetCursorLimits] Failed to get screen information for pointer !\n");
3733 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] isSet = TRUE !!\n");
3735 //Clip confine region with screen's width/height
3738 if( region[2] >= pCursorScreen->width )
3739 region[2] = pCursorScreen->width - 1;
3740 if( region [1] < 0 )
3742 if( region[3] >= pCursorScreen->height )
3743 region[3] = pCursorScreen->height - 1;
3745 //Do pointerwarp if region[4] is not zero and region[5] is zero
3746 if(region[4] && !region[5])
3749 pConfineBox->x1 = region[0];
3750 pConfineBox->y1 = region[1];
3751 pConfineBox->x2 = region[2];
3752 pConfineBox->y2 = region[3];
3753 pEvdev->confined_id = pInfo->dev->id;
3755 pCursorScreen->ConstrainCursor(inputInfo.pointer, pCursorScreen, pConfineBox);
3756 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] Constrain information for cursor was set to TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) !\n",
3757 region[0], region[1], region[2], region[3]);
3759 if( pCursorScreen->CursorLimits != EvdevHookPointerCursorLimits &&
3760 pCursorScreen->ConstrainCursor != EvdevHookPointerConstrainCursor)
3762 //Backup original function pointer(s)
3763 pEvdev->pOrgConstrainCursor = pCursorScreen->ConstrainCursor;
3764 pEvdev->pOrgCursorLimits = pCursorScreen->CursorLimits;
3766 //Overriding function pointer(s)
3767 pCursorScreen->CursorLimits = EvdevHookPointerCursorLimits;
3768 pCursorScreen->ConstrainCursor = EvdevHookPointerConstrainCursor;
3771 //Skip pointer warp if region[4] is zero
3774 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] region[4]=%d NOT pointer warp !\n", region[4]);
3779 v[0] = region[0] + (int)((float)(region[2]-region[0])/2);
3780 v[1] = region[1] + (int)((float)(region[3]-region[1])/2);
3782 xf86PostMotionEventP(pInfo->dev, TRUE, REL_X, 2, v);
3783 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] Cursor was warped to (%d, %d) !\n", v[0], v[1]);
3784 miPointerGetPosition(pInfo->dev, &x, &y);
3785 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] Cursor is located at (%d, %d) !\n", x, y);
3789 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] isSet = FALSE !!\n");
3791 pConfineBox->x1 = 0;
3792 pConfineBox->y1 = 0;
3793 pConfineBox->x2 = pCursorScreen->width - 1;
3794 pConfineBox->y2 = pCursorScreen->height - 1;
3795 pEvdev->confined_id = 0;
3797 pCursorScreen->ConstrainCursor(inputInfo.pointer, pCursorScreen, pConfineBox);
3798 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetCursorLimits] Constrain information for cursor was restored ! TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) !\n",
3799 pConfineBox->x1, pConfineBox->y1,
3800 pConfineBox->x2, pConfineBox->y2);
3802 //Restore original function pointer(s)
3803 pCursorScreen->CursorLimits = pEvdev->pOrgCursorLimits;
3804 pCursorScreen->ConstrainCursor = pEvdev->pOrgConstrainCursor;
3809 EvdevSetConfineRegion(InputInfoPtr pInfo, int num_item, int region[6])
3811 EvdevPtr pEvdev = pInfo ? pInfo->private : NULL;
3815 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetConfineRegion] num_item != 6 && num_item != 1 !!\n");
3819 if ((num_item != 6) && (num_item != 1) )
3821 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetConfineRegion] num_item != 6 && num_item != 1 !!\n");
3825 if (!pEvdev->pointer_confine_region)
3827 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetConfineRegion] pEvdev->pointer_confine_region is NULL\n");
3828 xf86IDrvMsg(pInfo, X_ERROR, "[X11][SetConfineRegion] num_item=%d\n", num_item);
3834 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetConfineRegion] num_item == 6\n");
3835 if ( (region[2]-region[0]>0) && (region[3]-region[1]>0) )
3837 EvdevSetCursorLimits(pInfo, ®ion[0], 1);
3838 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetConfineRegion] Confine region was set to TOPLEFT(%d, %d) BOTTOMRIGHT(%d, %d) pointerwarp=%d, confine=%d\n",
3839 region[0], region[1], region[2], region[3], region[4], region[5]);
3840 pEvdev->flags |= EVDEV_CONFINE_REGION;
3843 else//if( num_item == 1 )
3845 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetConfineRegion] num_item == 1\n");
3846 if( !region[0] && (pEvdev->flags & EVDEV_CONFINE_REGION) )
3848 EvdevSetCursorLimits(pInfo, ®ion[0], 0);
3849 xf86IDrvMsg(pInfo, X_INFO, "[X11][SetConfineRegion] Confine region was unset !\n");
3850 pEvdev->flags &= ~EVDEV_CONFINE_REGION;
3854 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
3856 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
3858 EvdevSetTransformMatrix(InputInfoPtr pInfo, int num_transform, float *tmatrix)
3861 struct pixman_transform tr;
3862 EvdevPtr pEvdev = pInfo ? pInfo->private : NULL;
3867 if( (num_transform != 9) && (num_transform != 1) )
3869 pEvdev->use_transform = FALSE;
3873 if( num_transform == 9 )
3875 pEvdev->use_transform = TRUE;
3877 memcpy(pEvdev->transform, tmatrix, sizeof(pEvdev->transform));
3880 tr.matrix[y][x] = pixman_double_to_fixed((double)*tmatrix++);
3882 pixman_transform_invert(&pEvdev->inv_transform, &tr);
3883 ErrorF("[X11][EvdevSetTransformMatrix] Touch transform has been enabled !\n");
3885 else if( (num_transform == 1) && (tmatrix[0] == 0) )
3887 pEvdev->use_transform = FALSE;
3888 ErrorF("[X11][EvdevSetTransformMatrix] Touch transform has been disabled !\n");
3891 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
3893 #ifdef _F_SUPPORT_ROTATION_ANGLE_
3895 EvdevSetRotationAngle(EvdevPtr pEvdev, int angle)
3897 if(pEvdev->rotation_node <= 0)
3899 xf86Msg(X_INFO, "[%s] Rotation node doesn't exist. Ignored. (angle=%d)\n", __FUNCTION__, angle);
3903 if(pEvdev->rotation_angle != angle)
3909 buf = (char)(angle + '0');
3911 nwrite = write(pEvdev->rotation_node, &buf, sizeof(buf));
3914 xf86Msg(X_ERROR, "[%s] Failed to write angle(=%d) on rotation_node. (errno=%d)\n", __FUNCTION__, angle, errno);
3916 xf86Msg(X_ERROR, "[%s] Succeed to write angle(=%d) on rotation_node.\n", __FUNCTION__, angle);
3919 pEvdev->rotation_angle = angle;
3923 xf86Msg(X_INFO, "[%s] Rotation angle has not been changed. Ignored. (angle=%d)\n", __FUNCTION__, angle);
3926 #endif// _F_SUPPORT_ROTATION_ANGLE_
3929 EvdevUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
3931 EvdevPtr pEvdev = pInfo ? pInfo->private : NULL;
3934 #ifdef _F_EVDEV_SUPPORT_ROTARY_
3935 EvdevRotaryUnInit(pEvdev);
3936 #endif //_F_EVDEV_SUPPORT_ROTARY_
3938 /* Release strings allocated in EvdevAddKeyClass. */
3939 XkbFreeRMLVOSet(&pEvdev->rmlvo, FALSE);
3940 /* Release string allocated in EvdevOpenDevice. */
3941 free(pEvdev->device);
3942 pEvdev->device = NULL;
3946 xf86DeleteInput(pInfo, flags);
3950 EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
3954 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
3956 int num_transform = 0;
3958 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
3960 #ifdef _F_PROXY_DEVICE_ENABLED_
3962 #endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
3964 #ifdef _F_BOOST_PULSE_
3965 if(fd_boostpulse == NULL)
3966 fd_boostpulse = open("sys/kernel/hmp/boostpulse", O_RDWR);
3967 #endif //_F_BOOST_PULSE_
3969 if (!(pEvdev = calloc(sizeof(EvdevRec), 1)))
3971 xf86IDrvMsg(pInfo, X_ERROR, "Failed to allocate memory for private member of pInfo !\n");
3977 pInfo->private = pEvdev;
3978 pInfo->type_name = "UNKNOWN";
3979 pInfo->device_control = EvdevProc;
3980 pInfo->read_input = EvdevReadInput;
3981 pInfo->switch_mode = EvdevSwitchMode;
3982 #ifdef _F_EVDEV_SUPPORT_SMARTRC_
3983 pEvdev->extra_input_process = NULL;
3984 pEvdev->rc_state = 0;
3985 pEvdev->proxy_enabled = xf86SetBoolOption(pInfo->options, "ProxyDeviceEnabled", FALSE);
3986 #endif //_F_EVDEV_SUPPORT_SMARTRC_
3988 #ifdef _F_PROXY_DEVICE_ENABLED_
3989 /* If Type == ProxyDev, this is a proxy device */
3990 type = xf86CheckStrOption(pInfo->options, "Type", NULL);
3992 xf86Msg(X_INFO, "%s: Evdev Type %s found\n", pInfo->name, type);
3994 if (type != NULL && strcmp(type, OPT_TYPE_VAL) == 0)
3996 EvdevPtr pCreatorEvdev;
4001 pCreatorEvdev = pCreatorInfo->private;
4002 xf86Msg(X_INFO, "%s: Evdev proxy device found\n", pInfo->name);
4003 memcpy(pEvdev, pCreatorEvdev, sizeof(EvdevRec));
4004 pInfo->read_input = EvdevProxydevReadInput;
4005 pInfo->type_name = pCreatorInfo->type_name;
4006 pEvdev->b_proxy_device = TRUE;
4007 pEvdev->proxy_device = NULL;
4013 pEvdev->b_proxy_device = FALSE;
4014 pEvdev->proxy_device = NULL;
4016 #endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
4018 #ifdef _F_EVDEV_SUPPORT_ROTARY_
4019 pEvdev->extra_rel_post_hallic= NULL;
4020 pEvdev->extra_rel_post_ofm= NULL;
4021 #endif //_F_EVDEV_SUPPORT_ROTARY_
4023 rc = EvdevOpenDevice(pInfo);
4028 pEvdev->cur_slot = -1;
4030 #ifdef MULTI_PASSIVE_GRAB_
4031 pEvdev->activatedkeylist = NULL;
4032 #endif //MULTI_PASSIVE_GRAB_
4035 * We initialize pEvdev->in_proximity to 1 so that device that doesn't use
4036 * proximity will still report events.
4038 pEvdev->in_proximity = 1;
4039 pEvdev->use_proximity = 1;
4041 /* Grabbing the event device stops in-kernel event forwarding. In other
4042 words, it disables rfkill and the "Macintosh mouse button emulation".
4043 Note that this needs a server that sets the console to RAW mode. */
4044 pEvdev->grabDevice = xf86CheckBoolOption(pInfo->options, "GrabDevice", 0);
4046 /* If grabDevice is set, ungrab immediately since we only want to grab
4047 * between DEVICE_ON and DEVICE_OFF. If we never get DEVICE_ON, don't
4049 if (!EvdevGrabDevice(pInfo, 1, 1))
4051 xf86IDrvMsg(pInfo, X_WARNING, "Device may already be configured.\n");
4056 EvdevInitButtonMapping(pInfo);
4058 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
4063 memset(&pEvdev->abs_gamepad_labels, 0, sizeof(pEvdev->abs_gamepad_labels));
4065 for(i = 0 ; i < MAX_GAMEPAD_DEFINITION_ABS ; i++)
4067 snprintf(tmp, sizeof(tmp), "GamePad_Condition_ABS%d", i+1);
4068 pEvdev->abs_gamepad_labels[i] = xf86SetIntOption(pInfo->options, tmp, 0);
4076 memset(&pEvdev->key_gamepad_labels, 0, sizeof(pEvdev->key_gamepad_labels));
4078 for(i = 0 ; i < MAX_GAMEPAD_DEFINITION_KEY ; i++)
4080 snprintf(tmp, sizeof(tmp), "GamePad_Condition_KEY%d", i+1);
4082 pEvdev->key_gamepad_labels[i] = xf86SetIntOption(pInfo->options, tmp, BTN_GAMEPAD);
4084 pEvdev->key_gamepad_labels[i] = xf86SetIntOption(pInfo->options, tmp, 0);
4087 #endif//_F_EVDEV_SUPPORT_GAMEPAD
4089 #ifdef _F_USE_DEFAULT_XKB_RULES_
4090 pEvdev->use_default_xkb_rmlvo = xf86SetBoolOption(pInfo->options, "UseDefaultXkbRMLVO", FALSE);
4093 #ifdef _F_EVDEV_SUPPORT_ROTARY_
4094 pEvdev->HW_Calibration = xf86SetIntOption(pInfo->options, "HW_ROTARY_MAX", DEFAULT_HW_ROTARY_MAX);
4095 #endif //_F_EVDEV_SUPPORT_ROTARY_
4097 if (EvdevCache(pInfo) || EvdevProbe(pInfo)) {
4102 EvdevAddDevice(pInfo);
4104 if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
4106 EvdevMBEmuPreInit(pInfo);
4107 Evdev3BEmuPreInit(pInfo);
4108 EvdevWheelEmuPreInit(pInfo);
4109 EvdevDragLockPreInit(pInfo);
4113 if (strstr(pInfo->type_name, XI_TOUCHSCREEN))
4115 pEvdev->mtdev = mtdev_new_open(pInfo->fd);
4119 pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
4123 xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
4130 pEvdev->mtdev = NULL;
4134 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
4135 pEvdev->use_transform = FALSE;
4137 if (strstr(pInfo->type_name, XI_TOUCHSCREEN))
4139 str = xf86CheckStrOption(pInfo->options, "Transform", NULL);
4143 num_transform = sscanf(str, "%f %f %f %f %f %f %f %f %f",
4144 &tr[0], &tr[1], &tr[2],
4145 &tr[3], &tr[4], &tr[5],
4146 &tr[6], &tr[7], &tr[8]);
4147 if (num_transform == 9)
4148 EvdevSetTransformMatrix(pInfo, num_transform, tr);
4151 xf86Msg(X_ERROR, "%s: Insufficient transform factors (%d). Ignoring transform\n",
4152 pInfo->name, num_transform);
4156 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
4158 #ifdef _F_EVDEV_CONFINE_REGION_
4159 pEvdev->confined_id = 0;
4160 pEvdev->pointer_confine_region = NULL;
4162 if (strstr(pInfo->name, XI_TOUCHPAD)
4163 || strstr(pInfo->type_name, XI_MOUSE)
4164 || strstr(pInfo->name, "Virtual Touchpad"))
4166 pEvdev->pointer_confine_region = (BoxPtr)malloc(sizeof(BoxRec));
4168 if (!pEvdev->pointer_confine_region)
4170 xf86IDrvMsg(pInfo, X_ERROR, "Failed to allocate memory for pointer confine region\nConfine feature may not work properly.");
4176 xf86IDrvMsg(pInfo, X_INFO, "Succeed to allocate memory for pointer confine region\nConfine feature will work properly.");
4179 memset(pEvdev->pointer_confine_region, 0, sizeof(BoxRec));
4181 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
4183 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
4184 pEvdev->rel_move_timer = NULL;
4185 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
4187 #ifdef _F_PROXY_DEVICE_ENABLED_
4188 if (!pEvdev->b_proxy_device)
4190 #endif //_F_PROXY_DEVICE_ENABLED_
4191 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
4192 pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo);
4193 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
4194 TimerCancel(pEvdev->rel_move_timer);
4195 ErrorF("[EvdevPreinit] Device: %s has relative events create RMS timer(%p)\n", pInfo->name, pEvdev->rel_move_timer);
4196 #ifdef _F_PROXY_DEVICE_ENABLED_
4198 #endif //_F_PROXY_DEVICE_ENABLED_
4200 pEvdev->rel_move_prop_set = 0;
4201 pEvdev->rel_move_status = 0;
4202 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
4204 #ifdef _F_GESTURE_EXTENSION_
4205 int alloc_size = sizeof(int)*num_slots(pEvdev);
4206 pEvdev->mt_status = NULL;
4208 if (strstr(pInfo->type_name, XI_TOUCHSCREEN))
4210 pEvdev->mt_status = (int *)malloc(alloc_size);
4212 if (!pEvdev->mt_status)
4214 xf86IDrvMsg(pInfo, X_ERROR, "Failed to allocate memory to maintain multitouch status !\nX Gesture driver may not work properly.\n");
4219 memset(pEvdev->mt_status, 0, alloc_size);
4221 #endif /* #ifdef _F_GESTURE_EXTENSION_ */
4222 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
4223 pEvdev->pre_x = 128;
4224 pEvdev->pre_y = 128;
4226 pEvdev->support_directional_key = xf86SetBoolOption(pInfo->options, "Support_Directional_Keys", FALSE);
4228 pEvdev->keycode_btnA = xf86SetIntOption(pInfo->options, "GamePad_ButtonA", 0);
4229 pEvdev->keycode_btnB = xf86SetIntOption(pInfo->options, "GamePad_ButtonB", 0);
4230 pEvdev->keycode_btnX = xf86SetIntOption(pInfo->options, "GamePad_ButtonX", 0);
4231 pEvdev->keycode_btnY = xf86SetIntOption(pInfo->options, "GamePad_ButtonY", 0);
4232 pEvdev->keycode_btnTL = xf86SetIntOption(pInfo->options, "GamePad_ButtonTL", 0);
4233 pEvdev->keycode_btnTR = xf86SetIntOption(pInfo->options, "GamePad_ButtonTR", 0);
4234 pEvdev->keycode_btnStart = xf86SetIntOption(pInfo->options, "GamePad_ButtonStart", 0);
4235 pEvdev->keycode_btnSelect = xf86SetIntOption(pInfo->options, "GamePad_ButtonSelect", 0);
4236 pEvdev->keycode_btnPlay = xf86SetIntOption(pInfo->options, "GamePad_ButtonPlay", 0);
4237 #endif//_F_EVDEV_SUPPORT_GAMEPAD
4239 #ifdef _F_SUPPORT_ROTATION_ANGLE_
4240 pEvdev->rotation_angle = xf86SetIntOption(pInfo->options, "RotationAngle", 0);
4242 str = xf86CheckStrOption(pInfo->options, "RotationNode", NULL);
4246 pEvdev->rotation_node = open(str, O_WRONLY, 0);
4247 } while (pEvdev->rotation_node < 0 && errno == EINTR);
4249 else xf86Msg(X_INFO, "%s: No rotation node exists..\n", pInfo->name);
4251 if (pEvdev->rotation_node < 0) {
4252 xf86Msg(X_ERROR, "Unable to open evdevmultitouch rotation_node\"%s\".\n", str);
4253 xf86Msg(X_ERROR, "Input rotation will be done inside evdevmultitouch driver.\n");
4254 pEvdev->rotation_node = 0;
4256 #endif// _F_SUPPORT_ROTATION_ANGLE_
4262 EvdevCloseDevice(pInfo);
4267 _X_EXPORT InputDriverRec EVDEV = {
4278 EvdevUnplug(pointer p)
4283 EvdevPlug(pointer module,
4288 xf86AddInputDriver(&EVDEV, module, 0);
4292 static XF86ModuleVersionInfo EvdevVersionRec =
4298 XORG_VERSION_CURRENT,
4299 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
4306 _X_EXPORT XF86ModuleData evdevModuleData =
4314 /* Return an index value for a given button event code
4315 * returns 0 on non-button event.
4318 EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code)
4329 case BTN_SIDE ... BTN_JOYSTICK - 1:
4330 return 8 + code - BTN_SIDE;
4332 /* Generic buttons */
4333 case BTN_0 ... BTN_2:
4334 return 1 + code - BTN_0;
4335 case BTN_3 ... BTN_MOUSE - 1:
4336 return 8 + code - BTN_3;
4338 /* Tablet stylus buttons */
4339 case BTN_TOUCH ... BTN_STYLUS2:
4340 return 1 + code - BTN_TOUCH;
4341 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
4342 /* Game pad buttons */
4343 case BTN_A ... BTN_THUMBR:
4344 return 8 + code - BTN_A;
4345 #endif//_F_EVDEV_SUPPORT_GAMEPAD
4354 /* Aligned with linux/input.h.
4355 Note that there are holes in the ABS_ range, these are simply replaced with
4357 static char* abs_labels[] = {
4358 AXIS_LABEL_PROP_ABS_X, /* 0x00 */
4359 AXIS_LABEL_PROP_ABS_Y, /* 0x01 */
4360 AXIS_LABEL_PROP_ABS_Z, /* 0x02 */
4361 AXIS_LABEL_PROP_ABS_RX, /* 0x03 */
4362 AXIS_LABEL_PROP_ABS_RY, /* 0x04 */
4363 AXIS_LABEL_PROP_ABS_RZ, /* 0x05 */
4364 AXIS_LABEL_PROP_ABS_THROTTLE, /* 0x06 */
4365 AXIS_LABEL_PROP_ABS_RUDDER, /* 0x07 */
4366 AXIS_LABEL_PROP_ABS_WHEEL, /* 0x08 */
4367 AXIS_LABEL_PROP_ABS_GAS, /* 0x09 */
4368 AXIS_LABEL_PROP_ABS_BRAKE, /* 0x0a */
4369 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4370 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4371 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4372 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4373 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4374 AXIS_LABEL_PROP_ABS_HAT0X, /* 0x10 */
4375 AXIS_LABEL_PROP_ABS_HAT0Y, /* 0x11 */
4376 AXIS_LABEL_PROP_ABS_HAT1X, /* 0x12 */
4377 AXIS_LABEL_PROP_ABS_HAT1Y, /* 0x13 */
4378 AXIS_LABEL_PROP_ABS_HAT2X, /* 0x14 */
4379 AXIS_LABEL_PROP_ABS_HAT2Y, /* 0x15 */
4380 AXIS_LABEL_PROP_ABS_HAT3X, /* 0x16 */
4381 AXIS_LABEL_PROP_ABS_HAT3Y, /* 0x17 */
4382 AXIS_LABEL_PROP_ABS_PRESSURE, /* 0x18 */
4383 AXIS_LABEL_PROP_ABS_DISTANCE, /* 0x19 */
4384 AXIS_LABEL_PROP_ABS_TILT_X, /* 0x1a */
4385 AXIS_LABEL_PROP_ABS_TILT_Y, /* 0x1b */
4386 AXIS_LABEL_PROP_ABS_TOOL_WIDTH, /* 0x1c */
4387 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4388 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4389 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4390 AXIS_LABEL_PROP_ABS_VOLUME /* 0x20 */
4391 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4392 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4393 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4394 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4395 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4396 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4397 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4398 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4399 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4400 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4401 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4402 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4403 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4404 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4405 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4406 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
4407 AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR, /* 0x30 */
4408 AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR, /* 0x31 */
4409 AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR, /* 0x32 */
4410 AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR, /* 0x33 */
4411 AXIS_LABEL_PROP_ABS_MT_ORIENTATION, /* 0x34 */
4412 AXIS_LABEL_PROP_ABS_MT_POSITION_X, /* 0x35 */
4413 AXIS_LABEL_PROP_ABS_MT_POSITION_Y, /* 0x36 */
4414 AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE, /* 0x37 */
4415 AXIS_LABEL_PROP_ABS_MT_BLOB_ID, /* 0x38 */
4416 AXIS_LABEL_PROP_ABS_MT_TRACKING_ID, /* 0x39 */
4417 AXIS_LABEL_PROP_ABS_MT_PRESSURE, /* 0x3a */
4420 static char* rel_labels[] = {
4421 AXIS_LABEL_PROP_REL_X,
4422 AXIS_LABEL_PROP_REL_Y,
4423 AXIS_LABEL_PROP_REL_Z,
4424 AXIS_LABEL_PROP_REL_RX,
4425 AXIS_LABEL_PROP_REL_RY,
4426 AXIS_LABEL_PROP_REL_RZ,
4427 AXIS_LABEL_PROP_REL_HWHEEL,
4428 AXIS_LABEL_PROP_REL_DIAL,
4429 AXIS_LABEL_PROP_REL_WHEEL,
4430 AXIS_LABEL_PROP_REL_MISC
4433 static char* btn_labels[][16] = {
4434 { /* BTN_MISC group offset 0x100*/
4435 BTN_LABEL_PROP_BTN_0, /* 0x00 */
4436 BTN_LABEL_PROP_BTN_1, /* 0x01 */
4437 BTN_LABEL_PROP_BTN_2, /* 0x02 */
4438 BTN_LABEL_PROP_BTN_3, /* 0x03 */
4439 BTN_LABEL_PROP_BTN_4, /* 0x04 */
4440 BTN_LABEL_PROP_BTN_5, /* 0x05 */
4441 BTN_LABEL_PROP_BTN_6, /* 0x06 */
4442 BTN_LABEL_PROP_BTN_7, /* 0x07 */
4443 BTN_LABEL_PROP_BTN_8, /* 0x08 */
4444 BTN_LABEL_PROP_BTN_9 /* 0x09 */
4446 { /* BTN_MOUSE group offset 0x110 */
4447 BTN_LABEL_PROP_BTN_LEFT, /* 0x00 */
4448 BTN_LABEL_PROP_BTN_RIGHT, /* 0x01 */
4449 BTN_LABEL_PROP_BTN_MIDDLE, /* 0x02 */
4450 BTN_LABEL_PROP_BTN_SIDE, /* 0x03 */
4451 BTN_LABEL_PROP_BTN_EXTRA, /* 0x04 */
4452 BTN_LABEL_PROP_BTN_FORWARD, /* 0x05 */
4453 BTN_LABEL_PROP_BTN_BACK, /* 0x06 */
4454 BTN_LABEL_PROP_BTN_TASK /* 0x07 */
4456 { /* BTN_JOYSTICK group offset 0x120 */
4457 BTN_LABEL_PROP_BTN_TRIGGER, /* 0x00 */
4458 BTN_LABEL_PROP_BTN_THUMB, /* 0x01 */
4459 BTN_LABEL_PROP_BTN_THUMB2, /* 0x02 */
4460 BTN_LABEL_PROP_BTN_TOP, /* 0x03 */
4461 BTN_LABEL_PROP_BTN_TOP2, /* 0x04 */
4462 BTN_LABEL_PROP_BTN_PINKIE, /* 0x05 */
4463 BTN_LABEL_PROP_BTN_BASE, /* 0x06 */
4464 BTN_LABEL_PROP_BTN_BASE2, /* 0x07 */
4465 BTN_LABEL_PROP_BTN_BASE3, /* 0x08 */
4466 BTN_LABEL_PROP_BTN_BASE4, /* 0x09 */
4467 BTN_LABEL_PROP_BTN_BASE5, /* 0x0a */
4468 BTN_LABEL_PROP_BTN_BASE6, /* 0x0b */
4472 BTN_LABEL_PROP_BTN_DEAD /* 0x0f */
4474 { /* BTN_GAMEPAD group offset 0x130 */
4475 BTN_LABEL_PROP_BTN_A, /* 0x00 */
4476 BTN_LABEL_PROP_BTN_B, /* 0x01 */
4477 BTN_LABEL_PROP_BTN_C, /* 0x02 */
4478 BTN_LABEL_PROP_BTN_X, /* 0x03 */
4479 BTN_LABEL_PROP_BTN_Y, /* 0x04 */
4480 BTN_LABEL_PROP_BTN_Z, /* 0x05 */
4481 BTN_LABEL_PROP_BTN_TL, /* 0x06 */
4482 BTN_LABEL_PROP_BTN_TR, /* 0x07 */
4483 BTN_LABEL_PROP_BTN_TL2, /* 0x08 */
4484 BTN_LABEL_PROP_BTN_TR2, /* 0x09 */
4485 BTN_LABEL_PROP_BTN_SELECT, /* 0x0a */
4486 BTN_LABEL_PROP_BTN_START, /* 0x0b */
4487 BTN_LABEL_PROP_BTN_MODE, /* 0x0c */
4488 BTN_LABEL_PROP_BTN_THUMBL, /* 0x0d */
4489 BTN_LABEL_PROP_BTN_THUMBR /* 0x0e */
4491 { /* BTN_DIGI group offset 0x140 */
4492 BTN_LABEL_PROP_BTN_TOOL_PEN, /* 0x00 */
4493 BTN_LABEL_PROP_BTN_TOOL_RUBBER, /* 0x01 */
4494 BTN_LABEL_PROP_BTN_TOOL_BRUSH, /* 0x02 */
4495 BTN_LABEL_PROP_BTN_TOOL_PENCIL, /* 0x03 */
4496 BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH, /* 0x04 */
4497 BTN_LABEL_PROP_BTN_TOOL_FINGER, /* 0x05 */
4498 BTN_LABEL_PROP_BTN_TOOL_MOUSE, /* 0x06 */
4499 BTN_LABEL_PROP_BTN_TOOL_LENS, /* 0x07 */
4502 BTN_LABEL_PROP_BTN_TOUCH, /* 0x0a */
4503 BTN_LABEL_PROP_BTN_STYLUS, /* 0x0b */
4504 BTN_LABEL_PROP_BTN_STYLUS2, /* 0x0c */
4505 BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP, /* 0x0d */
4506 BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP /* 0x0e */
4508 { /* BTN_WHEEL group offset 0x150 */
4509 BTN_LABEL_PROP_BTN_GEAR_DOWN, /* 0x00 */
4510 BTN_LABEL_PROP_BTN_GEAR_UP /* 0x01 */
4514 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int mode, int natoms, Atom *atoms)
4521 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
4522 if (mode == Absolute || pEvdev->flags & EVDEV_GAMEPAD)
4524 if (mode == Absolute)
4525 #endif//_F_EVDEV_SUPPORT_GAMEPAD
4527 labels = abs_labels;
4528 labels_len = ArrayLength(abs_labels);
4529 } else if (mode == Relative)
4531 labels = rel_labels;
4532 labels_len = ArrayLength(rel_labels);
4536 memset(atoms, 0, natoms * sizeof(Atom));
4538 /* Now fill the ones we know */
4539 for (axis = 0; axis < labels_len; axis++)
4541 if (pEvdev->axis_map[axis] == -1)
4544 atom = XIGetKnownProperty(labels[axis]);
4545 if (!atom) /* Should not happen */
4548 atoms[pEvdev->axis_map[axis]] = atom;
4552 static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
4557 /* First, make sure all atoms are initialized */
4558 atom = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN);
4559 for (button = 0; button < natoms; button++)
4560 atoms[button] = atom;
4562 #ifdef _F_EVDEV_SUPPORT_GAMEPAD
4563 for (button = BTN_MISC; button < BTN_THUMBR; button++)
4565 for (button = BTN_MISC; button < BTN_JOYSTICK; button++)
4566 #endif//_F_EVDEV_SUPPORT_GAMEPAD
4568 if (EvdevBitIsSet(pEvdev->key_bitmask, button))
4570 int group = (button % 0x100)/16;
4571 int idx = button - ((button/16) * 16);
4573 if ((unsigned int)group >= sizeof(btn_labels)/sizeof(btn_labels[0]))
4576 if (!btn_labels[group][idx])
4579 atom = XIGetKnownProperty(btn_labels[group][idx]);
4583 /* Props are 0-indexed, button numbers start with 1 */
4584 bmap = EvdevUtilButtonEventToButtonNumber(pEvdev, button) - 1;
4592 /* wheel buttons, hardcoded anyway */
4594 atoms[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
4596 atoms[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
4598 atoms[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
4600 atoms[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
4604 EvdevInitProperty(DeviceIntPtr dev)
4606 InputInfoPtr pInfo = dev->public.devicePrivate;
4607 EvdevPtr pEvdev = pInfo->private;
4610 #ifdef _F_ENABLE_DEVICE_TYPE_PROP_
4612 #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
4613 #ifdef _F_EVDEV_CONFINE_REGION_
4614 int region[6] = { 0, };
4615 #endif /* _F_EVDEV_CONFINE_REGION_ */
4616 #ifdef _F_PROXY_DEVICE_ENABLED_
4618 #endif /* _F_PROXY_DEVICE_ENABLED_ */
4621 #ifdef _F_PICTURE_OFF_MODE_ENABLE_
4622 atomPictureOffMode = MakeAtom(XI_PROP_PICTURE_OFF_MODE,strlen(XI_PROP_PICTURE_OFF_MODE), TRUE);
4623 #endif //_F_PICTURE_OFF_MODE_ENABLE_
4624 prop_product_id = MakeAtom(XI_PROP_PRODUCT_ID, strlen(XI_PROP_PRODUCT_ID), TRUE);
4625 product[0] = pEvdev->id_vendor;
4626 product[1] = pEvdev->id_product;
4627 rc = XIChangeDeviceProperty(dev, prop_product_id, XA_INTEGER, 32,
4628 PropModeReplace, 2, product, FALSE);
4632 XISetDevicePropertyDeletable(dev, prop_product_id, FALSE);
4634 /* Device node property */
4635 device_node = strdup(pEvdev->device);
4636 prop_device = MakeAtom(XI_PROP_DEVICE_NODE,
4637 strlen(XI_PROP_DEVICE_NODE), TRUE);
4640 rc = XIChangeDeviceProperty(dev, prop_device, XA_STRING, 8,
4642 strlen(device_node), device_node,
4647 XISetDevicePropertyDeletable(dev, prop_device, FALSE);
4650 #ifdef _F_ENABLE_DEVICE_TYPE_PROP_
4651 /* Device node property */
4652 device_type = strdup(pInfo->type_name);
4653 prop_device_type = MakeAtom(XI_PROP_DEVICE_TYPE,
4654 strlen(XI_PROP_DEVICE_TYPE), TRUE);
4657 rc = XIChangeDeviceProperty(dev, prop_device_type, XA_STRING, 8,
4659 strlen(device_type), device_type,
4663 #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
4665 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
4666 pEvdev->rel_move_status = 0;
4668 /* Relative movement property */
4669 prop_relative_move_status = MakeAtom(XI_PROP_REL_MOVE_STATUS,
4670 strlen(XI_PROP_REL_MOVE_STATUS), TRUE);
4671 prop_relative_move_ack = MakeAtom(XI_PROP_REL_MOVE_ACK,
4672 strlen(XI_PROP_REL_MOVE_ACK), TRUE);
4673 #ifdef _F_BLOCK_MOTION_DEVICE_
4674 prop_block_motion_status = MakeAtom(XI_PROP_BLOCK_MOTION_DEVICE,
4675 strlen(XI_PROP_BLOCK_MOTION_DEVICE), TRUE);
4676 #endif //_F_BLOCK_MOTION_DEVICE_
4677 ErrorF("[%s] prop_relative_move_status = %d, prop_relative_move_ack = %d\n", __FUNCTION__, prop_relative_move_status, prop_relative_move_ack);
4678 #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */
4680 if (EvdevDeviceIsVirtual(pEvdev->device))
4683 prop_virtual = MakeAtom(XI_PROP_VIRTUAL_DEVICE,
4684 strlen(XI_PROP_VIRTUAL_DEVICE), TRUE);
4685 rc = XIChangeDeviceProperty(dev, prop_virtual, XA_INTEGER, 8,
4686 PropModeReplace, 1, &virtual, FALSE);
4687 XISetDevicePropertyDeletable(dev, prop_virtual, FALSE);
4690 XISetDevicePropertyDeletable(dev, prop_device, FALSE);
4692 #ifdef _F_EVDEV_CONFINE_REGION_
4693 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
4695 prop_confine_region = MakeAtom(EVDEV_PROP_CONFINE_REGION,
4696 strlen(EVDEV_PROP_CONFINE_REGION), TRUE);
4697 rc = XIChangeDeviceProperty(dev, prop_confine_region, XA_INTEGER,
4698 32, PropModeReplace, 4, region, FALSE);
4700 //32, PropModeReplace, 6, region, FALSE);
4705 XISetDevicePropertyDeletable(dev, prop_confine_region, FALSE);
4707 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
4709 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
4710 if (strstr(pInfo->type_name, XI_TOUCHSCREEN))
4712 /* matrix to transform */
4713 prop_transform = MakeAtom(EVDEV_PROP_TOUCH_TRANSFORM_MATRIX, strlen(EVDEV_PROP_TOUCH_TRANSFORM_MATRIX), TRUE);
4714 rc = XIChangeDeviceProperty(dev, prop_transform, XIGetKnownProperty(XATOM_FLOAT), 32, PropModeReplace, 9, pEvdev->transform, FALSE);
4719 XISetDevicePropertyDeletable(dev, prop_transform, FALSE);
4721 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
4724 if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS))
4727 invert[0] = pEvdev->invert_x;
4728 invert[1] = pEvdev->invert_y;
4730 prop_invert = MakeAtom(EVDEV_PROP_INVERT_AXES, strlen(EVDEV_PROP_INVERT_AXES), TRUE);
4732 rc = XIChangeDeviceProperty(dev, prop_invert, XA_INTEGER, 8,
4738 XISetDevicePropertyDeletable(dev, prop_invert, FALSE);
4740 prop_calibration = MakeAtom(EVDEV_PROP_CALIBRATION,
4741 strlen(EVDEV_PROP_CALIBRATION), TRUE);
4742 if (pEvdev->flags & EVDEV_CALIBRATED) {
4745 calibration[0] = pEvdev->calibration.min_x;
4746 calibration[1] = pEvdev->calibration.max_x;
4747 calibration[2] = pEvdev->calibration.min_y;
4748 calibration[3] = pEvdev->calibration.max_y;
4750 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
4751 32, PropModeReplace, 4, calibration,
4753 } else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) {
4754 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
4755 32, PropModeReplace, 0, NULL,
4761 XISetDevicePropertyDeletable(dev, prop_calibration, FALSE);
4763 prop_swap = MakeAtom(EVDEV_PROP_SWAP_AXES,
4764 strlen(EVDEV_PROP_SWAP_AXES), TRUE);
4766 rc = XIChangeDeviceProperty(dev, prop_swap, XA_INTEGER, 8,
4767 PropModeReplace, 1, &pEvdev->swap_axes, FALSE);
4771 XISetDevicePropertyDeletable(dev, prop_swap, FALSE);
4773 /* Axis labelling */
4774 if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
4777 int num_axes = pEvdev->num_vals + pEvdev->num_mt_vals;
4778 Atom atoms[num_axes];
4780 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
4782 else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
4785 xf86IDrvMsg(pInfo, X_ERROR, "BUG: mode is neither absolute nor relative\n");
4789 EvdevInitAxesLabels(pEvdev, mode, num_axes, atoms);
4790 XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32,
4791 PropModeReplace, num_axes, atoms, FALSE);
4792 XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE);
4794 /* Button labelling */
4795 if ((pEvdev->num_buttons > 0) && (prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP)))
4797 Atom atoms[EVDEV_MAXBUTTONS];
4798 EvdevInitButtonLabels(pEvdev, EVDEV_MAXBUTTONS, atoms);
4799 XIChangeDeviceProperty(dev, prop_btn_label, XA_ATOM, 32,
4800 PropModeReplace, pEvdev->num_buttons, atoms, FALSE);
4801 XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE);
4803 #ifdef _F_SUPPORT_ROTATION_ANGLE_
4804 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) {
4806 prop_rotation_angle = MakeAtom(EVDEV_PROP_ROTATION_ANGLE,
4807 strlen(EVDEV_PROP_ROTATION_ANGLE), TRUE);
4809 rotation_angle = pEvdev->rotation_angle;
4810 rc = XIChangeDeviceProperty(dev, prop_rotation_angle, XA_INTEGER, 8,
4811 PropModeReplace, 1, &rotation_angle, TRUE);
4815 XISetDevicePropertyDeletable(dev, prop_rotation_angle, FALSE);
4818 prop_rotation_node = MakeAtom(EVDEV_PROP_ROTATION_NODE,
4819 strlen(EVDEV_PROP_ROTATION_NODE), TRUE);
4821 rotation_node = pEvdev->rotation_node;
4822 rc = XIChangeDeviceProperty(dev, prop_rotation_node, XA_INTEGER, 32,
4823 PropModeReplace, 1, &rotation_node, FALSE);
4827 XISetDevicePropertyDeletable(dev, prop_rotation_node, FALSE);
4829 #endif //_F_SUPPORT_ROTATION_ANGLE_
4831 #ifdef _F_PROXY_DEVICE_ENABLED_
4833 prop_use_proxy_slave_device = MakeAtom(XI_PROP_USE_PROXY_SLAVE_DEVICE, strlen(XI_PROP_USE_PROXY_SLAVE_DEVICE), TRUE);
4834 XIChangeDeviceProperty(dev, prop_use_proxy_slave_device, XA_INTEGER, 8,
4835 PropModeReplace, 1, &slave_proxy, FALSE);
4836 XISetDevicePropertyDeletable(dev, prop_use_proxy_slave_device, FALSE);
4837 pEvdev->proxy_device = NULL;
4838 #endif // _F_PROXY_DEVICE_ENABLED_
4840 #ifdef _F_PROXY_DEVICE_ENABLED_
4842 prop_use_proxy_slave_device = MakeAtom(XI_PROP_USE_PROXY_SLAVE_DEVICE, strlen(XI_PROP_USE_PROXY_SLAVE_DEVICE), TRUE);
4843 XIChangeDeviceProperty(dev, prop_use_proxy_slave_device, XA_INTEGER, 8,
4844 PropModeReplace, 1, &slave_proxy, FALSE);
4845 XISetDevicePropertyDeletable(dev, prop_use_proxy_slave_device, FALSE);
4846 pEvdev->proxy_device = NULL;
4847 #endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */
4851 EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
4854 InputInfoPtr pInfo = dev->public.devicePrivate;
4855 EvdevPtr pEvdev = pInfo->private;
4857 if (atom == prop_invert)
4860 if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
4865 data = (BOOL*)val->data;
4866 pEvdev->invert_x = data[0];
4867 pEvdev->invert_y = data[1];
4869 } else if (atom == prop_calibration)
4871 if (val->format != 32 || val->type != XA_INTEGER)
4873 if (val->size != 4 && val->size != 0)
4877 EvdevSetCalibration(pInfo, val->size, val->data);
4878 } else if (atom == prop_swap)
4880 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
4884 pEvdev->swap_axes = *((BOOL*)val->data);
4885 } else if (atom == prop_axis_label || atom == prop_btn_label ||
4886 atom == prop_product_id || atom == prop_device ||
4887 #ifdef _F_ENABLE_DEVICE_TYPE_PROP_
4888 atom == prop_virtual || atom == prop_device_type)
4889 #else /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
4890 atom == prop_virtual)
4891 #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */
4892 return BadAccess; /* Read-only properties */
4893 #ifdef _F_TOUCH_TRANSFORM_MATRIX_
4894 else if (atom == prop_transform)
4898 if (val->format != 32 || val->type != XIGetKnownProperty(XATOM_FLOAT)
4899 || ((val->size != 9) && (val->size != 1)))
4902 f = (float*)val->data;
4903 EvdevSetTransformMatrix(pInfo, val->size, f);
4906 #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */
4907 #ifdef _F_EVDEV_CONFINE_REGION_
4908 else if (atom == prop_confine_region)
4910 if (val->format != 32 || val->type != XA_INTEGER)
4912 if (val->size != 1 && val->size != 6)
4916 EvdevSetConfineRegion(pInfo, val->size, val->data);
4918 #endif /* #ifdef _F_EVDEV_CONFINE_REGION_ */
4919 #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_
4920 else if (atom == prop_relative_move_ack)
4924 if (val->format != 8 || val->type != XA_INTEGER)
4930 data = *((CARD8*)val->data);
4931 pEvdev->rel_move_ack = data;
4934 if ((pEvdev->rel_move_ack == 2) || (pEvdev->rel_move_ack == 3))
4936 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
4937 TimerCancel(pEvdev->rel_move_timer);
4938 if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer);
4939 pEvdev->rel_move_status = 0;
4942 #endif /* _F_ENABLE_REL_MOVE_STATUS_PROP_ */
4943 #ifdef _F_GESTURE_EXTENSION_
4944 else if (atom == XIGetKnownProperty(XI_PROP_ENABLED))
4946 if (val->format != 8 || val->type != XA_INTEGER)
4952 if (!checkonly && strcasestr(dev->name, "touchscreen"))
4954 DeviceIntPtr device;
4955 for (device = inputInfo.devices; device; device = device->next)
4957 if(!strncmp(device->name, GESTURE_DEV_NAME, sizeof(GESTURE_DEV_NAME)-1))
4959 InputInfoPtr gestureInfo = device->public.devicePrivate;
4960 ErrorF("[EvdevSetProperty][id:%d] find device (%s)\n", device->id, device->name);
4961 gestureInfo->device_control(device, DEVICE_READY);
4967 #endif //_F_GESTURE_EXTENSION_
4969 #ifdef _F_SUPPORT_ROTATION_ANGLE_
4970 else if (atom == prop_rotation_angle)
4974 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
4979 cdata = *((char*)val->data);
4982 EvdevSetRotationAngle(pEvdev, data);
4985 #endif //_F_SUPPORT_ROTATION_ANGLE_
4987 #ifdef _F_PROXY_DEVICE_ENABLED_
4988 else if (atom == prop_use_proxy_slave_device)
4992 if (val->format != 8 || val->type != XA_INTEGER)
4997 if (!pEvdev->proxy_enabled)
5001 data = *((CARD8*)val->data);
5002 EvdevSetProxyDevice(dev,data);
5005 #endif // #ifdef _F_PROXY_DEVICE_ENABLED_
5006 #ifdef _F_BLOCK_MOTION_DEVICE_
5007 else if (atom == prop_block_motion_status )
5012 data = *((CARD8*)val->data);
5013 block_motion_device = data;
5016 else if ((atom == atomPictureOffMode))
5019 data = *((CARD8*)val->data);
5020 pictureOffMode = data;
5022 #endif //_F_BLOCK_MOTION_DEVICE_
5027 #ifdef _F_PROXY_DEVICE_ENABLED_
5029 static int EvdevSetProxyDevice(DeviceIntPtr dev, int val)
5031 InputInfoPtr pInfo = dev->public.devicePrivate;
5032 EvdevPtr pEvdev = pInfo->private;
5034 pEvdev->proxy_device = NULL;
5036 if(NULL == pProxyDeviceInfo) {
5037 pProxyDeviceInfo = EvdevCreateProxyDevice(pInfo);
5039 pEvdev->proxy_device = pProxyDeviceInfo;
5044 /* Duplicate xf86 options and convert them to InputOption */
5045 static InputOption *EvdevOptionDupConvert(pointer original)
5047 InputOption *iopts = NULL, *new;
5050 memset(&dummy, 0, sizeof(dummy));
5051 dummy.options = xf86OptionListDuplicate(original);
5053 while(dummy.options)
5055 if (xf86NameCmp(xf86OptionName(dummy.options), "config_info") == 0) {
5056 /*should not copy config_info as its used by hotplugging layer*/
5057 dummy.options = xf86NextOption(dummy.options);
5060 new = calloc(1, sizeof(struct _InputOption));
5061 if (!new) return iopts;
5063 new->opt_name = xf86OptionName(dummy.options);
5064 new->opt_val = xf86OptionValue(dummy.options);
5065 new->list.next = iopts;
5067 dummy.options = xf86NextOption(dummy.options);
5073 static void EvdevFreeInputOpts(InputOption* opts)
5075 InputOption *tmp = opts;
5078 tmp = opts->list.next;
5079 free(opts->opt_name);
5080 free(opts->opt_val);
5086 static void EvdevReplaceOption(InputOption *opts,const char* key, char * value)
5090 if (xf86NameCmp(opts->opt_name, key) == 0)
5092 free(opts->opt_val);
5093 opts->opt_val = strdup(value);
5095 opts = opts->list.next;
5101 * @return 0 if successful, 1 if failure pProxyDeviceInfo
5104 EvdevCreateProxyDevice(InputInfoPtr pInfo) {
5105 InputInfoPtr pProxyDev;
5107 DeviceIntPtr dev; /* dummy */
5108 InputOption *input_options = NULL;
5110 char str_OPT_TYPE_VAL[sizeof(OPT_TYPE_VAL)];
5111 char str_dev_null[sizeof("/dev/null")];
5113 pInfo->options = xf86AddNewOption(pInfo->options, "Type", "core");
5114 pInfo->options = xf86AddNewOption(pInfo->options, "SendCoreEvents", "on");
5116 /* Create new device */
5117 input_options = EvdevOptionDupConvert(pInfo->options);
5118 snprintf(str_OPT_TYPE_VAL, sizeof(OPT_TYPE_VAL), OPT_TYPE_VAL);
5119 EvdevReplaceOption(input_options, "type",str_OPT_TYPE_VAL);
5121 name = malloc( (strlen(PROXY_DEV_NAME) + 1)*sizeof(char));
5125 EvdevFreeInputOpts(input_options);
5126 xf86DrvMsg(-1, X_ERROR, "[X11][%s] Failed to allocate memory !\n", __FUNCTION__);
5130 snprintf(name, strlen(PROXY_DEV_NAME)+1, PROXY_DEV_NAME);
5131 snprintf(str_dev_null, sizeof("/dev/null"), "/dev/null");
5132 EvdevReplaceOption(input_options, "name",name);
5133 EvdevReplaceOption(input_options, "Device",str_dev_null);
5134 EvdevReplaceOption(input_options, "Path",str_dev_null);
5136 pCreatorInfo = pInfo;
5137 NewInputDeviceRequest(input_options, NULL, &dev);
5138 pProxyDev = dev->public.devicePrivate;
5139 pCreatorInfo = NULL;
5141 EvdevFreeInputOpts(input_options);
5148 EvdevProxydevReadInput(InputInfoPtr pInfo)
5154 MakeClassesChangedEvent(DeviceChangedEvent *dce,
5155 DeviceIntPtr master, DeviceIntPtr slave, int flags)
5158 CARD32 ms = GetTimeInMillis();
5160 memset(dce, 0, sizeof(DeviceChangedEvent));
5161 dce->deviceid = slave->id;
5162 dce->masterid = master ? master->id : 0;
5163 dce->header = ET_Internal;
5164 dce->length = sizeof(DeviceChangedEvent);
5165 dce->type = ET_DeviceChanged;
5168 dce->sourceid = slave->id;
5170 if (slave->button) {
5171 dce->buttons.num_buttons = slave->button->numButtons;
5172 for (i = 0; i < dce->buttons.num_buttons; i++)
5173 dce->buttons.names[i] = slave->button->labels[i];
5175 if (slave->valuator) {
5176 dce->num_valuators = slave->valuator->numAxes;
5177 for (i = 0; i < dce->num_valuators; i++) {
5178 dce->valuators[i].min = slave->valuator->axes[i].min_value;
5179 dce->valuators[i].max = slave->valuator->axes[i].max_value;
5180 dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
5181 dce->valuators[i].mode = slave->valuator->axes[i].mode;
5182 dce->valuators[i].name = slave->valuator->axes[i].label;
5183 dce->valuators[i].scroll = slave->valuator->axes[i].scroll;
5187 dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
5188 dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
5191 #ifndef _F_PROXY_DEVICE_CHANGE_SOURCE_ID
5192 static void EvdevPostDevChangeEvent(InputInfoPtr pInfo)
5194 DeviceChangedEvent event;
5195 DeviceIntPtr master = inputInfo.keyboard;
5196 DeviceIntPtr dummyDevice = pInfo->dev;
5199 if(master->last.slave == dummyDevice) {
5203 flag = DEVCHANGE_KEYBOARD_EVENT | DEVCHANGE_SLAVE_SWITCH;
5205 MakeClassesChangedEvent(&event,master,dummyDevice,flag);
5207 master->last.slave = dummyDevice;
5209 mieqEnqueue (dummyDevice, (InternalEvent*)&event);
5211 #else /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */
5212 static void EvdevCheckDevChange(EvdevPtr pEvdev, int deviceid)
5214 DeviceChangedEvent event;
5215 DeviceIntPtr master;
5216 DeviceIntPtr dummyDevice;
5218 if(!pProxyDeviceInfo || !pEvdev) return;
5220 //if proxydevice is created but is not used by the current device,
5221 //reset the sourcedid of keyclass of the proxy device to its own id
5223 if(pProxyDeviceInfo && !pEvdev->proxy_device) {
5224 pProxyDeviceInfo->dev->key->sourceid = pProxyDeviceInfo->dev->id;
5228 master = inputInfo.keyboard;
5229 dummyDevice = pProxyDeviceInfo->dev;
5231 //if nothing has changed.. return
5232 //the first check is for differentiating between attached slaves and the second
5233 //differentiates between the floating slaves represented by the proxy device
5234 if(master->last.slave == dummyDevice &&
5235 pProxyDeviceInfo->dev->key->sourceid == deviceid) {
5239 flag = DEVCHANGE_KEYBOARD_EVENT | DEVCHANGE_SLAVE_SWITCH;
5241 MakeClassesChangedEvent(&event,master,dummyDevice,flag);
5243 master->last.slave = dummyDevice;
5245 //setting the source id of the device key class to the id of the actual slave it represents.
5246 //clients can query the same to know which device the actual events are coming from
5247 pProxyDeviceInfo->dev->key->sourceid = deviceid;
5249 mieqEnqueue (dummyDevice, (InternalEvent*)&event);
5251 #endif /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */
5252 #endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */