3 * xserver-xorg-input-evdev-multitouch
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.
10 * Copyright © 2004-2008 Red Hat, Inc.
12 * Permission to use, copy, modify, distribute, and sell this software
13 * and its documentation for any purpose is hereby granted without
14 * fee, provided that the above copyright notice appear in all copies
15 * and that both that copyright notice and this permission notice
16 * appear in supporting documentation, and that the name of Red Hat
17 * not be used in advertising or publicity pertaining to distribution
18 * of the software without specific, written prior permission. Red
19 * Hat makes no representations about the suitability of this software
20 * for any purpose. It is provided "as is" without express or implied
23 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
25 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
27 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
28 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 * Kristian Høgsberg (krh@redhat.com)
33 * Adam Jackson (ajax@redhat.com)
34 * Peter Hutterer (peter.hutterer@redhat.com)
35 * Oliver McFadden (oliver.mcfadden@nokia.com)
36 * Benjamin Tissoires (tissoire@cena.fr)
43 #include <X11/keysym.h>
51 #include <xf86Xinput.h>
53 #include <xorgVersion.h>
56 #include "evdevmultitouch.h"
57 #include "vsync_input_protocol.h"
58 #include "vsync_debug_info.h"
60 #ifdef HAVE_PROPERTIES
61 #include <X11/Xatom.h>
62 #include <evdevmultitouch-properties.h>
63 #include <xserver-properties.h>
64 /* 1.6 has properties, but no labels */
65 #ifdef AXIS_LABEL_PROP
74 #include <inputstr.h> /* for MAX_DEVICES */
75 #define MAXDEVICES MAX_DEVICES
78 /* 2.4 compatibility */
80 #define EVIOCGRAB _IOW('E', 0x90, int)
84 #define BTN_TASK 0x117
92 #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
101 #define POLL_DISABLE '0'
102 #define POLL_ENABLE '1'
103 #define POLL_REQUEST '2'
104 #define SYSFS_POLL "/sys/class/input/event2/device/poll"
106 #define ABS_MT_SLOT 0x2f
107 #define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
108 #define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
109 #define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
110 #define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
111 #define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
112 #define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
113 #define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
114 #define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
115 #define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
116 #define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
120 #define SYN_MT_REPORT 2
122 /* evdevmultitouch flags */
123 #define EVDEVMULTITOUCH_KEYBOARD_EVENTS (1 << 0)
124 #define EVDEVMULTITOUCH_BUTTON_EVENTS (1 << 1)
125 #define EVDEVMULTITOUCH_RELATIVE_EVENTS (1 << 2)
126 #define EVDEVMULTITOUCH_ABSOLUTE_EVENTS (1 << 3)
127 #define EVDEVMULTITOUCH_TOUCHPAD (1 << 4)
128 #define EVDEVMULTITOUCH_INITIALIZED (1 << 5) /* WheelInit etc. called already? */
129 #define EVDEVMULTITOUCH_TOUCHSCREEN (1 << 6)
130 #define EVDEVMULTITOUCH_CALIBRATED (1 << 7) /* run-time calibrated? */
131 #define EVDEVMULTITOUCH_TABLET (1 << 8) /* device looks like a tablet? */
132 #define EVDEVMULTITOUCH_UNIGNORE_ABSOLUTE (1 << 9) /* explicitly unignore abs axes */
133 #define EVDEVMULTITOUCH_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
134 #define EVDEVMULTITOUCH_MULTITOUCH (1 << 11) /* device looks like a multi-touch screen? */
135 #define EVDEVMULTITOUCH_RESOLUTION (1 << 12) /* device has a resolution setting? */
137 #define MIN_KEYCODE 8
138 #define GLYPHS_PER_KEY 2
139 #define AltMask Mod1Mask
140 #define NumLockMask Mod2Mask
141 #define AltLangMask Mod3Mask
142 #define KanaMask Mod4Mask
143 #define ScrollLockMask Mod5Mask
149 #define COMPOSEFLAG 16
151 static const char *evdevmultitouchDefaults[] = {
152 "XkbRules", "evdevmultitouch",
153 "XkbModel", "evdevmultitouch",
158 int poll_control(char cmd);
159 void sync_poll(int vsync_counter);
160 #ifdef _F_GESTURE_EXTENSION_
161 extern void mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e);
162 static void EvdevMultitouchFrameSync(InputInfoPtr pInfo, MTSyncType sync);
163 #endif//_F_GESTURE_EXTENSION_
164 static void EvdevMultitouchOff(DeviceIntPtr device);
165 static int EvdevMultitouchOn(DeviceIntPtr);
166 static int EvdevMultitouchCacheCompare(InputInfoPtr pInfo, BOOL compare);
167 static void EvdevMultitouchKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
168 static void EvdevMultitouchProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev);
169 static void EvdevMultitouchCopyFromData(InputInfoPtr pInfo, EvdevMultitouchDataMTPtr pData);
170 static void EvdevMultitouchReinitPEvdevMultitouch(InputInfoPtr pInfo);
171 static void EvdevMultitouchFakeOmittedEvents(InputInfoPtr pInfo);
172 static void EvdevMultitouchProcessEvent(InputInfoPtr pInfo, struct input_event *ev);
173 static void EvdevMultitouchEndOfMultiTouch(InputInfoPtr pInfo,EvdevMultitouchDataMTPtr pData);
174 static void EvdevMultitouchSetMultitouch(InputInfoPtr pInfo, int num_multitouch);
175 static void EvdevMultitouchSetUsePoll(InputInfoPtr pInfo, BOOL use_poll);
176 static void EvdevMultitouchGetGrabInfo(InputInfoPtr pInfo, BOOL val);
177 static void EvdevMultitouchSetResolution(InputInfoPtr pInfo, int num_resolution, int resolution[4]);
178 static void EvdevMultitouchSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
179 static InputInfoPtr EvdevMultitouchCreateSubDevice(InputInfoPtr pInfo, int id);
180 static void EvdevMultitouchDeleteSubDevice(InputInfoPtr pInfo, InputInfoPtr subdev);
181 static void EvdevMultitouchSwapAxes(EvdevMultitouchPtr pEvdevMultitouch);
182 static void EvdevMultitouchSetTransform(InputInfoPtr pInfo, int num_transform, float *tmatrix);
184 #ifdef HAVE_PROPERTIES
185 static void EvdevMultitouchInitAxesLabels(EvdevMultitouchPtr pEvdevMultitouch, int natoms, Atom *atoms);
186 static void EvdevMultitouchInitButtonLabels(EvdevMultitouchPtr pEvdevMultitouch, int natoms, Atom *atoms);
187 static void EvdevMultitouchInitProperty(DeviceIntPtr dev);
188 static int EvdevMultitouchSetProperty(DeviceIntPtr dev, Atom atom,
189 XIPropertyValuePtr val, BOOL checkonly);
190 static Atom prop_invert = 0;
191 static Atom prop_reopen = 0;
192 static Atom prop_calibration = 0;
193 static Atom prop_swap = 0;
194 static Atom prop_axis_label = 0;
195 static Atom prop_btn_label = 0;
196 static Atom prop_tracking_id = 0;
197 static Atom prop_multitouch = 0;
198 static Atom prop_use_poll = 0;
199 static Atom prop_transform = 0;
200 static Atom prop_grabinfo = 0;
203 static InputInfoPtr pCreatorInfo = NULL;
204 volatile VSYNC_INPUT_DISPATCH_TABLE *vsync_input_table = NULL;
206 int g_syspoll_fd = -1;
209 BOOL use_transform = False;
210 struct pixman_transform inv_transform;
213 poll_control(char cmd)
215 if( g_syspoll_fd < 0 )
218 write(g_syspoll_fd, &cmd, 1);
224 sync_poll(int vsync_counter)
228 vsync_debug_set_slot("Poll before");
229 poll_control(POLL_REQUEST);
230 vsync_debug_set_slot("Poll after");
234 /* All devices the evdevmultitouch driver has allocated and knows about.
235 * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
236 * cannot be used by evdevmultitouch, leaving us with a space of 2 at the end. */
237 static EvdevMultitouchPtr evdevmultitouch_devices[MAXDEVICES] = {NULL};
239 static size_t CountBits(unsigned long *array, size_t nlongs)
244 for (i = 0; i < nlongs; i++) {
245 unsigned long x = array[i];
257 EvdevMultitouchGetMajorMinor(InputInfoPtr pInfo)
261 if (fstat(pInfo->fd, &st) == -1)
263 xf86Msg(X_ERROR, "%s: stat failed (%s). cannot check for duplicates.\n",
264 pInfo->name, strerror(errno));
272 EvdevMultitouchIsCoreDevice(InputInfoPtr pInfo) {
273 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
274 return pEvdevMultitouch->core_device == pInfo;
278 * Return TRUE if one of the devices we know about has the same min/maj
282 EvdevMultitouchIsDuplicate(InputInfoPtr pInfo)
284 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
285 EvdevMultitouchPtr* dev = evdevmultitouch_devices;
287 if (pEvdevMultitouch->min_maj)
291 if ((*dev) != pEvdevMultitouch &&
293 (*dev)->min_maj == pEvdevMultitouch->min_maj)
302 * Add to internal device list.
305 EvdevMultitouchAddDevice(InputInfoPtr pInfo)
307 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
308 EvdevMultitouchPtr* dev = evdevmultitouch_devices;
313 *dev = pEvdevMultitouch;
317 * Remove from internal device list.
320 EvdevMultitouchRemoveDevice(InputInfoPtr pInfo)
322 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
323 EvdevMultitouchPtr *dev = evdevmultitouch_devices;
329 if (*dev == pEvdevMultitouch)
331 memmove(dev, dev + 1,
332 sizeof(evdevmultitouch_devices) - (count * sizeof(EvdevMultitouchPtr)));
341 SetXkbOption(InputInfoPtr pInfo, char *name, char **option)
345 if ((s = xf86SetStrOption(pInfo->options, name, NULL))) {
355 static int wheel_up_button = 4;
356 static int wheel_down_button = 5;
357 static int wheel_left_button = 6;
358 static int wheel_right_button = 7;
361 EvdevMultitouchQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
363 int code = ev->code + MIN_KEYCODE;
364 static char warned[KEY_CNT];
365 EventQueuePtr pQueue;
366 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
368 /* Filter all repeated events from device.
369 We'll do softrepeat in the server, but only since 1.6 */
371 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) <= 2
372 && (ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL ||
373 ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT ||
374 ev->code == KEY_LEFTALT || ev->code == KEY_RIGHTALT ||
375 ev->code == KEY_LEFTMETA || ev->code == KEY_RIGHTMETA ||
376 ev->code == KEY_CAPSLOCK || ev->code == KEY_NUMLOCK ||
377 ev->code == KEY_SCROLLLOCK) /* XXX windows keys? */
384 if (ev->code <= KEY_MAX && !warned[ev->code])
386 xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n",
387 pInfo->name, ev->code);
388 warned[ev->code] = 1;
391 /* The X server can't handle keycodes > 255. */
395 if (pEvdevMultitouch->num_queue >= EVDEVMULTITOUCH_MAXQUEUE)
397 xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name);
401 pQueue = &pEvdevMultitouch->queue[pEvdevMultitouch->num_queue];
402 pQueue->type = EV_QUEUE_KEY;
405 pEvdevMultitouch->num_queue++;
409 EvdevMultitouchQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
411 EventQueuePtr pQueue;
412 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
414 if (pEvdevMultitouch->num_queue >= EVDEVMULTITOUCH_MAXQUEUE)
416 xf86Msg(X_NONE, "%s: dropping event due to full queue!\n", pInfo->name);
420 pQueue = &pEvdevMultitouch->queue[pEvdevMultitouch->num_queue];
421 pQueue->type = EV_QUEUE_BTN;
422 pQueue->key = button;
424 pEvdevMultitouch->num_queue++;
428 * Post button event right here, right now.
429 * Interface for MB emulation since these need to post immediately.
432 EvdevMultitouchPostButtonEvent(InputInfoPtr pInfo, int button, int value)
434 xf86PostButtonEvent(pInfo->dev, 0, button, value, 0, 0);
438 EvdevMultitouchQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
442 for (i = 0; i < count; i++) {
443 EvdevMultitouchQueueButtonEvent(pInfo, button, 1);
444 EvdevMultitouchQueueButtonEvent(pInfo, button, 0);
452 EvdevMultitouchSubdevTimer(OsTimerPtr timer, CARD32 time, pointer arg)
454 InputInfoPtr pInfo = (InputInfoPtr)arg;
455 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
458 for (i=0;i<pEvdevMultitouch->num_multitouch;i++) {
459 if (pEvdevMultitouch->vals_mt[i].containsValues) {
460 EvdevMultitouchEndOfMultiTouch(pInfo, &(pEvdevMultitouch->vals_mt[i]));
465 //return pEvdevMultitouch->timeout; /* come back in 100 ms */
469 * Coming back from resume may leave us with a file descriptor that can be
470 * opened but fails on the first read (ENODEV).
471 * In this case, try to open the device until it becomes available or until
472 * the predefined count expires.
475 EvdevMultitouchReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
477 InputInfoPtr pInfo = (InputInfoPtr)arg;
478 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
481 pInfo->fd = open(pEvdevMultitouch->device, O_RDWR | O_NONBLOCK, 0);
482 } while (pInfo->fd < 0 && errno == EINTR);
486 if (EvdevMultitouchCacheCompare(pInfo, TRUE) == Success)
488 xf86Msg(X_INFO, "%s: Device reopened after %d attempts.\n", pInfo->name,
489 pEvdevMultitouch->reopen_attempts - pEvdevMultitouch->reopen_left + 1);
490 EvdevMultitouchOn(pInfo->dev);
493 xf86Msg(X_ERROR, "%s: Device has changed - disabling.\n",
495 xf86DisableDevice(pInfo->dev, FALSE);
498 pEvdevMultitouch->min_maj = 0; /* don't hog the device */
500 pEvdevMultitouch->reopen_left = 0;
504 pEvdevMultitouch->reopen_left--;
506 if (!pEvdevMultitouch->reopen_left)
508 xf86Msg(X_ERROR, "%s: Failed to reopen device after %d attempts.\n",
509 pInfo->name, pEvdevMultitouch->reopen_attempts);
510 xf86DisableDevice(pInfo->dev, FALSE);
511 pEvdevMultitouch->min_maj = 0; /* don't hog the device */
515 return 100; /* come back in 100 ms */
519 EvdevMultitouchMultitouchSettingTimer(OsTimerPtr timer, CARD32 time, pointer arg)
521 InputInfoPtr pInfo = (InputInfoPtr)arg;
522 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
524 int n_multitouch = xf86SetIntOption(pInfo->options, "MultiTouch", 0);
526 if( n_multitouch >= 2 )
527 EvdevMultitouchSetMultitouch(pInfo, n_multitouch);
528 pEvdevMultitouch->multitouch_setting_timer = TimerSet(pEvdevMultitouch->multitouch_setting_timer, 0, 0, NULL, NULL);
533 #define ABS_X_VALUE 0x1
534 #define ABS_Y_VALUE 0x2
535 #define ABS_VALUE 0x4
536 #define ABS_MT_X_VALUE 0x8
537 #define ABS_MT_Y_VALUE 0x10
538 #define ABS_MT_TOUCH_MAJOR_VALUE 0x20
540 * Take the valuators and process them accordingly.
543 EvdevMultitouchProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
547 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
550 *num_v = *first_v = 0;
552 /* convert to relative motion for touchpads */
553 if (pEvdevMultitouch->abs && (pEvdevMultitouch->flags & EVDEVMULTITOUCH_TOUCHPAD)) {
554 if (pEvdevMultitouch->tool) { /* meaning, touch is active */
555 if (pEvdevMultitouch->old_vals[0] != -1)
556 pEvdevMultitouch->delta[REL_X] = pEvdevMultitouch->vals[0] - pEvdevMultitouch->old_vals[0];
557 if (pEvdevMultitouch->old_vals[1] != -1)
558 pEvdevMultitouch->delta[REL_Y] = pEvdevMultitouch->vals[1] - pEvdevMultitouch->old_vals[1];
559 if (pEvdevMultitouch->abs & ABS_X_VALUE)
560 pEvdevMultitouch->old_vals[0] = pEvdevMultitouch->vals[0];
561 if (pEvdevMultitouch->abs & ABS_Y_VALUE)
562 pEvdevMultitouch->old_vals[1] = pEvdevMultitouch->vals[1];
564 pEvdevMultitouch->old_vals[0] = pEvdevMultitouch->old_vals[1] = -1;
566 pEvdevMultitouch->abs = 0;
567 pEvdevMultitouch->rel = 1;
570 if (pEvdevMultitouch->rel) {
571 int first = REL_CNT, last = 0;
574 if (pEvdevMultitouch->swap_axes) {
575 tmp = pEvdevMultitouch->delta[REL_X];
576 pEvdevMultitouch->delta[REL_X] = pEvdevMultitouch->delta[REL_Y];
577 pEvdevMultitouch->delta[REL_Y] = tmp;
579 if (pEvdevMultitouch->invert_x)
580 pEvdevMultitouch->delta[REL_X] *= -1;
581 if (pEvdevMultitouch->invert_y)
582 pEvdevMultitouch->delta[REL_Y] *= -1;
584 for (i = 0; i < REL_CNT; i++)
586 int map = pEvdevMultitouch->axis_map[i];
589 v[map] = pEvdevMultitouch->delta[i];
597 *num_v = (last - first + 1);
601 * Some devices only generate valid abs coords when BTN_DIGI is
602 * pressed. On wacom tablets, this means that the pen is in
603 * proximity of the tablet. After the pen is removed, BTN_DIGI is
604 * released, and a (0, 0) absolute event is generated. Checking
605 * pEvdevMultitouch->digi here, lets us ignore that event. pEvdevMultitouch is
606 * initialized to 1 so devices that doesn't use this scheme still
609 else if (pEvdevMultitouch->abs && pEvdevMultitouch->tool) {
610 memcpy(v, pEvdevMultitouch->vals, sizeof(int) * pEvdevMultitouch->num_vals);
611 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_CALIBRATED)
613 v[0] = xf86ScaleAxis(v[0],
614 pEvdevMultitouch->absinfo[ABS_X].maximum,
615 pEvdevMultitouch->absinfo[ABS_X].minimum,
616 pEvdevMultitouch->calibration.max_x, pEvdevMultitouch->calibration.min_x);
617 v[1] = xf86ScaleAxis(v[1],
618 pEvdevMultitouch->absinfo[ABS_Y].maximum,
619 pEvdevMultitouch->absinfo[ABS_Y].minimum,
620 pEvdevMultitouch->calibration.max_y, pEvdevMultitouch->calibration.min_y);
623 if (pEvdevMultitouch->swap_axes) {
629 if (pEvdevMultitouch->invert_x)
630 v[0] = (pEvdevMultitouch->absinfo[ABS_X].maximum - v[0] +
631 pEvdevMultitouch->absinfo[ABS_X].minimum);
632 if (pEvdevMultitouch->invert_y)
633 v[1] = (pEvdevMultitouch->absinfo[ABS_Y].maximum - v[1] +
634 pEvdevMultitouch->absinfo[ABS_Y].minimum);
638 p.vector[0] = pixman_int_to_fixed(v[0]);
639 p.vector[1] = pixman_int_to_fixed(v[1]);
640 p.vector[2] = pixman_int_to_fixed(1);
642 pixman_transform_point(&inv_transform, &p);
644 v[0] = pixman_fixed_to_int(p.vector[0]);
645 v[1] = pixman_fixed_to_int(p.vector[1]);
648 *num_v = pEvdevMultitouch->num_vals;
654 * Take a button input event and process it accordingly.
657 EvdevMultitouchProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
661 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
663 button = EvdevMultitouchUtilButtonEventToButtonNumber(pEvdevMultitouch, ev->code);
665 /* Get the signed value, earlier kernels had this as unsigned */
668 /* Handle drag lock */
669 if (EvdevMultitouchDragLockFilterEvent(pInfo, button, value))
672 if (EvdevMultitouchWheelEmuFilterButton(pInfo, button, value))
675 if (pEvdevMultitouch->num_multitouch)
678 if (EvdevMultitouchMBEmuFilterEvent(pInfo, button, value))
682 EvdevMultitouchQueueButtonEvent(pInfo, button, value);
684 EvdevMultitouchQueueKbdEvent(pInfo, ev, value);
688 * Take the relative motion input event and process it accordingly.
691 EvdevMultitouchProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
694 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
696 /* Get the signed value, earlier kernels had this as unsigned */
699 pEvdevMultitouch->rel = 1;
704 EvdevMultitouchQueueButtonClicks(pInfo, wheel_up_button, value);
706 EvdevMultitouchQueueButtonClicks(pInfo, wheel_down_button, -value);
712 EvdevMultitouchQueueButtonClicks(pInfo, wheel_right_button, value);
714 EvdevMultitouchQueueButtonClicks(pInfo, wheel_left_button, -value);
717 /* We don't post wheel events as axis motion. */
719 /* Ignore EV_REL events if we never set up for them. */
720 if (!(pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS))
723 /* Handle mouse wheel emulation */
724 if (EvdevMultitouchWheelEmuFilterMotion(pInfo, ev))
727 pEvdevMultitouch->delta[ev->code] += value;
733 * Take the absolute motion input event and process it accordingly.
736 EvdevMultitouchProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
739 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
741 /* Get the signed value, earlier kernels had this as unsigned */
744 /* Ignore EV_ABS events if we never set up for them. */
745 if (!(pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS))
748 if (ev->code > ABS_MAX)
751 pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ev->code]] = value;
753 if(pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH)
755 if(ev->code == ABS_MT_TOUCH_MAJOR)
757 #ifdef _DEBUG_MT_SEQUENCE_
758 ErrorF("[AbsoluteMotionEvent] ABS_MT_TOUCH_MAJOR (value=%d)\n", value);
760 pEvdevMultitouch->abs |= ABS_MT_TOUCH_MAJOR_VALUE;
762 else if (ev->code == ABS_MT_POSITION_X)
764 #ifdef _DEBUG_MT_SEQUENCE_
765 ErrorF("[AbsoluteMotionEvent] ABS_MT_POSITION_X (value=%d)\n", value);
767 EvdevMultitouchFakeOmittedEvents(pInfo);
768 pEvdevMultitouch->abs |= ABS_MT_X_VALUE;
770 else if (ev->code == ABS_MT_POSITION_Y)
772 #ifdef _DEBUG_MT_SEQUENCE_
773 ErrorF("[AbsoluteMotionEvent] ABS_MT_POSITION_Y (value=%d)\n", value);
775 EvdevMultitouchFakeOmittedEvents(pInfo);
776 pEvdevMultitouch->abs |= ABS_MT_Y_VALUE;
779 pEvdevMultitouch->abs |= ABS_VALUE;
783 if (ev->code == ABS_X)
785 #ifdef _DEBUG_MT_SEQUENCE_
786 ErrorF("[AbsoluteMotionEvent] ABS_X (value=%d)\n", value);
788 pEvdevMultitouch->abs |= ABS_X_VALUE;
790 else if (ev->code == ABS_Y)
792 #ifdef _DEBUG_MT_SEQUENCE_
793 ErrorF("[AbsoluteMotionEvent] ABS_Y (value=%d)\n", value);
795 pEvdevMultitouch->abs |= ABS_Y_VALUE;
798 pEvdevMultitouch->abs |= ABS_VALUE;
803 * Take the key press/release input event and process it accordingly.
806 EvdevMultitouchProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
809 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
811 if(pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH)
814 /* Get the signed value, earlier kernels had this as unsigned */
817 /* don't repeat mouse buttons */
818 if (ev->code >= BTN_MOUSE && ev->code < KEY_OK)
822 #ifdef _DEBUG_MT_SEQUENCE_
823 if( ev->code == BTN_TOUCH || ev->code == BTN_LEFT )
824 ErrorF("[KeyEvent] BTN_TOUCH (value=%d)\n", value);
830 case BTN_TOOL_RUBBER:
832 case BTN_TOOL_PENCIL:
833 case BTN_TOOL_AIRBRUSH:
834 case BTN_TOOL_FINGER:
837 pEvdevMultitouch->tool = value ? ev->code : 0;
838 if (!(pEvdevMultitouch->flags & EVDEVMULTITOUCH_TOUCHSCREEN || pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH))
840 /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
843 /* Intentional fallthrough! */
846 EvdevMultitouchProcessButtonEvent(pInfo, ev);
851 static void EvdevMultitouchEndOfMultiTouch(InputInfoPtr pInfo,EvdevMultitouchDataMTPtr pData)
853 InputInfoPtr pSubdev = pData->pInfo;
854 EvdevMultitouchPtr pEvdevMultitouchSubdev = pSubdev->private;
855 pEvdevMultitouchSubdev->id = -1;
856 pData->containsValues = FALSE;
860 #ifdef _F_GESTURE_EXTENSION_
861 static void EvdevMultitouchFrameSync(InputInfoPtr pInfo, MTSyncType sync)
865 memset(&event, 0, sizeof(event));
866 event.header = ET_Internal;
867 event.type = ET_MTSync;
868 event.length = sizeof(event);
869 event.time = GetTimeInMillis();
870 event.deviceid = pInfo->dev->id;
872 mieqEnqueue (pInfo->dev, (InternalEvent*)&event);
874 #endif//_F_GESTURE_EXTENSION_
877 * Post the multtouch motion events.
880 EvdevMultitouchPostMTMotionEvents(InputInfoPtr pInfo,struct input_event *ev)
882 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private, pEvdevMultitouchSubdev;
883 EvdevMultitouchDataMTPtr pData;
884 InputInfoPtr pSubdev;
886 static int num_of_pressed = 0;
888 for (i=0;i<pEvdevMultitouch->num_multitouch;++i) {
889 pData = &(pEvdevMultitouch->vals_mt[i]);
890 if (!pData->containsValues) {
893 pSubdev = pData->pInfo;
897 pData->containsValues = FALSE;
898 EvdevMultitouchCopyFromData(pSubdev, pData);
899 pEvdevMultitouchSubdev = pSubdev->private;
900 pEvdevMultitouchSubdev->mt = 0;
901 pEvdevMultitouchSubdev->abs = pData->abs;
902 pEvdevMultitouchSubdev->rel = 0;
903 pEvdevMultitouchSubdev->tool = 1;
904 /* droping of the pressed/released events */
905 memset(pEvdevMultitouchSubdev->queue, 0, sizeof(pEvdevMultitouchSubdev->queue));
906 pEvdevMultitouchSubdev->num_queue = 0;
908 /* generate button press/release event */
909 if(pEvdevMultitouchSubdev->abs & ABS_MT_TOUCH_MAJOR_VALUE)
911 if(pEvdevMultitouchSubdev->vals[pEvdevMultitouchSubdev->axis_map[ABS_MT_TOUCH_MAJOR]] )
913 if(pEvdevMultitouchSubdev->touch_state == 0)
915 num_of_pressed += (pData->id+1);
916 if( num_of_pressed && !g_pressed )
919 #ifdef _F_GESTURE_EXTENSION_
920 EvdevMultitouchFrameSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN);
921 #endif//_F_GESTURE_EXTENSION_
922 if(vsync_input_table)
924 vsync_input_table->start_sync(vsync_input_table->sync_arg);
928 EvdevMultitouchQueueButtonEvent(pSubdev, 1, 1);
929 pEvdevMultitouchSubdev->touch_state = 1;
934 num_of_pressed -= (pData->id+1);
935 /* last finger release */
936 if( !num_of_pressed )
939 if(vsync_input_table)
941 vsync_input_table->stop_sync(vsync_input_table->sync_arg);
945 EvdevMultitouchQueueButtonEvent(pSubdev, 1, 0);
946 pEvdevMultitouchSubdev->touch_state = 0;
947 pEvdevMultitouchSubdev->evtime = 0;
950 EvdevMultitouchProcessSyncEvent(pSubdev, ev);
956 EvdevMultitouchPostMTMotionEventsBySingle(InputInfoPtr pInfo,struct input_event *ev)
958 EvdevMultitouchPtr pEvdevMultitouch, pEvdevMultitouchSubdev;
959 EvdevMultitouchDataMTPtr pData;
960 InputInfoPtr pSubdev;
962 if( !pInfo || !pInfo->private )
965 pEvdevMultitouch = pInfo->private;
967 pData = &(pEvdevMultitouch->vals_mt[0]);
969 if (!pData->containsValues) {
974 pData->containsValues = FALSE;
975 EvdevMultitouchCopyFromData(pSubdev, pData);
976 pEvdevMultitouchSubdev = pSubdev->private;
977 pEvdevMultitouchSubdev->mt = 0;
978 pEvdevMultitouchSubdev->abs = pData->abs;
979 pEvdevMultitouchSubdev->rel = 0;
980 pEvdevMultitouchSubdev->tool = 1;
981 /* droping of the pressed/released events */
982 memset(pEvdevMultitouchSubdev->queue, 0, sizeof(pEvdevMultitouchSubdev->queue));
983 pEvdevMultitouchSubdev->num_queue = 0;
985 /* generate button press/release event */
986 if(pEvdevMultitouchSubdev->abs & ABS_MT_TOUCH_MAJOR_VALUE)
988 if(pEvdevMultitouchSubdev->vals[pEvdevMultitouchSubdev->axis_map[ABS_MT_TOUCH_MAJOR]] )
990 if(pEvdevMultitouchSubdev->touch_state == 0)
992 EvdevMultitouchQueueButtonEvent(pSubdev, 1, 1);
993 pEvdevMultitouchSubdev->touch_state = 1;
995 #ifdef _F_GESTURE_EXTENSION_
996 EvdevMultitouchFrameSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN);
997 #endif//_F_GESTURE_EXTENSION_
998 if(vsync_input_table)
1000 vsync_input_table->start_sync(vsync_input_table->sync_arg);
1001 vsync_debug_start();
1008 if(vsync_input_table)
1010 vsync_input_table->stop_sync(vsync_input_table->sync_arg);
1013 EvdevMultitouchQueueButtonEvent(pSubdev, 1, 0);
1014 pEvdevMultitouchSubdev->touch_state = 0;
1015 pEvdevMultitouchSubdev->evtime = 0;
1019 EvdevMultitouchProcessSyncEvent(pSubdev, ev);
1023 * Post the relative motion events.
1026 EvdevMultitouchPostRelativeMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
1027 int v[MAX_VALUATORS])
1029 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1031 if (pEvdevMultitouch->rel) {
1032 xf86PostMotionEventP(pInfo->dev, FALSE, *first_v, *num_v, v + *first_v);
1037 * Post the absolute motion events.
1040 EvdevMultitouchPostAbsoluteMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
1041 int v[MAX_VALUATORS])
1043 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1046 * Some devices only generate valid abs coords when BTN_DIGI is
1047 * pressed. On wacom tablets, this means that the pen is in
1048 * proximity of the tablet. After the pen is removed, BTN_DIGI is
1049 * released, and a (0, 0) absolute event is generated. Checking
1050 * pEvdevMultitouch->digi here, lets us ignore that event. pEvdevMultitouch is
1051 * initialized to 1 so devices that doesn't use this scheme still
1054 if (pEvdevMultitouch->abs && pEvdevMultitouch->tool) {
1055 xf86PostMotionEventP(pInfo->dev, TRUE, *first_v, *num_v, v);
1060 * Post the queued key/button events.
1062 static void EvdevMultitouchPostQueuedEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
1063 int v[MAX_VALUATORS])
1066 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1068 for (i = 0; i < pEvdevMultitouch->num_queue; i++) {
1069 switch (pEvdevMultitouch->queue[i].type) {
1071 xf86PostKeyboardEvent(pInfo->dev, pEvdevMultitouch->queue[i].key,
1072 pEvdevMultitouch->queue[i].val);
1075 /* FIXME: Add xf86PostButtonEventP to the X server so that we may
1076 * pass the valuators on ButtonPress/Release events, too. Currently
1077 * only MotionNotify events contain the pointer position. */
1078 xf86PostButtonEvent(pInfo->dev, 0, pEvdevMultitouch->queue[i].key,
1079 pEvdevMultitouch->queue[i].val, 0, 0);
1085 EvdevMultitouchCopyFromData(InputInfoPtr pInfo, EvdevMultitouchDataMTPtr pData) {
1086 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1087 memcpy(pEvdevMultitouch->vals, pData->vals, MAX_VALUATORS * sizeof(int));
1088 /* we drop the buttons/key events */
1092 EvdevMultitouchStoreMTData(InputInfoPtr pInfo, EvdevMultitouchDataMTPtr pData) {
1093 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1095 Time currentTime = GetTimeInMillis();
1097 id = pEvdevMultitouch->current_id;
1099 if(pEvdevMultitouch->abs & ABS_MT_X_VALUE)
1100 x = pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_POSITION_X]];
1102 x = pData->vals[pEvdevMultitouch->axis_map[ABS_X]];
1104 if(pEvdevMultitouch->abs & ABS_MT_Y_VALUE)
1105 y = pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_POSITION_Y]];
1107 y = pData->vals[pEvdevMultitouch->axis_map[ABS_Y]];
1110 EvdevMultitouchPtr pEvdevMultitouchSub = pData->pInfo->private;
1111 pEvdevMultitouchSub->evtime = currentTime;
1115 memcpy(pData->vals, pEvdevMultitouch->vals, MAX_VALUATORS * sizeof(int));
1116 pData->vals[pEvdevMultitouch->axis_map[ABS_X]] = x;
1117 pData->vals[pEvdevMultitouch->axis_map[ABS_Y]] = y;
1118 pData->containsValues = TRUE;
1119 pData->expires = currentTime + pEvdevMultitouch->timeout;
1120 pData->abs = pEvdevMultitouch->abs;
1126 * Take the synchronization input event and process it accordingly; the motion
1127 * notify events are sent first, then any button/key press/release events.
1130 EvdevMultitouchProcessMTSyncReport(InputInfoPtr pInfo, struct input_event *ev)
1132 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1135 id = pEvdevMultitouch->current_id;
1138 EvdevMultitouchReinitPEvdevMultitouch(pInfo);
1142 if(pEvdevMultitouch->num_multitouch == 0) //Single mode
1146 EvdevMultitouchReinitPEvdevMultitouch(pInfo);
1152 if (id > pEvdevMultitouch->num_multitouch-1)
1154 EvdevMultitouchReinitPEvdevMultitouch(pInfo);
1159 EvdevMultitouchStoreMTData(pInfo, &(pEvdevMultitouch->vals_mt[id]));
1160 EvdevMultitouchReinitPEvdevMultitouch(pInfo);
1161 pEvdevMultitouch->mt = 1;
1162 pEvdevMultitouch->sync_mt = 1;
1166 EvdevMultitouchReinitPEvdevMultitouch(InputInfoPtr pInfo) {
1167 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1169 memset(pEvdevMultitouch->delta, 0, sizeof(pEvdevMultitouch->delta));
1170 memset(pEvdevMultitouch->queue, 0, sizeof(pEvdevMultitouch->queue));
1171 pEvdevMultitouch->num_queue = 0;
1172 pEvdevMultitouch->abs = 0;
1173 pEvdevMultitouch->rel = 0;
1174 pEvdevMultitouch->mt = 0;
1175 pEvdevMultitouch->num_mt = 0;
1176 pEvdevMultitouch->current_id = -1;
1177 pEvdevMultitouch->sync_mt = 0;
1181 * Take the synchronization input event and process it accordingly; the motion
1182 * notify events are sent first, then any button/key press/release events.
1185 EvdevMultitouchProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
1187 int num_v = 0, first_v = 0;
1188 int v[MAX_VALUATORS];
1189 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1191 if (ev->code == SYN_MT_REPORT) {
1192 EvdevMultitouchProcessMTSyncReport(pInfo, ev);
1196 if( 0 <= pEvdevMultitouch->current_id && !pEvdevMultitouch->sync_mt )
1198 #ifdef _DEBUG_MT_SEQUENCE_
1199 if( pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_TOUCH_MAJOR]] )
1200 ErrorF("[SyncEvent] Press or Motion !(current->id=%d)\n", pEvdevMultitouch->current_id);
1202 ErrorF("[SyncEvent] Release!(current->id=%d)\n\n", pEvdevMultitouch->current_id);
1205 EvdevMultitouchProcessMTSyncReport(pInfo, ev);
1208 if (pEvdevMultitouch->mt) {
1209 if(pEvdevMultitouch->num_multitouch > 1)
1211 EvdevMultitouchPostMTMotionEvents(pInfo, ev);
1215 EvdevMultitouchPostMTMotionEventsBySingle(pInfo, ev);
1218 EvdevMultitouchProcessValuators(pInfo, v, &num_v, &first_v);
1220 vsync_debug_set_slot("Input %d %d %d", 1, v[0], v[1]);
1222 EvdevMultitouchPostRelativeMotionEvents(pInfo, &num_v, &first_v, v);
1223 EvdevMultitouchPostAbsoluteMotionEvents(pInfo, &num_v, &first_v, v);
1224 EvdevMultitouchPostQueuedEvents(pInfo, &num_v, &first_v, v);
1225 #ifdef _F_GESTURE_EXTENSION_
1227 EvdevMultitouchFrameSync(pInfo, MTOUCH_FRAME_SYNC_END);
1228 #endif//_F_GESTURE_EXTENSION_
1231 EvdevMultitouchReinitPEvdevMultitouch(pInfo);
1235 * Take the trackingID input event and process it accordingly.
1238 EvdevMultitouchProcessTrackingIDEvent(InputInfoPtr pInfo, struct input_event *ev)
1240 // begining of a new touch
1241 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1243 pEvdevMultitouch->last_slot = pEvdevMultitouch->current_id = ev->value;
1244 #ifdef _DEBUG_MT_SEQUENCE_
1245 ErrorF("[TrackingIDEvent] current_id=%d, last_slot=%d\n", pEvdevMultitouch->current_id, pEvdevMultitouch->last_slot);
1250 * Process the events from the device; nothing is actually posted to the server
1251 * until an EV_SYN event is received.
1253 static char* ev_name(int type, int code, int value)
1255 static char ename[100];
1259 char *svalue = NULL;
1272 scode = "SYN_REPORT";
1275 scode = "SYN_CONFIG";
1278 scode = "SYN_MT_REPORT";
1299 scode = "ABS_PRESSURE";
1301 case ABS_MT_TOUCH_MAJOR:
1302 scode = "ABS_MT_TOUCH_MAJOR";
1304 case ABS_MT_TOUCH_MINOR:
1305 scode = "ABS_MT_TOUCH_MINOR";
1307 case ABS_MT_WIDTH_MAJOR:
1308 scode = "ABS_MT_WIDTH_MAJOR";
1310 case ABS_MT_WIDTH_MINOR:
1311 scode = "ABS_MT_WIDTH_MINOR";
1313 case ABS_MT_ORIENTATION:
1314 scode = "ABS_MT_ORIENTATION";
1316 case ABS_MT_POSITION_X:
1317 scode = "ABS_MT_POSITION_X";
1319 case ABS_MT_POSITION_Y:
1320 scode = "ABS_MT_POSITION_Y";
1322 case ABS_MT_TOOL_TYPE:
1323 scode = "ABS_MT_TOOL_TYPE";
1325 case ABS_MT_BLOB_ID:
1326 scode = "ABS_MT_BLOB_ID";
1328 case ABS_MT_TRACKING_ID:
1329 scode = "ABS_MT_TRACKING_ID";
1332 scode = "ABS_MT_SLOT";
1341 sprintf(ttype, "T(0x%x)", type);
1347 sprintf(tcode, "C(0x%x)", code);
1353 sprintf(tvalue, "V(%d)",value);
1357 sprintf(ename, "%s : %s : %s", stype, scode, svalue);
1361 static void EvdevMultitouchFakeOmittedEvents(InputInfoPtr pInfo)
1363 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1365 if( !(pEvdevMultitouch->abs & ABS_MT_TOUCH_MAJOR_VALUE) )
1367 pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_TOUCH_MAJOR]] = 1;
1368 pEvdevMultitouch->abs |= ABS_MT_TOUCH_MAJOR_VALUE;
1369 #ifdef _DEBUG_MT_SEQUENCE_
1370 ErrorF("\t...Fake ABS_MT_TOUCH_MAJOR\n");
1374 if( pEvdevMultitouch->current_id < 0 )
1376 pEvdevMultitouch->current_id = pEvdevMultitouch->last_slot;
1377 #ifdef _DEBUG_MT_SEQUENCE_
1378 ErrorF("\t...Fake ABS_MT_SLOT (current_id=%d)\n", pEvdevMultitouch->current_id);
1384 EvdevMultitouchProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
1386 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1391 EvdevMultitouchProcessRelativeMotionEvent(pInfo, ev);
1402 if( ev->code == ABS_MT_TRACKING_ID )
1404 #ifdef _DEBUG_MT_SEQUENCE_
1405 ErrorF("[ProcessEvent] ABS_MT_TRACKING_ID (value=%d)\n", ev->value);
1408 if( pEvdevMultitouch->mt_slot_supported )
1409 {//MT protocol B Type
1410 if( pEvdevMultitouch->current_id < 0 )
1412 pEvdevMultitouch->current_id = pEvdevMultitouch->last_slot;
1415 if( 0 > ev->value )//ABS_MT_TRACKING_ID == -1
1417 #ifdef _DEBUG_MT_SEQUENCE_
1418 ErrorF("\t...Fake ABS_MT_TOUCH_MAJOR\n");
1420 pEvdevMultitouch->vals[pEvdevMultitouch->axis_map[ABS_MT_TOUCH_MAJOR]] = 0;
1421 pEvdevMultitouch->abs |= ABS_MT_TOUCH_MAJOR_VALUE;
1425 {//MT protocol A Type
1426 EvdevMultitouchProcessTrackingIDEvent(pInfo, ev);
1430 if (ev->code == ABS_MT_SLOT)
1432 #ifdef _DEBUG_MT_SEQUENCE_
1433 ErrorF("[ProcessEvent] ABS_MT_SLOT (value=%d)\n", ev->value);
1435 if( pEvdevMultitouch->last_slot != ev->value )
1437 ev->code = SYN_REPORT;
1438 EvdevMultitouchProcessSyncEvent(pInfo, ev);
1439 ev->code = ABS_MT_SLOT;
1442 EvdevMultitouchProcessTrackingIDEvent(pInfo, ev);
1446 EvdevMultitouchProcessAbsoluteMotionEvent(pInfo, ev);
1451 EvdevMultitouchProcessKeyEvent(pInfo, ev);
1454 #ifdef _DEBUG_MT_SEQUENCE_
1455 if( ev->code == SYN_MT_REPORT )
1456 ErrorF("[ProcessEvent] SYN_MT_REPORT (value=%d)\n", ev->value);
1458 ErrorF("[ProcessEvent] SYN_REPORT (value=%d)\n", ev->value);
1460 EvdevMultitouchProcessSyncEvent(pInfo, ev);
1469 /* just a magic number to reduce the number of reads */
1470 #define NUM_EVENTS 16
1473 * Empty callback for subdevice.
1476 EvdevMultitouchSubdevReadInput(InputInfoPtr pInfo) {
1481 EvdevMultitouchReadInput(InputInfoPtr pInfo)
1483 struct input_event ev[NUM_EVENTS];
1484 int i, len = sizeof(ev);
1485 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
1487 while (len == sizeof(ev))
1489 len = read(pInfo->fd, &ev, sizeof(ev));
1492 if (errno == ENODEV) /* May happen after resume */
1494 EvdevMultitouchMBEmuFinalize(pInfo);
1495 xf86RemoveEnabledDevice(pInfo);
1498 if (pEvdevMultitouch->reopen_timer)
1500 pEvdevMultitouch->reopen_left = pEvdevMultitouch->reopen_attempts;
1501 pEvdevMultitouch->reopen_timer = TimerSet(pEvdevMultitouch->reopen_timer, 0, 100, EvdevMultitouchReopenTimer, pInfo);
1503 } else if (errno != EAGAIN)
1505 /* We use X_NONE here because it doesn't alloc */
1506 xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name,
1512 /* The kernel promises that we always only read a complete
1513 * event, so len != sizeof ev is an error. */
1514 if (len % sizeof(ev[0])) {
1515 /* We use X_NONE here because it doesn't alloc */
1516 xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, strerror(errno));
1520 for (i = 0; i < len/sizeof(ev[0]); i++)
1521 EvdevMultitouchProcessEvent(pInfo, &ev[i]);
1525 #define TestBit(bit, array) ((array[(bit) / LONG_BITS]) & (1L << ((bit) % LONG_BITS)))
1528 EvdevMultitouchPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
1530 /* Nothing to do, dix handles all settings */
1533 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
1534 static KeySym map[] = {
1535 /* 0x00 */ NoSymbol, NoSymbol,
1536 /* 0x01 */ XK_Escape, NoSymbol,
1537 /* 0x02 */ XK_1, XK_exclam,
1538 /* 0x03 */ XK_2, XK_at,
1539 /* 0x04 */ XK_3, XK_numbersign,
1540 /* 0x05 */ XK_4, XK_dollar,
1541 /* 0x06 */ XK_5, XK_percent,
1542 /* 0x07 */ XK_6, XK_asciicircum,
1543 /* 0x08 */ XK_7, XK_ampersand,
1544 /* 0x09 */ XK_8, XK_asterisk,
1545 /* 0x0a */ XK_9, XK_parenleft,
1546 /* 0x0b */ XK_0, XK_parenright,
1547 /* 0x0c */ XK_minus, XK_underscore,
1548 /* 0x0d */ XK_equal, XK_plus,
1549 /* 0x0e */ XK_BackSpace, NoSymbol,
1550 /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,
1551 /* 0x10 */ XK_Q, NoSymbol,
1552 /* 0x11 */ XK_W, NoSymbol,
1553 /* 0x12 */ XK_E, NoSymbol,
1554 /* 0x13 */ XK_R, NoSymbol,
1555 /* 0x14 */ XK_T, NoSymbol,
1556 /* 0x15 */ XK_Y, NoSymbol,
1557 /* 0x16 */ XK_U, NoSymbol,
1558 /* 0x17 */ XK_I, NoSymbol,
1559 /* 0x18 */ XK_O, NoSymbol,
1560 /* 0x19 */ XK_P, NoSymbol,
1561 /* 0x1a */ XK_bracketleft, XK_braceleft,
1562 /* 0x1b */ XK_bracketright,XK_braceright,
1563 /* 0x1c */ XK_Return, NoSymbol,
1564 /* 0x1d */ XK_Control_L, NoSymbol,
1565 /* 0x1e */ XK_A, NoSymbol,
1566 /* 0x1f */ XK_S, NoSymbol,
1567 /* 0x20 */ XK_D, NoSymbol,
1568 /* 0x21 */ XK_F, NoSymbol,
1569 /* 0x22 */ XK_G, NoSymbol,
1570 /* 0x23 */ XK_H, NoSymbol,
1571 /* 0x24 */ XK_J, NoSymbol,
1572 /* 0x25 */ XK_K, NoSymbol,
1573 /* 0x26 */ XK_L, NoSymbol,
1574 /* 0x27 */ XK_semicolon, XK_colon,
1575 /* 0x28 */ XK_quoteright, XK_quotedbl,
1576 /* 0x29 */ XK_quoteleft, XK_asciitilde,
1577 /* 0x2a */ XK_Shift_L, NoSymbol,
1578 /* 0x2b */ XK_backslash, XK_bar,
1579 /* 0x2c */ XK_Z, NoSymbol,
1580 /* 0x2d */ XK_X, NoSymbol,
1581 /* 0x2e */ XK_C, NoSymbol,
1582 /* 0x2f */ XK_V, NoSymbol,
1583 /* 0x30 */ XK_B, NoSymbol,
1584 /* 0x31 */ XK_N, NoSymbol,
1585 /* 0x32 */ XK_M, NoSymbol,
1586 /* 0x33 */ XK_comma, XK_less,
1587 /* 0x34 */ XK_period, XK_greater,
1588 /* 0x35 */ XK_slash, XK_question,
1589 /* 0x36 */ XK_Shift_R, NoSymbol,
1590 /* 0x37 */ XK_KP_Multiply, NoSymbol,
1591 /* 0x38 */ XK_Alt_L, XK_Meta_L,
1592 /* 0x39 */ XK_space, NoSymbol,
1593 /* 0x3a */ XK_Caps_Lock, NoSymbol,
1594 /* 0x3b */ XK_F1, NoSymbol,
1595 /* 0x3c */ XK_F2, NoSymbol,
1596 /* 0x3d */ XK_F3, NoSymbol,
1597 /* 0x3e */ XK_F4, NoSymbol,
1598 /* 0x3f */ XK_F5, NoSymbol,
1599 /* 0x40 */ XK_F6, NoSymbol,
1600 /* 0x41 */ XK_F7, NoSymbol,
1601 /* 0x42 */ XK_F8, NoSymbol,
1602 /* 0x43 */ XK_F9, NoSymbol,
1603 /* 0x44 */ XK_F10, NoSymbol,
1604 /* 0x45 */ XK_Num_Lock, NoSymbol,
1605 /* 0x46 */ XK_Scroll_Lock, NoSymbol,
1606 /* These KP keys should have the KP_7 keysyms in the numlock
1608 /* 0x47 */ XK_KP_Home, XK_KP_7,
1609 /* 0x48 */ XK_KP_Up, XK_KP_8,
1610 /* 0x49 */ XK_KP_Prior, XK_KP_9,
1611 /* 0x4a */ XK_KP_Subtract, NoSymbol,
1612 /* 0x4b */ XK_KP_Left, XK_KP_4,
1613 /* 0x4c */ XK_KP_Begin, XK_KP_5,
1614 /* 0x4d */ XK_KP_Right, XK_KP_6,
1615 /* 0x4e */ XK_KP_Add, NoSymbol,
1616 /* 0x4f */ XK_KP_End, XK_KP_1,
1617 /* 0x50 */ XK_KP_Down, XK_KP_2,
1618 /* 0x51 */ XK_KP_Next, XK_KP_3,
1619 /* 0x52 */ XK_KP_Insert, XK_KP_0,
1620 /* 0x53 */ XK_KP_Delete, XK_KP_Decimal,
1621 /* 0x54 */ NoSymbol, NoSymbol,
1622 /* 0x55 */ XK_F13, NoSymbol,
1623 /* 0x56 */ XK_less, XK_greater,
1624 /* 0x57 */ XK_F11, NoSymbol,
1625 /* 0x58 */ XK_F12, NoSymbol,
1626 /* 0x59 */ XK_F14, NoSymbol,
1627 /* 0x5a */ XK_F15, NoSymbol,
1628 /* 0x5b */ XK_F16, NoSymbol,
1629 /* 0x5c */ XK_F17, NoSymbol,
1630 /* 0x5d */ XK_F18, NoSymbol,
1631 /* 0x5e */ XK_F19, NoSymbol,
1632 /* 0x5f */ XK_F20, NoSymbol,
1633 /* 0x60 */ XK_KP_Enter, NoSymbol,
1634 /* 0x61 */ XK_Control_R, NoSymbol,
1635 /* 0x62 */ XK_KP_Divide, NoSymbol,
1636 /* 0x63 */ XK_Print, XK_Sys_Req,
1637 /* 0x64 */ XK_Alt_R, XK_Meta_R,
1638 /* 0x65 */ NoSymbol, NoSymbol, /* KEY_LINEFEED */
1639 /* 0x66 */ XK_Home, NoSymbol,
1640 /* 0x67 */ XK_Up, NoSymbol,
1641 /* 0x68 */ XK_Prior, NoSymbol,
1642 /* 0x69 */ XK_Left, NoSymbol,
1643 /* 0x6a */ XK_Right, NoSymbol,
1644 /* 0x6b */ XK_End, NoSymbol,
1645 /* 0x6c */ XK_Down, NoSymbol,
1646 /* 0x6d */ XK_Next, NoSymbol,
1647 /* 0x6e */ XK_Insert, NoSymbol,
1648 /* 0x6f */ XK_Delete, NoSymbol,
1649 /* 0x70 */ NoSymbol, NoSymbol, /* KEY_MACRO */
1650 /* 0x71 */ NoSymbol, NoSymbol,
1651 /* 0x72 */ NoSymbol, NoSymbol,
1652 /* 0x73 */ NoSymbol, NoSymbol,
1653 /* 0x74 */ NoSymbol, NoSymbol,
1654 /* 0x75 */ XK_KP_Equal, NoSymbol,
1655 /* 0x76 */ NoSymbol, NoSymbol,
1656 /* 0x77 */ NoSymbol, NoSymbol,
1657 /* 0x78 */ XK_F21, NoSymbol,
1658 /* 0x79 */ XK_F22, NoSymbol,
1659 /* 0x7a */ XK_F23, NoSymbol,
1660 /* 0x7b */ XK_F24, NoSymbol,
1661 /* 0x7c */ XK_KP_Separator, NoSymbol,
1662 /* 0x7d */ XK_Meta_L, NoSymbol,
1663 /* 0x7e */ XK_Meta_R, NoSymbol,
1664 /* 0x7f */ XK_Multi_key, NoSymbol,
1665 /* 0x80 */ NoSymbol, NoSymbol,
1666 /* 0x81 */ NoSymbol, NoSymbol,
1667 /* 0x82 */ NoSymbol, NoSymbol,
1668 /* 0x83 */ NoSymbol, NoSymbol,
1669 /* 0x84 */ NoSymbol, NoSymbol,
1670 /* 0x85 */ NoSymbol, NoSymbol,
1671 /* 0x86 */ NoSymbol, NoSymbol,
1672 /* 0x87 */ NoSymbol, NoSymbol,
1673 /* 0x88 */ NoSymbol, NoSymbol,
1674 /* 0x89 */ NoSymbol, NoSymbol,
1675 /* 0x8a */ NoSymbol, NoSymbol,
1676 /* 0x8b */ NoSymbol, NoSymbol,
1677 /* 0x8c */ NoSymbol, NoSymbol,
1678 /* 0x8d */ NoSymbol, NoSymbol,
1679 /* 0x8e */ NoSymbol, NoSymbol,
1680 /* 0x8f */ NoSymbol, NoSymbol,
1681 /* 0x90 */ NoSymbol, NoSymbol,
1682 /* 0x91 */ NoSymbol, NoSymbol,
1683 /* 0x92 */ NoSymbol, NoSymbol,
1684 /* 0x93 */ NoSymbol, NoSymbol,
1685 /* 0x94 */ NoSymbol, NoSymbol,
1686 /* 0x95 */ NoSymbol, NoSymbol,
1687 /* 0x96 */ NoSymbol, NoSymbol,
1688 /* 0x97 */ NoSymbol, NoSymbol,
1689 /* 0x98 */ NoSymbol, NoSymbol,
1690 /* 0x99 */ NoSymbol, NoSymbol,
1691 /* 0x9a */ NoSymbol, NoSymbol,
1692 /* 0x9b */ NoSymbol, NoSymbol,
1693 /* 0x9c */ NoSymbol, NoSymbol,
1694 /* 0x9d */ NoSymbol, NoSymbol,
1695 /* 0x9e */ NoSymbol, NoSymbol,
1696 /* 0x9f */ NoSymbol, NoSymbol,
1697 /* 0xa0 */ NoSymbol, NoSymbol,
1698 /* 0xa1 */ NoSymbol, NoSymbol,
1699 /* 0xa2 */ NoSymbol, NoSymbol,
1700 /* 0xa3 */ NoSymbol, NoSymbol,
1701 /* 0xa4 */ NoSymbol, NoSymbol,
1702 /* 0xa5 */ NoSymbol, NoSymbol,
1703 /* 0xa6 */ NoSymbol, NoSymbol,
1704 /* 0xa7 */ NoSymbol, NoSymbol,
1705 /* 0xa8 */ NoSymbol, NoSymbol,
1706 /* 0xa9 */ NoSymbol, NoSymbol,
1707 /* 0xaa */ NoSymbol, NoSymbol,
1708 /* 0xab */ NoSymbol, NoSymbol,
1709 /* 0xac */ NoSymbol, NoSymbol,
1710 /* 0xad */ NoSymbol, NoSymbol,
1711 /* 0xae */ NoSymbol, NoSymbol,
1712 /* 0xaf */ NoSymbol, NoSymbol,
1713 /* 0xb0 */ NoSymbol, NoSymbol,
1714 /* 0xb1 */ NoSymbol, NoSymbol,
1715 /* 0xb2 */ NoSymbol, NoSymbol,
1716 /* 0xb3 */ NoSymbol, NoSymbol,
1717 /* 0xb4 */ NoSymbol, NoSymbol,
1718 /* 0xb5 */ NoSymbol, NoSymbol,
1719 /* 0xb6 */ NoSymbol, NoSymbol,
1720 /* 0xb7 */ NoSymbol, NoSymbol,
1721 /* 0xb8 */ NoSymbol, NoSymbol,
1722 /* 0xb9 */ NoSymbol, NoSymbol,
1723 /* 0xba */ NoSymbol, NoSymbol,
1724 /* 0xbb */ NoSymbol, NoSymbol,
1725 /* 0xbc */ NoSymbol, NoSymbol,
1726 /* 0xbd */ NoSymbol, NoSymbol,
1727 /* 0xbe */ NoSymbol, NoSymbol,
1728 /* 0xbf */ NoSymbol, NoSymbol,
1729 /* 0xc0 */ NoSymbol, NoSymbol,
1730 /* 0xc1 */ NoSymbol, NoSymbol,
1731 /* 0xc2 */ NoSymbol, NoSymbol,
1732 /* 0xc3 */ NoSymbol, NoSymbol,
1733 /* 0xc4 */ NoSymbol, NoSymbol,
1734 /* 0xc5 */ NoSymbol, NoSymbol,
1735 /* 0xc6 */ NoSymbol, NoSymbol,
1736 /* 0xc7 */ NoSymbol, NoSymbol,
1737 /* 0xc8 */ NoSymbol, NoSymbol,
1738 /* 0xc9 */ NoSymbol, NoSymbol,
1739 /* 0xca */ NoSymbol, NoSymbol,
1740 /* 0xcb */ NoSymbol, NoSymbol,
1741 /* 0xcc */ NoSymbol, NoSymbol,
1742 /* 0xcd */ NoSymbol, NoSymbol,
1743 /* 0xce */ NoSymbol, NoSymbol,
1744 /* 0xcf */ NoSymbol, NoSymbol,
1745 /* 0xd0 */ NoSymbol, NoSymbol,
1746 /* 0xd1 */ NoSymbol, NoSymbol,
1747 /* 0xd2 */ NoSymbol, NoSymbol,
1748 /* 0xd3 */ NoSymbol, NoSymbol,
1749 /* 0xd4 */ NoSymbol, NoSymbol,
1750 /* 0xd5 */ NoSymbol, NoSymbol,
1751 /* 0xd6 */ NoSymbol, NoSymbol,
1752 /* 0xd7 */ NoSymbol, NoSymbol,
1753 /* 0xd8 */ NoSymbol, NoSymbol,
1754 /* 0xd9 */ NoSymbol, NoSymbol,
1755 /* 0xda */ NoSymbol, NoSymbol,
1756 /* 0xdb */ NoSymbol, NoSymbol,
1757 /* 0xdc */ NoSymbol, NoSymbol,
1758 /* 0xdd */ NoSymbol, NoSymbol,
1759 /* 0xde */ NoSymbol, NoSymbol,
1760 /* 0xdf */ NoSymbol, NoSymbol,
1761 /* 0xe0 */ NoSymbol, NoSymbol,
1762 /* 0xe1 */ NoSymbol, NoSymbol,
1763 /* 0xe2 */ NoSymbol, NoSymbol,
1764 /* 0xe3 */ NoSymbol, NoSymbol,
1765 /* 0xe4 */ NoSymbol, NoSymbol,
1766 /* 0xe5 */ NoSymbol, NoSymbol,
1767 /* 0xe6 */ NoSymbol, NoSymbol,
1768 /* 0xe7 */ NoSymbol, NoSymbol,
1769 /* 0xe8 */ NoSymbol, NoSymbol,
1770 /* 0xe9 */ NoSymbol, NoSymbol,
1771 /* 0xea */ NoSymbol, NoSymbol,
1772 /* 0xeb */ NoSymbol, NoSymbol,
1773 /* 0xec */ NoSymbol, NoSymbol,
1774 /* 0xed */ NoSymbol, NoSymbol,
1775 /* 0xee */ NoSymbol, NoSymbol,
1776 /* 0xef */ NoSymbol, NoSymbol,
1777 /* 0xf0 */ NoSymbol, NoSymbol,
1778 /* 0xf1 */ NoSymbol, NoSymbol,
1779 /* 0xf2 */ NoSymbol, NoSymbol,
1780 /* 0xf3 */ NoSymbol, NoSymbol,
1781 /* 0xf4 */ NoSymbol, NoSymbol,
1782 /* 0xf5 */ NoSymbol, NoSymbol,
1783 /* 0xf6 */ NoSymbol, NoSymbol,
1784 /* 0xf7 */ NoSymbol, NoSymbol,
1787 static struct { KeySym keysym; CARD8 mask; } modifiers[] = {
1788 { XK_Shift_L, ShiftMask },
1789 { XK_Shift_R, ShiftMask },
1790 { XK_Control_L, ControlMask },
1791 { XK_Control_R, ControlMask },
1792 { XK_Caps_Lock, LockMask },
1793 { XK_Alt_L, AltMask },
1794 { XK_Alt_R, AltMask },
1795 { XK_Meta_L, Mod4Mask },
1796 { XK_Meta_R, Mod4Mask },
1797 { XK_Num_Lock, NumLockMask },
1798 { XK_Scroll_Lock, ScrollLockMask },
1799 { XK_Mode_switch, AltLangMask }
1802 /* Server 1.6 and earlier */
1804 EvdevMultitouchInitKeysyms(DeviceIntPtr device)
1807 EvdevMultitouchPtr pEvdevMultitouch;
1809 CARD8 modMap[MAP_LENGTH];
1813 pInfo = device->public.devicePrivate;
1814 pEvdevMultitouch = pInfo->private;
1816 /* Compute the modifier map */
1817 memset(modMap, 0, sizeof modMap);
1819 for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) {
1820 sym = map[i * GLYPHS_PER_KEY];
1821 for (j = 0; j < ArrayLength(modifiers); j++) {
1822 if (modifiers[j].keysym == sym)
1823 modMap[i + MIN_KEYCODE] = modifiers[j].mask;
1828 keySyms.mapWidth = GLYPHS_PER_KEY;
1829 keySyms.minKeyCode = MIN_KEYCODE;
1830 keySyms.maxKeyCode = MIN_KEYCODE + ArrayLength(map) / GLYPHS_PER_KEY - 1;
1832 XkbSetRulesDflts(pEvdevMultitouch->rmlvo.rules, pEvdevMultitouch->rmlvo.model,
1833 pEvdevMultitouch->rmlvo.layout, pEvdevMultitouch->rmlvo.variant,
1834 pEvdevMultitouch->rmlvo.options);
1835 if (!XkbInitKeyboardDeviceStruct(device, &pEvdevMultitouch->xkbnames,
1836 &keySyms, modMap, NULL,
1837 EvdevMultitouchKbdCtrl))
1845 EvdevMultitouchKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
1847 static struct { int xbit, code; } bits[] = {
1848 { CAPSFLAG, LED_CAPSL },
1849 { NUMFLAG, LED_NUML },
1850 { SCROLLFLAG, LED_SCROLLL },
1851 { MODEFLAG, LED_KANA },
1852 { COMPOSEFLAG, LED_COMPOSE }
1856 struct input_event ev[ArrayLength(bits)];
1859 memset(ev, 0, sizeof(ev));
1861 pInfo = device->public.devicePrivate;
1862 for (i = 0; i < ArrayLength(bits); i++) {
1863 ev[i].type = EV_LED;
1864 ev[i].code = bits[i].code;
1865 ev[i].value = (ctrl->leds & bits[i].xbit) > 0;
1868 write(pInfo->fd, ev, sizeof ev);
1872 EvdevMultitouchAddKeyClass(DeviceIntPtr device)
1875 EvdevMultitouchPtr pEvdevMultitouch;
1877 pInfo = device->public.devicePrivate;
1878 pEvdevMultitouch = pInfo->private;
1880 /* sorry, no rules change allowed for you */
1881 xf86ReplaceStrOption(pInfo->options, "xkb_rules", "evdevmultitouch");
1882 SetXkbOption(pInfo, "xkb_rules", &pEvdevMultitouch->rmlvo.rules);
1883 SetXkbOption(pInfo, "xkb_model", &pEvdevMultitouch->rmlvo.model);
1884 if (!pEvdevMultitouch->rmlvo.model)
1885 SetXkbOption(pInfo, "XkbModel", &pEvdevMultitouch->rmlvo.model);
1886 SetXkbOption(pInfo, "xkb_layout", &pEvdevMultitouch->rmlvo.layout);
1887 if (!pEvdevMultitouch->rmlvo.layout)
1888 SetXkbOption(pInfo, "XkbLayout", &pEvdevMultitouch->rmlvo.layout);
1889 SetXkbOption(pInfo, "xkb_variant", &pEvdevMultitouch->rmlvo.variant);
1890 if (!pEvdevMultitouch->rmlvo.variant)
1891 SetXkbOption(pInfo, "XkbVariant", &pEvdevMultitouch->rmlvo.variant);
1892 SetXkbOption(pInfo, "xkb_options", &pEvdevMultitouch->rmlvo.options);
1893 if (!pEvdevMultitouch->rmlvo.options)
1894 SetXkbOption(pInfo, "XkbOptions", &pEvdevMultitouch->rmlvo.options);
1896 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5
1897 if (!InitKeyboardDeviceStruct(device, &pEvdevMultitouch->rmlvo, NULL, EvdevMultitouchKbdCtrl))
1900 if (!EvdevMultitouchInitKeysyms(device))
1905 pInfo->flags |= XI86_KEYBOARD_CAPABLE;
1911 EvdevMultitouchAddAbsClass(DeviceIntPtr device)
1914 EvdevMultitouchPtr pEvdevMultitouch;
1915 EvdevMultitouchPtr g_pEvdevMultitouch;
1916 int num_axes, axis, i = 0;
1919 pInfo = device->public.devicePrivate;
1920 pEvdevMultitouch = pInfo->private;
1922 g_pEvdevMultitouch = pEvdevMultitouch->core_device->private;
1924 if (!TestBit(EV_ABS, g_pEvdevMultitouch->bitmask))
1927 num_axes = CountBits(g_pEvdevMultitouch->abs_bitmask, NLONGS(ABS_MAX));
1930 pEvdevMultitouch->num_vals = num_axes;
1931 memset(pEvdevMultitouch->vals, 0, num_axes * sizeof(int));
1932 memset(pEvdevMultitouch->old_vals, -1, num_axes * sizeof(int));
1933 atoms = malloc(pEvdevMultitouch->num_vals * sizeof(Atom));
1937 ErrorF("[X11][EvdevMultitouchAddAbsClass] Failed to allocate memory !\n", __FUNCTION__);
1941 for (axis = ABS_X; axis <= ABS_MAX; axis++) {
1942 pEvdevMultitouch->axis_map[axis] = -1;
1943 if (!TestBit(axis, pEvdevMultitouch->abs_bitmask))
1945 pEvdevMultitouch->axis_map[axis] = i;
1949 EvdevMultitouchInitAxesLabels(g_pEvdevMultitouch, g_pEvdevMultitouch->num_vals, atoms);
1951 if (!InitValuatorClassDeviceStruct(device, num_axes,
1952 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
1955 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
1958 GetMotionHistorySize(), Absolute))
1961 for (axis = ABS_X; axis <= ABS_MAX; axis++) {
1962 int axnum = g_pEvdevMultitouch->axis_map[axis];
1965 xf86InitValuatorAxisStruct(device, axnum,
1966 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
1969 pEvdevMultitouch->absinfo[axis].minimum,
1970 pEvdevMultitouch->absinfo[axis].maximum,
1972 xf86InitValuatorDefaults(device, axnum);
1973 pEvdevMultitouch->old_vals[axnum] = -1;
1978 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevMultitouchPtrCtrlProc))
1981 if ((TestBit(ABS_X, pEvdevMultitouch->abs_bitmask) &&
1982 TestBit(ABS_Y, pEvdevMultitouch->abs_bitmask)) ||
1983 (TestBit(ABS_RX, pEvdevMultitouch->abs_bitmask) &&
1984 TestBit(ABS_RY, pEvdevMultitouch->abs_bitmask)) ||
1985 (TestBit(ABS_HAT0X, pEvdevMultitouch->abs_bitmask) &&
1986 TestBit(ABS_HAT0Y, pEvdevMultitouch->abs_bitmask)) ||
1987 (TestBit(ABS_HAT1X, pEvdevMultitouch->abs_bitmask) &&
1988 TestBit(ABS_HAT1Y, pEvdevMultitouch->abs_bitmask)) ||
1989 (TestBit(ABS_HAT2X, pEvdevMultitouch->abs_bitmask) &&
1990 TestBit(ABS_HAT2Y, pEvdevMultitouch->abs_bitmask)) ||
1991 (TestBit(ABS_HAT3X, pEvdevMultitouch->abs_bitmask) &&
1992 TestBit(ABS_HAT3Y, pEvdevMultitouch->abs_bitmask)) ||
1993 (TestBit(ABS_TILT_X, pEvdevMultitouch->abs_bitmask) &&
1994 TestBit(ABS_TILT_Y, pEvdevMultitouch->abs_bitmask)))
1995 pInfo->flags |= XI86_POINTER_CAPABLE;
2001 EvdevMultitouchAddRelClass(DeviceIntPtr device)
2004 EvdevMultitouchPtr pEvdevMultitouch;
2005 int num_axes, axis, i = 0;
2008 pInfo = device->public.devicePrivate;
2009 pEvdevMultitouch = pInfo->private;
2011 if (!TestBit(EV_REL, pEvdevMultitouch->bitmask))
2014 num_axes = CountBits(pEvdevMultitouch->rel_bitmask, NLONGS(REL_MAX));
2018 /* Wheels are special, we post them as button events. So let's ignore them
2019 * in the axes list too */
2020 if (TestBit(REL_WHEEL, pEvdevMultitouch->rel_bitmask))
2022 if (TestBit(REL_HWHEEL, pEvdevMultitouch->rel_bitmask))
2024 if (TestBit(REL_DIAL, pEvdevMultitouch->rel_bitmask))
2030 pEvdevMultitouch->num_vals = num_axes;
2031 memset(pEvdevMultitouch->vals, 0, num_axes * sizeof(int));
2032 atoms = malloc(pEvdevMultitouch->num_vals * sizeof(Atom));
2036 ErrorF("[X11][EvdevMultitouchAddRelClass] Failed to allocate memory !\n", __FUNCTION__);
2040 for (axis = REL_X; axis <= REL_MAX; axis++)
2042 pEvdevMultitouch->axis_map[axis] = -1;
2043 /* We don't post wheel events, so ignore them here too */
2044 if (axis == REL_WHEEL || axis == REL_HWHEEL || axis == REL_DIAL)
2046 if (!TestBit(axis, pEvdevMultitouch->rel_bitmask))
2048 pEvdevMultitouch->axis_map[axis] = i;
2052 EvdevMultitouchInitAxesLabels(pEvdevMultitouch, pEvdevMultitouch->num_vals, atoms);
2054 if (!InitValuatorClassDeviceStruct(device, num_axes,
2055 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
2058 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
2061 GetMotionHistorySize(), Relative))
2064 for (axis = REL_X; axis <= REL_MAX; axis++)
2066 int axnum = pEvdevMultitouch->axis_map[axis];
2070 xf86InitValuatorAxisStruct(device, axnum,
2071 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
2075 xf86InitValuatorDefaults(device, axnum);
2080 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevMultitouchPtrCtrlProc))
2083 pInfo->flags |= XI86_POINTER_CAPABLE;
2089 EvdevMultitouchAddButtonClass(DeviceIntPtr device)
2092 EvdevMultitouchPtr pEvdevMultitouch;
2095 pInfo = device->public.devicePrivate;
2096 pEvdevMultitouch = pInfo->private;
2098 labels = malloc(pEvdevMultitouch->num_buttons * sizeof(Atom));
2103 EvdevMultitouchInitButtonLabels(pEvdevMultitouch, pEvdevMultitouch->num_buttons, labels);
2105 if (!InitButtonClassDeviceStruct(device, pEvdevMultitouch->num_buttons,
2106 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
2109 pEvdevMultitouch->btnmap))
2117 * Init the button mapping for the device. By default, this is a 1:1 mapping,
2118 * i.e. Button 1 maps to Button 1, Button 2 to 2, etc.
2120 * If a mapping has been specified, the mapping is the default, with the
2121 * user-defined ones overwriting the defaults.
2122 * i.e. a user-defined mapping of "3 2 1" results in a mapping of 3 2 1 4 5 6 ...
2124 * Invalid button mappings revert to the default.
2126 * Note that index 0 is unused, button 0 does not exist.
2127 * This mapping is initialised for all devices, but only applied if the device
2128 * has buttons (in EvdevMultitouchAddButtonClass).
2131 EvdevMultitouchInitButtonMapping(InputInfoPtr pInfo)
2133 int i, nbuttons = 1;
2134 char *mapping = NULL;
2135 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
2137 /* Check for user-defined button mapping */
2138 if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL)))
2143 xf86Msg(X_CONFIG, "%s: ButtonMapping '%s'\n", pInfo->name, mapping);
2144 while (s && *s != '\0' && nbuttons < EVDEVMULTITOUCH_MAXBUTTONS)
2146 btn = strtol(mapping, &s, 10);
2148 if (s == mapping || btn < 0 || btn > EVDEVMULTITOUCH_MAXBUTTONS)
2151 "%s: ... Invalid button mapping. Using defaults\n",
2153 nbuttons = 1; /* ensure defaults start at 1 */
2157 pEvdevMultitouch->btnmap[nbuttons++] = btn;
2162 for (i = nbuttons; i < ArrayLength(pEvdevMultitouch->btnmap); i++)
2163 pEvdevMultitouch->btnmap[i] = i;
2168 EvdevMultitouchInitAnyClass(DeviceIntPtr device, EvdevMultitouchPtr pEvdevMultitouch)
2170 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS &&
2171 EvdevMultitouchAddRelClass(device) == Success)
2172 xf86Msg(X_INFO, "%s: initialized for relative axes.\n", device->name);
2173 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS &&
2174 EvdevMultitouchAddAbsClass(device) == Success)
2175 xf86Msg(X_INFO, "%s: initialized for absolute axes.\n", device->name);
2179 EvdevMultitouchInitAbsClass(DeviceIntPtr device, EvdevMultitouchPtr pEvdevMultitouch)
2181 if (EvdevMultitouchAddAbsClass(device) == Success) {
2183 xf86Msg(X_INFO,"%s: initialized for absolute axes.\n", device->name);
2187 xf86Msg(X_ERROR,"%s: failed to initialize for absolute axes.\n",
2190 pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_ABSOLUTE_EVENTS;
2196 EvdevMultitouchInitRelClass(DeviceIntPtr device, EvdevMultitouchPtr pEvdevMultitouch)
2198 int has_abs_axes = pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS;
2200 if (EvdevMultitouchAddRelClass(device) == Success) {
2202 xf86Msg(X_INFO,"%s: initialized for relative axes.\n", device->name);
2206 xf86Msg(X_WARNING,"%s: ignoring absolute axes.\n", device->name);
2207 pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_ABSOLUTE_EVENTS;
2212 xf86Msg(X_ERROR,"%s: failed to initialize for relative axes.\n",
2215 pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_RELATIVE_EVENTS;
2218 EvdevMultitouchInitAbsClass(device, pEvdevMultitouch);
2223 EvdevMultitouchInitTouchDevice(DeviceIntPtr device, EvdevMultitouchPtr pEvdevMultitouch)
2225 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS) {
2227 xf86Msg(X_WARNING,"%s: touchpads, tablets and (multi)touchscreens ignore "
2228 "relative axes.\n", device->name);
2230 pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_RELATIVE_EVENTS;
2233 EvdevMultitouchInitAbsClass(device, pEvdevMultitouch);
2237 EvdevMultitouchInit(DeviceIntPtr device)
2241 EvdevMultitouchPtr pEvdevMultitouch;
2243 pInfo = device->public.devicePrivate;
2244 pEvdevMultitouch = pInfo->private;
2246 /* clear all axis_map entries */
2247 for(i = 0; i < max(ABS_CNT,REL_CNT); i++)
2248 pEvdevMultitouch->axis_map[i]=-1;
2250 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_KEYBOARD_EVENTS)
2251 EvdevMultitouchAddKeyClass(device);
2252 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_BUTTON_EVENTS)
2253 EvdevMultitouchAddButtonClass(device);
2255 /* We don't allow relative and absolute axes on the same device. The
2256 * reason is that some devices (MS Optical Desktop 2000) register both
2257 * rel and abs axes for x/y.
2259 * The abs axes register min/max; this min/max then also applies to the
2260 * relative device (the mouse) and caps it at 0..255 for both axes.
2261 * So, unless you have a small screen, you won't be enjoying it much;
2262 * consequently, absolute axes are generally ignored.
2264 * However, currenly only a device with absolute axes can be registered
2265 * as a touch{pad,screen}. Thus, given such a device, absolute axes are
2266 * used and relative axes are ignored.
2269 if (pEvdevMultitouch->flags & (EVDEVMULTITOUCH_UNIGNORE_RELATIVE | EVDEVMULTITOUCH_UNIGNORE_ABSOLUTE))
2270 EvdevMultitouchInitAnyClass(device, pEvdevMultitouch);
2271 else if (pEvdevMultitouch->flags & (EVDEVMULTITOUCH_TOUCHPAD | EVDEVMULTITOUCH_TOUCHSCREEN | EVDEVMULTITOUCH_TABLET | EVDEVMULTITOUCH_MULTITOUCH))
2272 EvdevMultitouchInitTouchDevice(device, pEvdevMultitouch);
2273 else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS)
2274 EvdevMultitouchInitRelClass(device, pEvdevMultitouch);
2275 else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS)
2276 EvdevMultitouchInitAbsClass(device, pEvdevMultitouch);
2278 #ifdef HAVE_PROPERTIES
2279 /* We drop the return value, the only time we ever want the handlers to
2280 * unregister is when the device dies. In which case we don't have to
2281 * unregister anyway */
2282 EvdevMultitouchInitProperty(device);
2283 XIRegisterPropertyHandler(device, EvdevMultitouchSetProperty, NULL, NULL);
2284 EvdevMultitouchMBEmuInitProperty(device);
2285 EvdevMultitouchWheelEmuInitProperty(device);
2286 EvdevMultitouchDragLockInitProperty(device);
2293 * Init all extras (wheel emulation, etc.) and grab the device.
2295 * Coming from a resume, the grab may fail with ENODEV. In this case, we set a
2296 * timer to wake up and try to reopen the device later.
2299 EvdevMultitouchOn(DeviceIntPtr device)
2302 EvdevMultitouchPtr pEvdevMultitouch;
2304 BOOL finish = False;
2307 pInfo = device->public.devicePrivate;
2308 pEvdevMultitouch = pInfo->private;
2310 /* If this is an object device,
2311 * just add device to subdev list */
2312 if (!EvdevMultitouchIsCoreDevice(pInfo)) {
2315 if (pInfo->fd != -1 && pEvdevMultitouch->grabDevice &&
2316 (rc = ioctl(pInfo->fd, EVIOCGRAB, (void *)1)))
2318 xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
2321 /* ENODEV - device has disappeared after resume */
2322 if (rc && errno == ENODEV)
2329 if (pInfo->fd == -1)
2331 pEvdevMultitouch->reopen_left = pEvdevMultitouch->reopen_attempts;
2332 pEvdevMultitouch->reopen_timer = TimerSet(pEvdevMultitouch->reopen_timer, 0, 100, EvdevMultitouchReopenTimer, pInfo);
2335 pEvdevMultitouch->min_maj = EvdevMultitouchGetMajorMinor(pInfo);
2336 if (EvdevMultitouchIsDuplicate(pInfo))
2338 xf86Msg(X_WARNING, "%s: Refusing to enable duplicate device.\n",
2344 pEvdevMultitouch->reopen_timer = TimerSet(pEvdevMultitouch->reopen_timer, 0, 0, NULL, NULL);
2346 xf86FlushInput(pInfo->fd);
2348 EvdevMultitouchSetMultitouch(pInfo, pEvdevMultitouch->num_multitouch);
2355 if( !strstr(pInfo->name, "subdev" ) )
2357 xf86AddEnabledDevice(pInfo);
2358 pEvdevMultitouch->last_slot = 0;
2359 EvdevMultitouchReinitPEvdevMultitouch(pInfo);
2361 EvdevMultitouchMBEmuOn(pInfo);
2362 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_INITIALIZED;
2363 device->public.on = TRUE;
2365 pEvdevMultitouch->multitouch_setting_timer = TimerSet(pEvdevMultitouch->multitouch_setting_timer, 0, 100, EvdevMultitouchMultitouchSettingTimer, pInfo);
2368 if( pEvdevMultitouch->use_poll != TRUE )
2371 EvdevMultitouchSetUsePoll(pInfo, TRUE);
2377 EvdevMultitouchOff(DeviceIntPtr device)
2380 EvdevMultitouchPtr pEvdevMultitouch;
2382 pInfo = device->public.devicePrivate;
2383 pEvdevMultitouch = pInfo->private;
2385 if( pEvdevMultitouch->use_poll != TRUE )
2388 EvdevMultitouchSetUsePoll(pInfo, FALSE);
2392 EvdevMultitouchProc(DeviceIntPtr device, int what)
2395 EvdevMultitouchPtr pEvdevMultitouch, g_pEvdevMultitouch;
2399 pInfo = device->public.devicePrivate;
2400 pEvdevMultitouch = pInfo->private;
2405 return EvdevMultitouchInit(device);
2408 return EvdevMultitouchOn(device);
2411 EvdevMultitouchOff(device);
2412 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_INITIALIZED)
2413 EvdevMultitouchMBEmuFinalize(pInfo);
2414 if (EvdevMultitouchIsCoreDevice(pInfo)){
2415 EvdevMultitouchSetMultitouch(pInfo, 0);
2416 if (pInfo->fd != -1)
2418 if (pEvdevMultitouch->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)0))
2419 xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
2421 xf86RemoveEnabledDevice(pInfo);
2425 if( pEvdevMultitouch->multitouch_setting_timer )
2427 TimerFree(pEvdevMultitouch->multitouch_setting_timer);
2428 pEvdevMultitouch->multitouch_setting_timer = NULL;
2430 if (pEvdevMultitouch->reopen_timer)
2432 TimerFree(pEvdevMultitouch->reopen_timer);
2433 pEvdevMultitouch->reopen_timer = NULL;
2436 /* removing it in the list of the core device */
2437 g_pEvdevMultitouch = pEvdevMultitouch->core_device->private;
2438 for (i=0; i<MAX_VALUATORS_MT; ++i) {
2439 if (g_pEvdevMultitouch->vals_mt[i].pInfo == pInfo) {
2440 g_pEvdevMultitouch->vals_mt[i].pInfo = NULL;
2444 xf86RemoveEnabledDevice(pInfo);
2446 pEvdevMultitouch->min_maj = 0;
2447 pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_INITIALIZED;
2448 device->public.on = FALSE;
2452 xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
2453 if (EvdevMultitouchIsCoreDevice(pInfo)) { // master only
2454 //EvdevMultitouchDeleteAllSubdevices(pInfo);
2456 if (pInfo->fd != -1) {
2460 EvdevMultitouchRemoveDevice(pInfo);
2462 pEvdevMultitouch->min_maj = 0;
2470 * Get as much information as we can from the fd and cache it.
2471 * If compare is True, then the information retrieved will be compared to the
2472 * one already cached. If the information does not match, then this function
2475 * @return Success if the information was cached, or !Success otherwise.
2478 EvdevMultitouchCacheCompare(InputInfoPtr pInfo, BOOL compare)
2480 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
2483 char name[1024] = {0};
2484 unsigned long bitmask[NLONGS(EV_CNT)] = {0};
2485 unsigned long key_bitmask[NLONGS(KEY_CNT)] = {0};
2486 unsigned long rel_bitmask[NLONGS(REL_CNT)] = {0};
2487 unsigned long abs_bitmask[NLONGS(ABS_CNT)] = {0};
2488 unsigned long led_bitmask[NLONGS(LED_CNT)] = {0};
2490 if (ioctl(pInfo->fd, EVIOCGNAME(sizeof(name) - 1), name) < 0) {
2491 xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
2496 strcpy(pEvdevMultitouch->name, name);
2497 } else if (strcmp(pEvdevMultitouch->name, name)) {
2498 xf86Msg(X_ERROR, "%s: device name changed: %s != %s\n",
2499 pInfo->name, pEvdevMultitouch->name, name);
2503 len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask);
2505 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
2506 pInfo->name, strerror(errno));
2511 memcpy(pEvdevMultitouch->bitmask, bitmask, len);
2512 } else if (memcmp(pEvdevMultitouch->bitmask, bitmask, len)) {
2513 xf86Msg(X_ERROR, "%s: device bitmask has changed\n", pInfo->name);
2517 len = ioctl(pInfo->fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask);
2519 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
2520 pInfo->name, strerror(errno));
2525 memcpy(pEvdevMultitouch->rel_bitmask, rel_bitmask, len);
2526 } else if (memcmp(pEvdevMultitouch->rel_bitmask, rel_bitmask, len)) {
2527 xf86Msg(X_ERROR, "%s: device rel_bitmask has changed\n", pInfo->name);
2531 len = ioctl(pInfo->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
2533 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
2534 pInfo->name, strerror(errno));
2539 if( TestBit(ABS_MT_SLOT, abs_bitmask) && TestBit(ABS_MT_TRACKING_ID, abs_bitmask) )
2541 ErrorF("[X11] MT Protocol B Type : ABS_MT_SLOT is supported : \n");
2542 pEvdevMultitouch->mt_slot_supported = (BOOL)1;
2546 ErrorF("[X11] MT Protocol A Type : ABS_MT_SLOT is NOT supported\n");
2547 pEvdevMultitouch->mt_slot_supported = (BOOL)0;
2552 memcpy(pEvdevMultitouch->abs_bitmask, abs_bitmask, len);
2553 } else if (memcmp(pEvdevMultitouch->abs_bitmask, abs_bitmask, len)) {
2554 xf86Msg(X_ERROR, "%s: device abs_bitmask has changed\n", pInfo->name);
2558 len = ioctl(pInfo->fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask);
2560 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
2561 pInfo->name, strerror(errno));
2566 memcpy(pEvdevMultitouch->led_bitmask, led_bitmask, len);
2567 } else if (memcmp(pEvdevMultitouch->led_bitmask, led_bitmask, len)) {
2568 xf86Msg(X_ERROR, "%s: device led_bitmask has changed\n", pInfo->name);
2573 * Do not try to validate absinfo data since it is not expected
2574 * to be static, always refresh it in evdevmultitouch structure.
2576 if( !xf86CheckStrOption(pInfo->options, "Resolution", NULL) )
2578 #ifdef _F_IGNORE_TSP_RESOLUTION_
2579 pEvdevMultitouch->absinfo[ABS_X].maximum = 0;
2580 pEvdevMultitouch->absinfo[ABS_X].minimum = 0;
2581 pEvdevMultitouch->absinfo[ABS_Y].maximum = 0;
2582 pEvdevMultitouch->absinfo[ABS_Y].minimum = 0;
2583 #else//_F_IGNORE_TSP_RESOLUTION_
2584 for (i = ABS_X; i <= ABS_MAX; i++) {
2585 if (TestBit(i, abs_bitmask)) {
2586 len = ioctl(pInfo->fd, EVIOCGABS(i), &pEvdevMultitouch->absinfo[i]);
2588 xf86Msg(X_ERROR, "%s: ioctl EVIOCGABSi(%d) failed: %s\n",
2589 pInfo->name, i, strerror(errno));
2594 #endif//_F_IGNORE_TSP_RESOLUTION_
2597 len = ioctl(pInfo->fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
2599 xf86Msg(X_ERROR, "%s: ioctl EVIOCGBIT failed: %s\n",
2600 pInfo->name, strerror(errno));
2606 * Keys are special as user can adjust keymap at any time (on
2607 * devices that support EVIOCSKEYCODE. However we do not expect
2608 * buttons reserved for mice/tablets/digitizers and so on to
2609 * appear/disappear so we will check only those in
2610 * [BTN_MISC, KEY_OK) range.
2612 size_t start_word = BTN_MISC / LONG_BITS;
2613 size_t start_byte = start_word * sizeof(unsigned long);
2614 size_t end_word = KEY_OK / LONG_BITS;
2615 size_t end_byte = end_word * sizeof(unsigned long);
2617 if (len >= start_byte &&
2618 memcmp(&pEvdevMultitouch->key_bitmask[start_word], &key_bitmask[start_word],
2619 min(len, end_byte) - start_byte + 1)) {
2620 xf86Msg(X_ERROR, "%s: device key_bitmask has changed\n", pInfo->name);
2625 /* Copy the data so we have reasonably up-to-date info */
2626 memcpy(pEvdevMultitouch->key_bitmask, key_bitmask, len);
2636 EvdevMultitouchProbe(InputInfoPtr pInfo)
2638 int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll;
2640 int ignore_abs = 0, ignore_rel = 0;
2641 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
2643 if (pEvdevMultitouch->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
2644 if (errno == EINVAL) {
2645 /* keyboards are unsafe in 2.4 */
2647 pEvdevMultitouch->grabDevice = 0;
2649 xf86Msg(X_ERROR, "Grab failed. Device already configured?\n");
2652 } else if (pEvdevMultitouch->grabDevice) {
2653 ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
2656 /* Trinary state for ignoring axes:
2657 - unset: do the normal thing.
2658 - TRUE: explicitly ignore them.
2659 - FALSE: unignore axes, use them at all cost if they're present.
2661 if (xf86FindOption(pInfo->options, "IgnoreRelativeAxes"))
2663 if (xf86SetBoolOption(pInfo->options, "IgnoreRelativeAxes", FALSE))
2666 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_UNIGNORE_RELATIVE;
2669 if (xf86FindOption(pInfo->options, "IgnoreAbsoluteAxes"))
2671 if (xf86SetBoolOption(pInfo->options, "IgnoreAbsoluteAxes", FALSE))
2674 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_UNIGNORE_ABSOLUTE;
2677 has_rel_axes = FALSE;
2678 has_abs_axes = FALSE;
2683 /* count all buttons */
2684 for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
2687 if (TestBit(i, pEvdevMultitouch->key_bitmask))
2689 mapping = EvdevMultitouchUtilButtonEventToButtonNumber(pEvdevMultitouch, i);
2690 if (mapping > num_buttons)
2691 num_buttons = mapping;
2697 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_BUTTON_EVENTS;
2698 pEvdevMultitouch->num_buttons = num_buttons;
2699 xf86Msg(X_INFO, "%s: Found %d mouse buttons\n", pInfo->name,
2703 for (i = 0; i < REL_MAX; i++) {
2704 if (TestBit(i, pEvdevMultitouch->rel_bitmask)) {
2705 has_rel_axes = TRUE;
2711 if (TestBit(REL_WHEEL, pEvdevMultitouch->rel_bitmask) ||
2712 TestBit(REL_HWHEEL, pEvdevMultitouch->rel_bitmask) ||
2713 TestBit(REL_DIAL, pEvdevMultitouch->rel_bitmask)) {
2714 xf86Msg(X_INFO, "%s: Found scroll wheel(s)\n", pInfo->name);
2717 xf86Msg(X_INFO, "%s: Forcing buttons for scroll wheel(s)\n",
2719 num_buttons = (num_buttons < 3) ? 7 : num_buttons + 4;
2720 pEvdevMultitouch->num_buttons = num_buttons;
2725 xf86Msg(X_INFO, "%s: Found relative axes\n", pInfo->name);
2726 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_RELATIVE_EVENTS;
2728 if (TestBit(REL_X, pEvdevMultitouch->rel_bitmask) &&
2729 TestBit(REL_Y, pEvdevMultitouch->rel_bitmask)) {
2730 xf86Msg(X_INFO, "%s: Found x and y relative axes\n", pInfo->name);
2733 xf86Msg(X_INFO, "%s: Relative axes present but ignored.\n", pInfo->name);
2734 has_rel_axes = FALSE;
2738 for (i = 0; i < ABS_MAX; i++) {
2739 if (TestBit(i, pEvdevMultitouch->abs_bitmask)) {
2740 has_abs_axes = TRUE;
2745 if (ignore_abs && has_abs_axes)
2747 xf86Msg(X_INFO, "%s: Absolute axes present but ignored.\n", pInfo->name);
2748 has_abs_axes = FALSE;
2749 } else if (has_abs_axes) {
2750 xf86Msg(X_INFO, "%s: Found absolute axes\n", pInfo->name);
2751 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_ABSOLUTE_EVENTS;
2753 if ((TestBit(ABS_X, pEvdevMultitouch->abs_bitmask) &&
2754 TestBit(ABS_Y, pEvdevMultitouch->abs_bitmask))) {
2755 xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
2756 if (TestBit(BTN_TOOL_PEN, pEvdevMultitouch->key_bitmask))
2758 xf86Msg(X_INFO, "%s: Found absolute tablet.\n", pInfo->name);
2759 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_TABLET;
2760 } else if ((TestBit(ABS_MT_POSITION_X, pEvdevMultitouch->abs_bitmask) &&
2761 TestBit(ABS_MT_POSITION_Y, pEvdevMultitouch->abs_bitmask))) {
2762 xf86Msg(X_INFO, "%s: Found absolute multitouch tablet.\n", pInfo->name);
2763 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_MULTITOUCH;
2764 } else if (TestBit(ABS_PRESSURE, pEvdevMultitouch->abs_bitmask) ||
2765 TestBit(BTN_TOUCH, pEvdevMultitouch->key_bitmask)) {
2766 if (num_buttons || TestBit(BTN_TOOL_FINGER, pEvdevMultitouch->key_bitmask)) {
2767 xf86Msg(X_INFO, "%s: Found absolute touchpad.\n", pInfo->name);
2768 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_TOUCHPAD;
2769 memset(pEvdevMultitouch->old_vals, -1, sizeof(int) * pEvdevMultitouch->num_vals);
2771 xf86Msg(X_INFO, "%s: Found absolute touchscreen\n", pInfo->name);
2772 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_TOUCHSCREEN;
2773 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_BUTTON_EVENTS;
2779 for (i = 0; i < BTN_MISC; i++) {
2780 if (TestBit(i, pEvdevMultitouch->key_bitmask)) {
2781 xf86Msg(X_INFO, "%s: Found keys\n", pInfo->name);
2782 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_KEYBOARD_EVENTS;
2788 if (has_rel_axes || has_abs_axes || num_buttons) {
2789 pInfo->flags |= XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS |
2791 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_TOUCHPAD) {
2792 xf86Msg(X_INFO, "%s: Configuring as touchpad\n", pInfo->name);
2793 pInfo->type_name = XI_TOUCHPAD;
2794 } else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_TABLET) {
2795 xf86Msg(X_INFO, "%s: Configuring as tablet\n", pInfo->name);
2796 pInfo->type_name = XI_TABLET;
2797 } else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_TOUCHSCREEN) {
2798 xf86Msg(X_INFO, "%s: Configuring as touchscreen\n", pInfo->name);
2799 pInfo->type_name = XI_TOUCHSCREEN;
2800 } else if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH) {
2801 xf86Msg(X_INFO, "%s: Configuring as multitouch screen\n", pInfo->name);
2802 pInfo->type_name = "MULTITOUCHSCREEN";
2804 xf86Msg(X_INFO, "%s: Configuring as mouse\n", pInfo->name);
2805 pInfo->type_name = XI_MOUSE;
2811 xf86Msg(X_INFO, "%s: Kernel < 2.6 is too old, ignoring keyboard\n",
2814 xf86Msg(X_INFO, "%s: Configuring as keyboard\n", pInfo->name);
2815 pInfo->flags |= XI86_KEYBOARD_CAPABLE | XI86_CONFIGURED;
2816 pInfo->type_name = XI_KEYBOARD;
2820 if (has_scroll && (pInfo->flags & XI86_CONFIGURED) &&
2821 (pInfo->flags & XI86_POINTER_CAPABLE) == 0)
2823 xf86Msg(X_INFO, "%s: Adding scrollwheel support\n", pInfo->name);
2824 pInfo->flags |= XI86_POINTER_CAPABLE;
2825 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_BUTTON_EVENTS;
2826 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_RELATIVE_EVENTS;
2829 if ((pInfo->flags & XI86_CONFIGURED) == 0) {
2830 xf86Msg(X_WARNING, "%s: Don't know how to use device\n",
2839 EvdevMultitouchSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
2841 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
2843 if (num_calibration == 0) {
2844 pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_CALIBRATED;
2845 pEvdevMultitouch->calibration.min_x = 0;
2846 pEvdevMultitouch->calibration.max_x = 0;
2847 pEvdevMultitouch->calibration.min_y = 0;
2848 pEvdevMultitouch->calibration.max_y = 0;
2849 } else if (num_calibration == 4) {
2850 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_CALIBRATED;
2851 pEvdevMultitouch->calibration.min_x = calibration[0];
2852 pEvdevMultitouch->calibration.max_x = calibration[1];
2853 pEvdevMultitouch->calibration.min_y = calibration[2];
2854 pEvdevMultitouch->calibration.max_y = calibration[3];
2859 EvdevMultitouchSetResolution(InputInfoPtr pInfo, int num_resolution, int resolution[4])
2861 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
2863 if (num_resolution == 0) {
2864 pEvdevMultitouch->flags &= ~EVDEVMULTITOUCH_RESOLUTION;
2865 pEvdevMultitouch->resolution.min_x = 0;
2866 pEvdevMultitouch->resolution.max_x = 0;
2867 pEvdevMultitouch->resolution.min_y = 0;
2868 pEvdevMultitouch->resolution.max_y = 0;
2869 } else if (num_resolution == 4) {
2870 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_RESOLUTION;
2871 pEvdevMultitouch->resolution.min_x = resolution[0];
2872 pEvdevMultitouch->resolution.max_x = resolution[1];
2873 pEvdevMultitouch->resolution.min_y = resolution[2];
2874 pEvdevMultitouch->resolution.max_y = resolution[3];
2878 static void EvdevMultitouchSetTransform(InputInfoPtr pInfo, int num_transform, float *tmatrix)
2881 struct pixman_transform tr;
2883 if( num_transform != 9 )
2885 use_transform = False;
2888 use_transform = True;
2890 memcpy(transform, tmatrix, sizeof(transform));
2893 tr.matrix[y][x] = pixman_double_to_fixed((double)*tmatrix++);
2895 pixman_transform_invert(&inv_transform, &tr);
2899 EvdevMultitouchSetMultitouch(InputInfoPtr pInfo, int num_multitouch) {
2900 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
2903 if( !(pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH) )
2905 ErrorF("[X11][%s] Device is not a multitouch screen !(flags=%d)\n", __FUNCTION__, pEvdevMultitouch->flags);
2909 if (num_multitouch > MAX_VALUATORS_MT)
2910 num_multitouch = MAX_VALUATORS_MT;
2911 if (num_multitouch < 0)
2914 for (i=0;i<num_multitouch;++i) {
2915 if (pEvdevMultitouch->vals_mt[i].pInfo == NULL){
2916 pEvdevMultitouch->vals_mt[i].containsValues = FALSE;
2917 pEvdevMultitouch->vals_mt[i].id = -1;
2918 pEvdevMultitouch->vals_mt[i].pInfo = EvdevMultitouchCreateSubDevice(pInfo, i);
2921 for (i=num_multitouch;i<MAX_VALUATORS_MT;++i) {
2922 pEvdevMultitouch->vals_mt[i].containsValues = FALSE;
2923 pEvdevMultitouch->vals_mt[i].id = -1;
2924 if (pEvdevMultitouch->vals_mt[i].pInfo && pEvdevMultitouch->vals_mt[i].pInfo != pInfo) {
2925 EvdevMultitouchDeleteSubDevice(pInfo, pEvdevMultitouch->vals_mt[i].pInfo);
2926 pEvdevMultitouch->vals_mt[i].pInfo = NULL;
2930 pEvdevMultitouch->num_multitouch = num_multitouch;
2932 rc = XIChangeDeviceProperty(pInfo->dev, prop_multitouch, XA_INTEGER, 8,
2933 PropModeReplace, 1, &pEvdevMultitouch->num_multitouch, FALSE);
2936 ErrorF("[X11][%s] Failed to Change device property !\n", __FUNCTION__);
2940 EvdevMultitouchSetUsePoll(InputInfoPtr pInfo, BOOL use_poll)
2942 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
2944 if( use_poll == TRUE )
2946 if( !EvdevMultitouchIsCoreDevice(pInfo) )//master only
2949 if( !vsync_input_table)
2951 vsync_input_table = vsync_input_init();
2952 if( !vsync_input_table )
2954 ErrorF("[SetUsePoll] Failed to init vsync input ...\n");
2959 g_syspoll_fd = open(SYSFS_POLL, O_WRONLY);
2960 if( g_syspoll_fd < 0 )
2963 ErrorF("[SetUsePoll] Failed to open %s ...\n", SYSFS_POLL);
2967 vsync_input_table->sync = sync_poll;
2968 vsync_input_table->stop_sync(vsync_input_table->sync_arg);
2969 poll_control(POLL_ENABLE);
2970 pEvdevMultitouch->use_poll = use_poll;
2972 else if( use_poll == FALSE )
2974 if( !EvdevMultitouchIsCoreDevice(pInfo) )//master only
2977 if( !vsync_input_table)
2980 vsync_input_table->stop_sync(vsync_input_table->sync_arg);
2981 vsync_input_table->sync = NULL;
2982 vsync_input_close(vsync_input_table);
2983 vsync_input_table = NULL;
2984 poll_control(POLL_DISABLE);
2985 close(g_syspoll_fd);
2987 pEvdevMultitouch->use_poll = use_poll;
2990 ErrorF("\n[SetUsePoll] Unknown value for use_poll (%d)\n", use_poll);
2997 IsMaster(DeviceIntPtr dev)
2999 return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
3003 GetPairedDevice(DeviceIntPtr dev)
3005 if (!IsMaster(dev) && dev->u.master)
3006 dev = dev->u.master;
3008 return dev->spriteInfo->paired;
3012 GetMaster(DeviceIntPtr dev, int which)
3014 DeviceIntPtr master;
3019 master = dev->u.master;
3023 if (which == MASTER_KEYBOARD)
3025 if (master->type != MASTER_KEYBOARD)
3026 master = GetPairedDevice(master);
3029 if (master->type != MASTER_POINTER)
3030 master = GetPairedDevice(master);
3038 EvdevMultitouchGetGrabInfo(InputInfoPtr pInfo, BOOL val)
3040 DeviceIntPtr master_pointer;
3044 if( pInfo->dev->deviceGrab.grab )
3046 ErrorF("[X11][EvdevMultitouchGetGrabInfo] Device id=%d (grabbed) !\n", pInfo->dev->id);
3047 ErrorF("[X11][EvdevMultitouchGetGrabInfo] (event) type=%d\n", pInfo->dev->deviceGrab.grab->type);
3048 ErrorF("[X11][EvdevMultitouchGetGrabInfo] grabtype=%d\n", pInfo->dev->deviceGrab.grab->grabtype);
3049 ErrorF("[X11][EvdevMultitouchGetGrabInfo] resource=0x%x\n", (unsigned int)pInfo->dev->deviceGrab.grab->resource);
3050 ErrorF("[X11][EvdevMultitouchGetGrabInfo] keyboardMode=%d\n", pInfo->dev->deviceGrab.grab->keyboardMode);
3051 ErrorF("[X11][EvdevMultitouchGetGrabInfo] pointerMode=%d\n", pInfo->dev->deviceGrab.grab->pointerMode);
3052 ErrorF("[X11][EvdevMultitouchGetGrabInfo] sync.frozen=%d\n", pInfo->dev->deviceGrab.sync.frozen);
3053 ErrorF("[X11][EvdevMultitouchGetGrabInfo] fromPassiveGrab=%d\n", pInfo->dev->deviceGrab.fromPassiveGrab);
3054 ErrorF("[X11][EvdevMultitouchGetGrabInfo] implicitGrab=%d\n", pInfo->dev->deviceGrab.implicitGrab);
3056 else if( (master_pointer = GetMaster(pInfo->dev, MASTER_POINTER)) && master_pointer->deviceGrab.grab )
3058 ErrorF("[X11][EvdevMultitouchGetGrabInfo] Device id=%d (master_pointer, grabbed) !\n", master_pointer->id);
3059 ErrorF("[X11][EvdevMultitouchGetGrabInfo] (event) type=%d\n", master_pointer->deviceGrab.grab->type);
3060 ErrorF("[X11][EvdevMultitouchGetGrabInfo] grabtype=%d\n", master_pointer->deviceGrab.grab->grabtype);
3061 ErrorF("[X11][EvdevMultitouchGetGrabInfo] resource=0x%x\n", (unsigned int)master_pointer->deviceGrab.grab->resource);
3062 ErrorF("[X11][EvdevMultitouchGetGrabInfo] keyboardMode=%d\n", master_pointer->deviceGrab.grab->keyboardMode);
3063 ErrorF("[X11][EvdevMultitouchGetGrabInfo] pointerMode=%d\n", master_pointer->deviceGrab.grab->pointerMode);
3064 ErrorF("[X11][EvdevMultitouchGetGrabInfo] sync.frozen=%d\n", master_pointer->deviceGrab.sync.frozen);
3065 ErrorF("[X11][EvdevMultitouchGetGrabInfo] fromPassiveGrab=%d\n", master_pointer->deviceGrab.fromPassiveGrab);
3066 ErrorF("[X11][EvdevMultitouchGetGrabInfo] implicitGrab=%d\n", master_pointer->deviceGrab.implicitGrab);
3069 ErrorF("[X11][EvdevMultitouchGetGrabInfo] Device id=%d (ungrabbed) !\n", pInfo->dev->id);
3074 EvdevMultitouchPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
3077 const char *device, *str;
3078 int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
3079 int num_resolution = 0, resolution[4] = { 0, 0, 0, 0 };
3080 int num_transform = 0; float tr[9];
3081 EvdevMultitouchPtr pEvdevMultitouch;
3084 if (!(pInfo = xf86AllocateInput(drv, 0)))
3087 /* Initialise the InputInfoRec. */
3088 pInfo->name = dev->identifier;
3090 pInfo->type_name = "UNKNOWN";
3091 pInfo->device_control = EvdevMultitouchProc;
3092 pInfo->history_size = 0;
3093 pInfo->control_proc = NULL;
3094 pInfo->close_proc = NULL;
3095 pInfo->switch_mode = NULL;
3096 pInfo->conversion_proc = NULL;
3097 pInfo->reverse_conversion_proc = NULL;
3099 pInfo->private_flags = 0;
3100 pInfo->always_core_feedback = NULL;
3101 pInfo->conf_idev = dev;
3103 if (!(pEvdevMultitouch = calloc(sizeof(EvdevMultitouchRec), 1)))
3106 pInfo->private = pEvdevMultitouch;
3108 xf86CollectInputOptions(pInfo, evdevmultitouchDefaults, NULL);
3109 xf86ProcessCommonOptions(pInfo, pInfo->options);
3110 pEvdevMultitouch->id = -1;
3113 /* If Type == Object, this is a device for an object to use */
3114 type = xf86CheckStrOption(dev->commonOptions, "Type", NULL);
3116 xf86Msg(X_INFO, "%s: EvdevMultitouch Type %s found\n", dev->identifier,type);
3118 if (type != NULL && strcmp(type, "Object") == 0) {
3119 EvdevMultitouchPtr pCreatorEvdevMultitouch;
3123 pCreatorEvdevMultitouch = pCreatorInfo->private;
3124 xf86Msg(X_INFO, "%s: EvdevMultitouch subdevice found\n", dev->identifier);
3125 memcpy(pEvdevMultitouch, pCreatorEvdevMultitouch, sizeof(EvdevMultitouchRec));
3126 pInfo->read_input = EvdevMultitouchSubdevReadInput;
3127 pInfo->flags |= XI86_CONFIGURED;
3128 pEvdevMultitouch->associated = FALSE;
3129 pInfo->type_name = pCreatorInfo->type_name;
3130 pEvdevMultitouch->num_multitouch = 1;
3131 //EvdevMultitouchInitButtonMapping(pInfo);
3133 pInfo->read_input = EvdevMultitouchReadInput;
3135 pEvdevMultitouch->core_device = pInfo;
3136 pEvdevMultitouch->associated = FALSE;
3138 memset(pEvdevMultitouch->vals, 0, MAX_VALUATORS * sizeof(int));
3139 memset(pEvdevMultitouch->old_vals, -1, MAX_VALUATORS * sizeof(int));
3142 * We initialize pEvdevMultitouch->tool to 1 so that device that doesn't use
3143 * proximity will still report events.
3145 pEvdevMultitouch->tool = 1;
3147 device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
3149 xf86Msg(X_ERROR, "%s: No device specified.\n", pInfo->name);
3150 xf86DeleteInput(pInfo, 0);
3154 pEvdevMultitouch->device = device;
3156 xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
3158 pInfo->fd = open(device, O_RDWR | O_NONBLOCK, 0);
3159 } while (pInfo->fd < 0 && errno == EINTR);
3161 if (pInfo->fd < 0) {
3162 xf86Msg(X_ERROR, "Unable to open evdevmultitouch device \"%s\".\n", device);
3163 xf86DeleteInput(pInfo, 0);
3167 /* Check major/minor of device node to avoid adding duplicate devices. */
3168 pEvdevMultitouch->min_maj = EvdevMultitouchGetMajorMinor(pInfo);
3169 if (EvdevMultitouchIsDuplicate(pInfo))
3171 xf86Msg(X_WARNING, "%s: device file already in use. Ignoring.\n",
3174 xf86DeleteInput(pInfo, 0);
3178 pEvdevMultitouch->reopen_attempts = xf86SetIntOption(pInfo->options, "ReopenAttempts", 10);
3179 pEvdevMultitouch->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
3180 pEvdevMultitouch->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
3181 pEvdevMultitouch->num_multitouch = xf86SetIntOption(pInfo->options, "MultiTouch", 0);
3182 pEvdevMultitouch->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
3183 pEvdevMultitouch->use_poll = xf86SetBoolOption(pInfo->options, "UsePoll", FALSE);
3185 str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
3187 num_calibration = sscanf(str, "%d %d %d %d",
3188 &calibration[0], &calibration[1],
3189 &calibration[2], &calibration[3]);
3190 if (num_calibration == 4)
3191 EvdevMultitouchSetCalibration(pInfo, num_calibration, calibration);
3194 "%s: Insufficient calibration factors (%d). Ignoring calibration\n",
3195 pInfo->name, num_calibration);
3198 str = xf86CheckStrOption(pInfo->options, "Resolution", NULL);
3200 num_resolution = sscanf(str, "%d %d %d %d",
3201 &resolution[0], &resolution[1],
3202 &resolution[2], &resolution[3]);
3203 if (num_resolution == 4)
3204 EvdevMultitouchSetResolution(pInfo, num_resolution, resolution);
3207 "%s: Insufficient resolution factors (%d). Ignoring resolution\n",
3208 pInfo->name, num_resolution);
3211 use_transform = False;
3212 str = xf86CheckStrOption(pInfo->options, "Transform", NULL);
3214 num_transform = sscanf(str, "%f %f %f %f %f %f %f %f %f",
3215 &tr[0], &tr[1], &tr[2],
3216 &tr[3], &tr[4], &tr[5],
3217 &tr[6], &tr[7], &tr[8]);
3218 if (num_transform == 9)
3219 EvdevMultitouchSetTransform(pInfo, num_transform, tr);
3223 "%s: Insufficient transform factors (%d). Ignoring transform\n",
3224 pInfo->name, num_transform);
3228 /* Grabbing the event device stops in-kernel event forwarding. In other
3229 words, it disables rfkill and the "Macintosh mouse button emulation".
3230 Note that this needs a server that sets the console to RAW mode. */
3231 pEvdevMultitouch->grabDevice = xf86CheckBoolOption(dev->commonOptions, "GrabDevice", 0);
3233 /* Get setting for checking wether a point is still alive */
3234 pEvdevMultitouch->timeout = xf86CheckIntOption(dev->commonOptions,
3235 "SubdevTimeout", DEFAULT_TIMEOUT);
3236 if (pEvdevMultitouch->timeout < 1) {
3237 pEvdevMultitouch->timeout = 1;
3239 xf86Msg(X_INFO, "%s: SubdevTimeout set to %d\n",
3240 dev->identifier, (int)pEvdevMultitouch->timeout);
3242 EvdevMultitouchInitButtonMapping(pInfo);
3244 if (EvdevMultitouchCacheCompare(pInfo, FALSE) ||
3245 EvdevMultitouchProbe(pInfo)) {
3247 xf86DeleteInput(pInfo, 0);
3251 if ((pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH) && !pEvdevMultitouch->num_buttons) {
3252 /* absolute multitouch screen :
3253 * forcing num_buttons = 1
3255 pEvdevMultitouch->num_buttons = 1;
3256 pEvdevMultitouch->flags |= EVDEVMULTITOUCH_BUTTON_EVENTS;
3259 if(pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH)
3261 pEvdevMultitouch->num_multitouch = 1;
3262 pEvdevMultitouch->vals_mt[0].pInfo = pInfo;
3265 if(pEvdevMultitouch->flags & EVDEVMULTITOUCH_RESOLUTION)
3267 EvdevMultitouchSwapAxes(pEvdevMultitouch);
3269 #ifdef _F_IGNORE_TSP_RESOLUTION_
3272 pEvdevMultitouch->absinfo[ABS_X].maximum = 0;
3273 pEvdevMultitouch->absinfo[ABS_X].minimum = 0;
3274 pEvdevMultitouch->absinfo[ABS_Y].maximum = 0;
3275 pEvdevMultitouch->absinfo[ABS_Y].minimum = 0;
3277 #endif//_F_IGNORE_TSP_RESOLUTION_
3279 // register only the core device
3280 EvdevMultitouchAddDevice(pInfo);
3283 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_BUTTON_EVENTS)
3285 EvdevMultitouchMBEmuPreInit(pInfo);
3286 EvdevMultitouchWheelEmuPreInit(pInfo);
3287 EvdevMultitouchDragLockPreInit(pInfo);
3293 _X_EXPORT InputDriverRec EVDEVMULTITOUCHh = {
3297 EvdevMultitouchPreInit,
3304 EvdevMultitouchUnplug(pointer p)
3309 EvdevMultitouchPlug(pointer module,
3314 xf86AddInputDriver(&EVDEVMULTITOUCHh, module, 0);
3318 static XF86ModuleVersionInfo EvdevMultitouchVersionRec =
3324 XORG_VERSION_CURRENT,
3325 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
3332 _X_EXPORT XF86ModuleData evdevmultitouchModuleData =
3334 &EvdevMultitouchVersionRec,
3335 EvdevMultitouchPlug,
3336 EvdevMultitouchUnplug
3340 /* Return an index value for a given button event code
3341 * returns 0 on non-button event.
3344 EvdevMultitouchUtilButtonEventToButtonNumber(EvdevMultitouchPtr pEvdevMultitouch, int code)
3346 unsigned int button = 0;
3361 /* Treat BTN_[0-2] as LMR buttons on devices that do not advertise
3362 BTN_LEFT, BTN_MIDDLE, BTN_RIGHT.
3363 Otherwise, treat BTN_[0+n] as button 5+n.
3364 XXX: This causes duplicate mappings for BTN_0 + n and BTN_SIDE + n
3367 button = (TestBit(BTN_LEFT, pEvdevMultitouch->key_bitmask)) ? 8 : 1;
3370 button = (TestBit(BTN_MIDDLE, pEvdevMultitouch->key_bitmask)) ? 9 : 2;
3373 button = (TestBit(BTN_RIGHT, pEvdevMultitouch->key_bitmask)) ? 10 : 3;
3376 /* FIXME: BTN_3.. and BTN_SIDE.. have the same button mapping */
3384 button = (code - BTN_0 + 5);
3392 button = (code - BTN_LEFT + 5);
3396 if ((code > BTN_TASK) && (code < KEY_OK)) {
3397 if (code < BTN_JOYSTICK) {
3398 if (code < BTN_MOUSE)
3399 button = (code - BTN_0 + 5);
3401 button = (code - BTN_LEFT + 5);
3406 if (button > EVDEVMULTITOUCH_MAXBUTTONS)
3412 #ifdef HAVE_PROPERTIES
3414 /* Aligned with linux/input.h.
3415 Note that there are holes in the ABS_ range, these are simply replaced with
3417 static char* abs_labels[] = {
3418 AXIS_LABEL_PROP_ABS_X, /* 0x00 */
3419 AXIS_LABEL_PROP_ABS_Y, /* 0x01 */
3420 AXIS_LABEL_PROP_ABS_Z, /* 0x02 */
3421 AXIS_LABEL_PROP_ABS_RX, /* 0x03 */
3422 AXIS_LABEL_PROP_ABS_RY, /* 0x04 */
3423 AXIS_LABEL_PROP_ABS_RZ, /* 0x05 */
3424 AXIS_LABEL_PROP_ABS_THROTTLE, /* 0x06 */
3425 AXIS_LABEL_PROP_ABS_RUDDER, /* 0x07 */
3426 AXIS_LABEL_PROP_ABS_WHEEL, /* 0x08 */
3427 AXIS_LABEL_PROP_ABS_GAS, /* 0x09 */
3428 AXIS_LABEL_PROP_ABS_BRAKE, /* 0x0a */
3429 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3430 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3431 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3432 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3433 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3434 AXIS_LABEL_PROP_ABS_HAT0X, /* 0x10 */
3435 AXIS_LABEL_PROP_ABS_HAT0Y, /* 0x11 */
3436 AXIS_LABEL_PROP_ABS_HAT1X, /* 0x12 */
3437 AXIS_LABEL_PROP_ABS_HAT1Y, /* 0x13 */
3438 AXIS_LABEL_PROP_ABS_HAT2X, /* 0x14 */
3439 AXIS_LABEL_PROP_ABS_HAT2Y, /* 0x15 */
3440 AXIS_LABEL_PROP_ABS_HAT3X, /* 0x16 */
3441 AXIS_LABEL_PROP_ABS_HAT3Y, /* 0x17 */
3442 AXIS_LABEL_PROP_ABS_PRESSURE, /* 0x18 */
3443 AXIS_LABEL_PROP_ABS_DISTANCE, /* 0x19 */
3444 AXIS_LABEL_PROP_ABS_TILT_X, /* 0x1a */
3445 AXIS_LABEL_PROP_ABS_TILT_Y, /* 0x1b */
3446 AXIS_LABEL_PROP_ABS_TOOL_WIDTH, /* 0x1c */
3447 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3448 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3449 AXIS_LABEL_PROP_ABS_MISC, /* undefined */
3450 AXIS_LABEL_PROP_ABS_VOLUME /* 0x20 */
3453 static char* rel_labels[] = {
3454 AXIS_LABEL_PROP_REL_X,
3455 AXIS_LABEL_PROP_REL_Y,
3456 AXIS_LABEL_PROP_REL_Z,
3457 AXIS_LABEL_PROP_REL_RX,
3458 AXIS_LABEL_PROP_REL_RY,
3459 AXIS_LABEL_PROP_REL_RZ,
3460 AXIS_LABEL_PROP_REL_HWHEEL,
3461 AXIS_LABEL_PROP_REL_DIAL,
3462 AXIS_LABEL_PROP_REL_WHEEL,
3463 AXIS_LABEL_PROP_REL_MISC
3466 static char* btn_labels[][16] = {
3467 { /* BTN_MISC group offset 0x100*/
3468 BTN_LABEL_PROP_BTN_0, /* 0x00 */
3469 BTN_LABEL_PROP_BTN_1, /* 0x01 */
3470 BTN_LABEL_PROP_BTN_2, /* 0x02 */
3471 BTN_LABEL_PROP_BTN_3, /* 0x03 */
3472 BTN_LABEL_PROP_BTN_4, /* 0x04 */
3473 BTN_LABEL_PROP_BTN_5, /* 0x05 */
3474 BTN_LABEL_PROP_BTN_6, /* 0x06 */
3475 BTN_LABEL_PROP_BTN_7, /* 0x07 */
3476 BTN_LABEL_PROP_BTN_8, /* 0x08 */
3477 BTN_LABEL_PROP_BTN_9 /* 0x09 */
3479 { /* BTN_MOUSE group offset 0x110 */
3480 BTN_LABEL_PROP_BTN_LEFT, /* 0x00 */
3481 BTN_LABEL_PROP_BTN_RIGHT, /* 0x01 */
3482 BTN_LABEL_PROP_BTN_MIDDLE, /* 0x02 */
3483 BTN_LABEL_PROP_BTN_SIDE, /* 0x03 */
3484 BTN_LABEL_PROP_BTN_EXTRA, /* 0x04 */
3485 BTN_LABEL_PROP_BTN_FORWARD, /* 0x05 */
3486 BTN_LABEL_PROP_BTN_BACK, /* 0x06 */
3487 BTN_LABEL_PROP_BTN_TASK /* 0x07 */
3489 { /* BTN_JOYSTICK group offset 0x120 */
3490 BTN_LABEL_PROP_BTN_TRIGGER, /* 0x00 */
3491 BTN_LABEL_PROP_BTN_THUMB, /* 0x01 */
3492 BTN_LABEL_PROP_BTN_THUMB2, /* 0x02 */
3493 BTN_LABEL_PROP_BTN_TOP, /* 0x03 */
3494 BTN_LABEL_PROP_BTN_TOP2, /* 0x04 */
3495 BTN_LABEL_PROP_BTN_PINKIE, /* 0x05 */
3496 BTN_LABEL_PROP_BTN_BASE, /* 0x06 */
3497 BTN_LABEL_PROP_BTN_BASE2, /* 0x07 */
3498 BTN_LABEL_PROP_BTN_BASE3, /* 0x08 */
3499 BTN_LABEL_PROP_BTN_BASE4, /* 0x09 */
3500 BTN_LABEL_PROP_BTN_BASE5, /* 0x0a */
3501 BTN_LABEL_PROP_BTN_BASE6, /* 0x0b */
3505 BTN_LABEL_PROP_BTN_DEAD /* 0x0f */
3507 { /* BTN_GAMEPAD group offset 0x130 */
3508 BTN_LABEL_PROP_BTN_A, /* 0x00 */
3509 BTN_LABEL_PROP_BTN_B, /* 0x01 */
3510 BTN_LABEL_PROP_BTN_C, /* 0x02 */
3511 BTN_LABEL_PROP_BTN_X, /* 0x03 */
3512 BTN_LABEL_PROP_BTN_Y, /* 0x04 */
3513 BTN_LABEL_PROP_BTN_Z, /* 0x05 */
3514 BTN_LABEL_PROP_BTN_TL, /* 0x06 */
3515 BTN_LABEL_PROP_BTN_TR, /* 0x07 */
3516 BTN_LABEL_PROP_BTN_TL2, /* 0x08 */
3517 BTN_LABEL_PROP_BTN_TR2, /* 0x09 */
3518 BTN_LABEL_PROP_BTN_SELECT, /* 0x0a */
3519 BTN_LABEL_PROP_BTN_START, /* 0x0b */
3520 BTN_LABEL_PROP_BTN_MODE, /* 0x0c */
3521 BTN_LABEL_PROP_BTN_THUMBL, /* 0x0d */
3522 BTN_LABEL_PROP_BTN_THUMBR /* 0x0e */
3524 { /* BTN_DIGI group offset 0x140 */
3525 BTN_LABEL_PROP_BTN_TOOL_PEN, /* 0x00 */
3526 BTN_LABEL_PROP_BTN_TOOL_RUBBER, /* 0x01 */
3527 BTN_LABEL_PROP_BTN_TOOL_BRUSH, /* 0x02 */
3528 BTN_LABEL_PROP_BTN_TOOL_PENCIL, /* 0x03 */
3529 BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH, /* 0x04 */
3530 BTN_LABEL_PROP_BTN_TOOL_FINGER, /* 0x05 */
3531 BTN_LABEL_PROP_BTN_TOOL_MOUSE, /* 0x06 */
3532 BTN_LABEL_PROP_BTN_TOOL_LENS, /* 0x07 */
3535 BTN_LABEL_PROP_BTN_TOUCH, /* 0x0a */
3536 BTN_LABEL_PROP_BTN_STYLUS, /* 0x0b */
3537 BTN_LABEL_PROP_BTN_STYLUS2, /* 0x0c */
3538 BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP, /* 0x0d */
3539 BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP /* 0x0e */
3541 { /* BTN_WHEEL group offset 0x150 */
3542 BTN_LABEL_PROP_BTN_GEAR_DOWN, /* 0x00 */
3543 BTN_LABEL_PROP_BTN_GEAR_UP /* 0x01 */
3547 #endif /* HAVE_LABELS */
3549 static void EvdevMultitouchInitAxesLabels(EvdevMultitouchPtr pEvdevMultitouch, int natoms, Atom *atoms)
3558 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_ABSOLUTE_EVENTS)
3560 labels = abs_labels;
3561 labels_len = ArrayLength(abs_labels);
3562 misc_label = AXIS_LABEL_PROP_ABS_MISC;
3563 } else if ((pEvdevMultitouch->flags & EVDEVMULTITOUCH_RELATIVE_EVENTS))
3565 labels = rel_labels;
3566 labels_len = ArrayLength(rel_labels);
3567 misc_label = AXIS_LABEL_PROP_REL_MISC;
3570 memset(atoms, 0, natoms * sizeof(Atom));
3572 /* Now fill the ones we know */
3573 for (axis = 0; axis < labels_len; axis++)
3575 if (pEvdevMultitouch->axis_map[axis] == -1)
3578 atom = XIGetKnownProperty(labels[axis]);
3579 if (!atom) /* Should not happen */
3582 atoms[pEvdevMultitouch->axis_map[axis]] = atom;
3587 static void EvdevMultitouchInitButtonLabels(EvdevMultitouchPtr pEvdevMultitouch, int natoms, Atom *atoms)
3593 /* First, make sure all atoms are initialized */
3594 atom = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN);
3595 for (button = 0; button < natoms; button++)
3596 atoms[button] = atom;
3598 for (button = BTN_MISC; button < BTN_JOYSTICK; button++)
3600 if (TestBit(button, pEvdevMultitouch->key_bitmask))
3602 int group = (button % 0x100)/16;
3603 int idx = button - ((button/16) * 16);
3605 if (!btn_labels[group][idx])
3608 atom = XIGetKnownProperty(btn_labels[group][idx]);
3612 /* Props are 0-indexed, button numbers start with 1 */
3613 bmap = EvdevMultitouchUtilButtonEventToButtonNumber(pEvdevMultitouch, button) - 1;
3619 /* wheel buttons, hardcoded anyway */
3621 atoms[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
3623 atoms[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
3625 atoms[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
3627 atoms[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
3632 EvdevMultitouchInitProperty(DeviceIntPtr dev)
3634 InputInfoPtr pInfo = dev->public.devicePrivate;
3635 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
3641 prop_reopen = MakeAtom(EVDEVMULTITOUCH_PROP_REOPEN, strlen(EVDEVMULTITOUCH_PROP_REOPEN),
3644 reopen = pEvdevMultitouch->reopen_attempts;
3645 rc = XIChangeDeviceProperty(dev, prop_reopen, XA_INTEGER, 8,
3646 PropModeReplace, 1, &reopen, FALSE);
3650 XISetDevicePropertyDeletable(dev, prop_reopen, FALSE);
3652 if (pEvdevMultitouch->flags & (EVDEVMULTITOUCH_RELATIVE_EVENTS | EVDEVMULTITOUCH_ABSOLUTE_EVENTS))
3654 invert[0] = pEvdevMultitouch->invert_x;
3655 invert[1] = pEvdevMultitouch->invert_y;
3657 prop_invert = MakeAtom(EVDEVMULTITOUCH_PROP_INVERT_AXES, strlen(EVDEVMULTITOUCH_PROP_INVERT_AXES), TRUE);
3659 rc = XIChangeDeviceProperty(dev, prop_invert, XA_INTEGER, 8,
3665 XISetDevicePropertyDeletable(dev, prop_invert, FALSE);
3667 prop_calibration = MakeAtom(EVDEVMULTITOUCH_PROP_CALIBRATION,
3668 strlen(EVDEVMULTITOUCH_PROP_CALIBRATION), TRUE);
3669 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER, 32,
3670 PropModeReplace, 0, NULL, FALSE);
3674 XISetDevicePropertyDeletable(dev, prop_calibration, FALSE);
3676 prop_swap = MakeAtom(EVDEVMULTITOUCH_PROP_SWAP_AXES,
3677 strlen(EVDEVMULTITOUCH_PROP_SWAP_AXES), TRUE);
3679 rc = XIChangeDeviceProperty(dev, prop_swap, XA_INTEGER, 8,
3680 PropModeReplace, 1, &pEvdevMultitouch->swap_axes, FALSE);
3684 XISetDevicePropertyDeletable(dev, prop_swap, FALSE);
3686 if (pEvdevMultitouch->flags & EVDEVMULTITOUCH_MULTITOUCH)
3688 /* tracking ids for mt */
3689 prop_tracking_id = MakeAtom(EVDEVMULTITOUCH_PROP_TRACKING_ID,
3690 strlen(EVDEVMULTITOUCH_PROP_TRACKING_ID), TRUE);
3691 rc = XIChangeDeviceProperty(dev, prop_tracking_id, XA_INTEGER, 32,
3692 PropModeReplace, 1, &pEvdevMultitouch->id, FALSE);
3696 XISetDevicePropertyDeletable(dev, prop_tracking_id, FALSE);
3698 /* flag to emulate or not a touchscreen for mt */
3699 prop_multitouch = MakeAtom(EVDEVMULTITOUCH_PROP_MULTITOUCH_SUBDEVICES,
3700 strlen(EVDEVMULTITOUCH_PROP_MULTITOUCH_SUBDEVICES), TRUE);
3701 rc = XIChangeDeviceProperty(dev, prop_multitouch, XA_INTEGER, 8,
3702 PropModeReplace, 1, &pEvdevMultitouch->num_multitouch, FALSE);
3706 XISetDevicePropertyDeletable(dev, prop_multitouch, FALSE);
3709 //property for checking pointer grab status
3711 prop_grabinfo = MakeAtom(EVDEVMULTITOUCH_PROP_GRABINFO, strlen(EVDEVMULTITOUCH_PROP_GRABINFO), TRUE);
3712 rc = XIChangeDeviceProperty(dev, prop_grabinfo, XA_INTEGER, 8, PropModeReplace, 1, &val, FALSE);
3717 XISetDevicePropertyDeletable(dev, prop_grabinfo, FALSE);
3719 if( EvdevMultitouchIsCoreDevice(pInfo) )//master only
3721 /* flag to use poll */
3722 prop_use_poll = MakeAtom(EVDEVMULTITOUCH_PROP_USE_POLL, strlen(EVDEVMULTITOUCH_PROP_USE_POLL), TRUE);
3723 rc = XIChangeDeviceProperty(dev, prop_use_poll, XA_INTEGER, 8, PropModeReplace, 1, &pEvdevMultitouch->use_poll, FALSE);
3727 XISetDevicePropertyDeletable(dev, prop_use_poll, FALSE);
3729 /* matrix to transform */
3730 prop_transform = MakeAtom(EVDEVMULTITOUCH_PROP_TRANSFORM, strlen(EVDEVMULTITOUCH_PROP_TRANSFORM), TRUE);
3731 rc = XIChangeDeviceProperty(dev, prop_transform, XIGetKnownProperty(XATOM_FLOAT), 32, PropModeReplace, 9, transform, FALSE);
3736 XISetDevicePropertyDeletable(dev, prop_transform, FALSE);
3740 /* Axis labelling */
3741 if ((pEvdevMultitouch->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
3743 Atom atoms[pEvdevMultitouch->num_vals];
3744 EvdevMultitouchInitAxesLabels(pEvdevMultitouch, pEvdevMultitouch->num_vals, atoms);
3745 XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32,
3746 PropModeReplace, pEvdevMultitouch->num_vals, atoms, FALSE);
3747 XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE);
3749 /* Button labelling */
3750 if ((pEvdevMultitouch->num_buttons > 0) && (prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP)))
3752 Atom atoms[EVDEVMULTITOUCH_MAXBUTTONS];
3753 EvdevMultitouchInitButtonLabels(pEvdevMultitouch, EVDEVMULTITOUCH_MAXBUTTONS, atoms);
3754 XIChangeDeviceProperty(dev, prop_btn_label, XA_ATOM, 32,
3755 PropModeReplace, pEvdevMultitouch->num_buttons, atoms, FALSE);
3756 XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE);
3758 #endif /* HAVE_LABELS */
3763 static void EvdevMultitouchSwapAxes(EvdevMultitouchPtr pEvdevMultitouch)
3765 if(pEvdevMultitouch->swap_axes)
3767 pEvdevMultitouch->absinfo[ABS_Y].maximum = pEvdevMultitouch->resolution.max_x;
3768 pEvdevMultitouch->absinfo[ABS_Y].minimum = pEvdevMultitouch->resolution.min_x;
3769 pEvdevMultitouch->absinfo[ABS_X].maximum = pEvdevMultitouch->resolution.max_y;
3770 pEvdevMultitouch->absinfo[ABS_X].minimum = pEvdevMultitouch->resolution.min_y;
3774 pEvdevMultitouch->absinfo[ABS_X].maximum = pEvdevMultitouch->resolution.max_x;
3775 pEvdevMultitouch->absinfo[ABS_X].minimum = pEvdevMultitouch->resolution.min_x;
3776 pEvdevMultitouch->absinfo[ABS_Y].maximum = pEvdevMultitouch->resolution.max_y;
3777 pEvdevMultitouch->absinfo[ABS_Y].minimum = pEvdevMultitouch->resolution.min_y;
3782 EvdevMultitouchSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
3785 InputInfoPtr pInfo = dev->public.devicePrivate;
3786 EvdevMultitouchPtr pEvdevMultitouch = pInfo->private;
3788 if (atom == prop_invert)
3791 if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
3796 data = (BOOL*)val->data;
3797 pEvdevMultitouch->invert_x = data[0];
3798 pEvdevMultitouch->invert_y = data[1];
3800 } else if (atom == prop_reopen)
3802 if (val->format != 8 || val->size != 1 || val->type != XA_INTEGER)
3806 pEvdevMultitouch->reopen_attempts = *((CARD8*)val->data);
3807 } else if (atom == prop_calibration)
3809 if (val->format != 32 || val->type != XA_INTEGER)
3811 if (val->size != 4 && val->size != 0)
3815 EvdevMultitouchSetCalibration(pInfo, val->size, val->data);
3816 } else if (atom == prop_swap)
3818 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
3822 pEvdevMultitouch->swap_axes = *((BOOL*)val->data);
3823 EvdevMultitouchSwapAxes(pEvdevMultitouch);
3824 } else if (atom == prop_axis_label || atom == prop_btn_label)
3825 return BadAccess; /* Axis/Button labels can't be changed */
3826 else if (atom == prop_tracking_id)
3828 if (val->format != 32 || val->type != XA_INTEGER || val->size != 1)
3832 pEvdevMultitouch->id = *((int*)val->data);
3833 } else if (atom == prop_multitouch)
3836 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
3839 data = *((BOOL*)val->data);
3840 if (pEvdevMultitouch->num_multitouch != data)
3841 EvdevMultitouchSetMultitouch(pInfo,data);
3843 } else if (atom == prop_use_poll)
3846 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
3849 data = *((BOOL*)val->data);
3850 if (pEvdevMultitouch->use_poll != data)
3851 EvdevMultitouchSetUsePoll(pInfo,(BOOL)data);
3854 else if (atom == prop_transform)
3857 if (val->format != 32 || val->type != XIGetKnownProperty(XATOM_FLOAT) || val->size != 9)
3860 f = (float*)val->data;
3861 EvdevMultitouchSetTransform(pInfo, val->size, f);
3864 else if (atom == prop_grabinfo)
3867 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
3870 data = *((BOOL*)val->data);
3871 EvdevMultitouchGetGrabInfo(pInfo, (BOOL)data);
3879 /* Duplicate xf86 options and convert them to InputOption */
3880 static InputOption *EvdevMultitouchOptionDupConvert(pointer original)
3882 InputOption *iopts = NULL, *new;
3886 memset(&dummy, 0, sizeof(dummy));
3887 xf86CollectInputOptions(&dummy, NULL, original);
3889 while(dummy.options)
3891 new = calloc(1, sizeof(InputOption));
3893 new->key = xf86OptionName(dummy.options);
3894 new->value = xf86OptionValue(dummy.options);
3898 dummy.options = xf86NextOption(dummy.options);
3902 static void EvdevMultitouchFreeInputOpts(InputOption* opts)
3904 InputOption *tmp = opts;
3915 static void EvdevMultitouchReplaceOption(InputOption *opts,const char* key, char * value)
3920 if (xf86NameCmp(opts->key, key) == 0)
3924 opts->value = strdup(value);
3931 * New device creation through xorg/input
3933 * @return 0 if successful, 1 if failure
3936 EvdevMultitouchCreateSubDevice(InputInfoPtr pInfo, int id) {
3937 InputInfoPtr pSubdev;
3939 DeviceIntPtr dev; /* dummy */
3940 InputOption *input_options = NULL;
3944 pInfo->options = xf86AddNewOption(pInfo->options, "Type", "core");
3945 pInfo->options = xf86AddNewOption(pInfo->options, "SendCoreEvents", "off");
3947 /* Create new device */
3949 input_options = EvdevMultitouchOptionDupConvert(pInfo->options);
3951 EvdevMultitouchReplaceOption(input_options, "type","Object");
3953 //EvdevMultitouchReplaceOption(input_options, "SendCoreEvents","off"); //FIXME: bug in xserver
3954 name = malloc( (strlen(pInfo->name) + strlen(" subdev ") + 20 )*sizeof(char)); // 20 for adding the id
3958 ErrorF("[X11][%s] Failed to allocate memory !\n", __FUNCTION__);
3962 sprintf(name, "%s subdev %i", pInfo->name, id);
3963 EvdevMultitouchReplaceOption(input_options, "name",name);
3965 pCreatorInfo = pInfo;
3966 NewInputDeviceRequest(input_options, NULL, &dev);//for xserver 1.8.0
3967 //NewInputDeviceRequest(input_options, &dev);//for xserver 1.7.1
3968 pSubdev = dev->public.devicePrivate;
3969 pCreatorInfo = NULL;
3971 EvdevMultitouchFreeInputOpts(input_options);
3977 EvdevMultitouchDeleteSubDevice(InputInfoPtr pInfo, InputInfoPtr subdev) {
3978 /* We need to explicitely flush the events so as not deleting
3979 * a device that still has events in queue
3981 xf86Msg(X_INFO, "%s: Removing subdevice %s\n", pInfo->name,subdev->name);
3982 DeleteInputDeviceRequest(subdev->dev);