1 /*
2 * Copyright © 2004-2008 Red Hat, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of Red Hat
9 * not be used in advertising or publicity pertaining to distribution
10 * of the software without specific, written prior permission. Red
11 * Hat makes no representations about the suitability of this software
12 * for any purpose. It is provided "as is" without express or implied
13 * warranty.
14 *
15 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authors:
24 * Kristian Høgsberg (krh@redhat.com)
25 * Adam Jackson (ajax@redhat.com)
26 * Peter Hutterer (peter.hutterer@redhat.com)
27 * Oliver McFadden (oliver.mcfadden@nokia.com)
28 * Thomas H.P. Andersen (phomes@gmail.com)
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "evdev.h"
36 #include "axis_labels.h"
37
38 #include <X11/keysym.h>
39 #include <X11/extensions/XI.h>
40
41 #ifdef __linux__
42 #include <linux/version.h>
43 #endif
44 #include <sys/stat.h>
45 #ifdef HAVE_LIBUDEV
46 #include <libudev.h>
47 #endif
48 #include <unistd.h>
49 #include <errno.h>
50 #include <fcntl.h>
51
52 #include <xf86.h>
53 #include <xf86Xinput.h>
54 #include <exevents.h>
55 #include <xorgVersion.h>
56 #include <xkbsrv.h>
57
58 #include <X11/Xatom.h>
59 #include <evdev-properties.h>
60 #include <xserver-properties.h>
61 #include <mtdev-plumbing.h>
62
63 #ifndef XI_PROP_PRODUCT_ID
64 #define XI_PROP_PRODUCT_ID "Device Product ID"
65 #endif
66
67 #ifndef XI_PROP_VIRTUAL_DEVICE
68 #define XI_PROP_VIRTUAL_DEVICE "Virtual Device"
69 #endif
70
71 /* removed from server, purge when dropping support for server 1.10 */
72 #define XI86_SEND_DRAG_EVENTS 0x08
73
74 #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
75
76 #define MIN_KEYCODE 8
77
78 #define CAPSFLAG 1
79 #define NUMFLAG 2
80 #define SCROLLFLAG 4
81 #define MODEFLAG 8
82 #define COMPOSEFLAG 16
83
84 #ifndef ABS_MT_SLOT
85 #define ABS_MT_SLOT 0x2f
86 #endif
87
88 #ifndef ABS_MT_TRACKING_ID
89 #define ABS_MT_TRACKING_ID 0x39
90 #endif
91
92 #ifndef XI86_SERVER_FD
93 #define XI86_SERVER_FD 0x20
94 #endif
95
96 /* Any of those triggers a proximity event */
97 static int proximity_bits[] = {
98 BTN_TOOL_PEN,
99 BTN_TOOL_RUBBER,
100 BTN_TOOL_BRUSH,
101 BTN_TOOL_PENCIL,
102 BTN_TOOL_AIRBRUSH,
103 BTN_TOOL_FINGER,
104 BTN_TOOL_MOUSE,
105 BTN_TOOL_LENS,
106 };
107
108 static int EvdevOn(DeviceIntPtr);
109 static int EvdevCache(InputInfoPtr pInfo);
110 static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
111 static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode);
112 static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab);
113 static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
114 static int EvdevOpenDevice(InputInfoPtr pInfo);
115 static void EvdevCloseDevice(InputInfoPtr pInfo);
116
117 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int mode, int natoms, Atom *atoms);
118 static void EvdevInitOneAxisLabel(EvdevPtr pEvdev, int mapped_axis,
119 const char **labels, int label_idx, Atom *atoms);
120 static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
121 static void EvdevInitProperty(DeviceIntPtr dev);
122 static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
123 XIPropertyValuePtr val, BOOL checkonly);
124 static Atom prop_product_id;
125 static Atom prop_invert;
126 static Atom prop_calibration;
127 static Atom prop_swap;
128 static Atom prop_axis_label;
129 static Atom prop_btn_label;
130 static Atom prop_device;
131 static Atom prop_virtual;
132 static Atom prop_scroll_dist;
133
EvdevSwitchMode(ClientPtr client,DeviceIntPtr device,int mode)134 static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode)
135 {
136 InputInfoPtr pInfo;
137 EvdevPtr pEvdev;
138 int val;
139
140 pInfo = device->public.devicePrivate;
141 pEvdev = pInfo->private;
142
143 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
144 {
145 if (mode == Relative)
146 return Success;
147 else
148 return XI_BadMode;
149 }
150
151 switch (mode) {
152 case Absolute:
153 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
154 if (valuator_mask_fetch(pEvdev->old_vals, 0, &val))
155 valuator_mask_set(pEvdev->abs_vals, 0, val);
156 if (valuator_mask_fetch(pEvdev->old_vals, 1, &val))
157 valuator_mask_set(pEvdev->abs_vals, 1, val);
158 valuator_mask_zero(pEvdev->old_vals);
159 break;
160
161 case Relative:
162 pEvdev->flags |= EVDEV_RELATIVE_MODE;
163 if (valuator_mask_fetch(pEvdev->abs_vals, 0, &val))
164 valuator_mask_set(pEvdev->old_vals, 0, val);
165 if (valuator_mask_fetch(pEvdev->abs_vals, 1, &val))
166 valuator_mask_set(pEvdev->old_vals, 1, val);
167 valuator_mask_unset(pEvdev->abs_vals, 0);
168 valuator_mask_unset(pEvdev->abs_vals, 1);
169 break;
170
171 default:
172 return XI_BadMode;
173 }
174
175 return Success;
176 }
177
EvdevBitIsSet(const unsigned long * array,int bit)178 static inline int EvdevBitIsSet(const unsigned long *array, int bit)
179 {
180 return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
181 }
182
EvdevSetBit(unsigned long * array,int bit)183 static inline void EvdevSetBit(unsigned long *array, int bit)
184 {
185 array[bit / LONG_BITS] |= (1LL << (bit % LONG_BITS));
186 }
187
188 static int
EvdevGetMajorMinor(InputInfoPtr pInfo)189 EvdevGetMajorMinor(InputInfoPtr pInfo)
190 {
191 struct stat st;
192
193 if (fstat(pInfo->fd, &st) == -1)
194 {
195 xf86IDrvMsg(pInfo, X_ERROR, "stat failed (%s). cannot check for duplicates.\n",
196 strerror(errno));
197 return 0;
198 }
199
200 return st.st_rdev;
201 }
202
203 /**
204 * Return TRUE if one of the devices we know about has the same min/maj
205 * number.
206 */
207 static BOOL
EvdevIsDuplicate(InputInfoPtr pInfo)208 EvdevIsDuplicate(InputInfoPtr pInfo)
209 {
210 EvdevPtr pEvdev = pInfo->private;
211 InputInfoPtr d;
212
213 nt_list_for_each_entry(d, xf86FirstLocalDevice(), next)
214 {
215 EvdevPtr e;
216
217 if (strcmp(d->drv->driverName, "evdev") != 0)
218 continue;
219
220 e = (EvdevPtr)d->private;
221 if (e != pEvdev &&
222 e->min_maj &&
223 e->min_maj == pEvdev->min_maj)
224 return TRUE;
225 }
226
227 return FALSE;
228 }
229
230 static BOOL
EvdevDeviceIsVirtual(const char * devicenode)231 EvdevDeviceIsVirtual(const char* devicenode)
232 {
233 #ifdef HAVE_LIBUDEV
234 struct udev *udev = NULL;
235 struct udev_device *device = NULL;
236 struct stat st;
237 int rc = FALSE;
238 const char *devpath;
239
240 udev = udev_new();
241 if (!udev)
242 goto out;
243
244 if (stat(devicenode, &st) == -1)
245 goto out;
246
247 device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
248
249 if (!device)
250 goto out;
251
252
253 devpath = udev_device_get_devpath(device);
254 if (!devpath)
255 goto out;
256
257 if (strstr(devpath, "LNXSYSTM"))
258 rc = TRUE;
259
260 out:
261 udev_device_unref(device);
262 udev_unref(udev);
263 return rc;
264 #else
265 return FALSE;
266 #endif
267 }
268
269
270 static EventQueuePtr
EvdevNextInQueue(InputInfoPtr pInfo)271 EvdevNextInQueue(InputInfoPtr pInfo)
272 {
273 EvdevPtr pEvdev = pInfo->private;
274
275 if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
276 {
277 LogMessageVerbSigSafe(X_WARNING, 0, "dropping event due to full queue!\n");
278 return NULL;
279 }
280
281 pEvdev->num_queue++;
282 return &pEvdev->queue[pEvdev->num_queue - 1];
283 }
284
285 void
EvdevQueueKbdEvent(InputInfoPtr pInfo,struct input_event * ev,int value)286 EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
287 {
288 int code = ev->code + MIN_KEYCODE;
289 EventQueuePtr pQueue;
290
291 /* Filter all repeated events from device.
292 We'll do softrepeat in the server, but only since 1.6 */
293 if (value == 2)
294 return;
295
296 if ((pQueue = EvdevNextInQueue(pInfo)))
297 {
298 pQueue->type = EV_QUEUE_KEY;
299 pQueue->detail.key = code;
300 pQueue->val = value;
301 }
302 }
303
304 void
EvdevQueueButtonEvent(InputInfoPtr pInfo,int button,int value)305 EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
306 {
307 EventQueuePtr pQueue;
308
309 if ((pQueue = EvdevNextInQueue(pInfo)))
310 {
311 pQueue->type = EV_QUEUE_BTN;
312 pQueue->detail.key = button;
313 pQueue->val = value;
314 }
315 }
316
317 void
EvdevQueueProximityEvent(InputInfoPtr pInfo,int value)318 EvdevQueueProximityEvent(InputInfoPtr pInfo, int value)
319 {
320 EventQueuePtr pQueue;
321 if ((pQueue = EvdevNextInQueue(pInfo)))
322 {
323 pQueue->type = EV_QUEUE_PROXIMITY;
324 pQueue->detail.key = 0;
325 pQueue->val = value;
326 }
327 }
328
329 void
EvdevQueueTouchEvent(InputInfoPtr pInfo,unsigned int touch,ValuatorMask * mask,uint16_t evtype)330 EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask,
331 uint16_t evtype)
332 {
333 EventQueuePtr pQueue;
334 if ((pQueue = EvdevNextInQueue(pInfo)))
335 {
336 pQueue->type = EV_QUEUE_TOUCH;
337 pQueue->detail.touch = touch;
338 valuator_mask_copy(pQueue->touchMask, mask);
339 pQueue->val = evtype;
340 }
341 }
342
343 /**
344 * Post button event right here, right now.
345 * Interface for MB emulation since these need to post immediately.
346 */
347 void
EvdevPostButtonEvent(InputInfoPtr pInfo,int button,enum ButtonAction act)348 EvdevPostButtonEvent(InputInfoPtr pInfo, int button, enum ButtonAction act)
349 {
350 xf86PostButtonEvent(pInfo->dev, Relative, button,
351 (act == BUTTON_PRESS) ? 1 : 0, 0, 0);
352 }
353
354 void
EvdevQueueButtonClicks(InputInfoPtr pInfo,int button,int count)355 EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
356 {
357 int i;
358
359 for (i = 0; i < count; i++) {
360 EvdevQueueButtonEvent(pInfo, button, 1);
361 EvdevQueueButtonEvent(pInfo, button, 0);
362 }
363 }
364
365 static void
EvdevSwapAbsValuators(EvdevPtr pEvdev,ValuatorMask * mask)366 EvdevSwapAbsValuators(EvdevPtr pEvdev, ValuatorMask *mask)
367 {
368 int i;
369 int swapped_isset[2] = {0, 0};
370 int swapped_values[2];
371
372 if (!pEvdev->swap_axes)
373 return;
374
375 for(i = 0; i <= 1; i++) {
376 if (valuator_mask_isset(mask, i)) {
377 const struct input_absinfo *abs1 =
378 libevdev_get_abs_info(pEvdev->dev, i);
379 const struct input_absinfo *abs2 =
380 libevdev_get_abs_info(pEvdev->dev, 1 - i);
381
382 swapped_isset[1 - i] = 1;
383 swapped_values[1 - i] =
384 xf86ScaleAxis(valuator_mask_get(mask, i),
385 abs2->maximum, abs2->minimum,
386 abs1->maximum, abs1->minimum);
387 }
388 }
389
390 for (i = 0; i <= 1; i++) {
391 if (swapped_isset[i])
392 valuator_mask_set(mask, i, swapped_values[i]);
393 else
394 valuator_mask_unset(mask, i);
395 }
396 }
397
398 static void
EvdevApplyCalibration(EvdevPtr pEvdev,ValuatorMask * mask)399 EvdevApplyCalibration(EvdevPtr pEvdev, ValuatorMask *mask)
400 {
401 int i;
402
403 for (i = 0; i <= 1; i++) {
404 const struct input_absinfo *abs;
405 int val;
406 int calib_min;
407 int calib_max;
408
409 if (!valuator_mask_isset(mask, i))
410 continue;
411
412 val = valuator_mask_get(mask, i);
413 abs = libevdev_get_abs_info(pEvdev->dev, i);
414
415 if (i == 0) {
416 calib_min = pEvdev->calibration.min_x;
417 calib_max = pEvdev->calibration.max_x;
418 } else {
419 calib_min = pEvdev->calibration.min_y;
420 calib_max = pEvdev->calibration.max_y;
421 }
422
423 if (pEvdev->flags & EVDEV_CALIBRATED)
424 val = xf86ScaleAxis(val, abs->maximum, abs->minimum,
425 calib_max, calib_min);
426
427 if ((i == 0 && pEvdev->invert_x) || (i == 1 && pEvdev->invert_y))
428 val = (abs->maximum - val + abs->minimum);
429
430 valuator_mask_set(mask, i, val);
431 }
432 }
433
434 /**
435 * Take the valuators and process them accordingly.
436 */
437 static void
EvdevProcessValuators(InputInfoPtr pInfo)438 EvdevProcessValuators(InputInfoPtr pInfo)
439 {
440 EvdevPtr pEvdev = pInfo->private;
441 int val;
442
443 if (pEvdev->abs_vals) {
444 if (valuator_mask_fetch(pEvdev->abs_vals, 0, &val))
445 valuator_mask_set(pEvdev->old_vals, 0, val);
446 if (valuator_mask_fetch(pEvdev->abs_vals, 1, &val))
447 valuator_mask_set(pEvdev->old_vals, 1, val);
448 }
449
450 /* Apply transformations on relative coordinates */
451 if (pEvdev->rel_queued) {
452 double deltaX = 0, deltaY = 0;
453
454 if (valuator_mask_isset(pEvdev->rel_vals, REL_X))
455 deltaX = valuator_mask_get_double(pEvdev->rel_vals, REL_X);
456 if (valuator_mask_isset(pEvdev->rel_vals, REL_Y))
457 deltaY = valuator_mask_get_double(pEvdev->rel_vals, REL_Y);
458
459 if (pEvdev->swap_axes) {
460 double tmp = deltaX;
461 deltaX = deltaY;
462 deltaY = tmp;
463 }
464
465 if (pEvdev->resolution > 0) {
466 deltaX *= DEFAULT_MOUSE_DPI / pEvdev->resolution;
467 deltaY *= DEFAULT_MOUSE_DPI / pEvdev->resolution;
468 }
469
470 if (pEvdev->invert_x)
471 deltaX *= -1;
472 if (pEvdev->invert_y)
473 deltaY *= -1;
474
475 if (deltaX)
476 valuator_mask_set_double(pEvdev->rel_vals, REL_X, deltaX);
477 else
478 valuator_mask_unset(pEvdev->rel_vals, REL_X);
479
480 if (deltaY)
481 valuator_mask_set_double(pEvdev->rel_vals, REL_Y, deltaY);
482 else
483 valuator_mask_unset(pEvdev->rel_vals, REL_Y);
484
485 Evdev3BEmuProcessRelMotion(pInfo, deltaX, deltaY);
486
487 }
488 /*
489 * Some devices only generate valid abs coords when BTN_TOOL_PEN is
490 * pressed. On wacom tablets, this means that the pen is in
491 * proximity of the tablet. After the pen is removed, BTN_TOOL_PEN is
492 * released, and a (0, 0) absolute event is generated. Checking
493 * pEvdev->in_proximity here lets us ignore that event. pEvdev is
494 * initialized to 1 so devices that don't use this scheme still
495 * just works.
496 */
497 else if (pEvdev->abs_queued && pEvdev->in_proximity) {
498 EvdevSwapAbsValuators(pEvdev, pEvdev->abs_vals);
499 EvdevApplyCalibration(pEvdev, pEvdev->abs_vals);
500 Evdev3BEmuProcessAbsMotion(pInfo, pEvdev->abs_vals);
501 }
502 }
503
504 static void
EvdevProcessProximityEvent(InputInfoPtr pInfo,struct input_event * ev)505 EvdevProcessProximityEvent(InputInfoPtr pInfo, struct input_event *ev)
506 {
507 EvdevPtr pEvdev = pInfo->private;
508
509 if (!pEvdev->use_proximity)
510 return;
511
512 pEvdev->prox_queued = 1;
513
514 EvdevQueueProximityEvent(pInfo, ev->value);
515 }
516
517 /**
518 * Proximity handling is rather weird because of tablet-specific issues.
519 * Some tablets, notably Wacoms, send a 0/0 coordinate in the same EV_SYN as
520 * the out-of-proximity notify. We need to ignore those, hence we only
521 * actually post valuator events when we're in proximity.
522 *
523 * Other tablets send the x/y coordinates, then EV_SYN, then the proximity
524 * event. For those, we need to remember x/y to post it when the proximity
525 * comes.
526 *
527 * If we're not in proximity and we get valuator events, remember that, they
528 * won't be posted though. If we move into proximity without valuators, use
529 * the last ones we got and let the rest of the code post them.
530 */
531 static int
EvdevProcessProximityState(InputInfoPtr pInfo)532 EvdevProcessProximityState(InputInfoPtr pInfo)
533 {
534 EvdevPtr pEvdev = pInfo->private;
535 int prox_state = 0;
536 int i;
537
538 /* Does this device have any proximity axes? */
539 if (!pEvdev->prox)
540 return 0;
541
542 /* no proximity change in the queue */
543 if (!pEvdev->prox_queued)
544 {
545 if (pEvdev->abs_queued && !pEvdev->in_proximity)
546 for (i = 0; i < valuator_mask_size(pEvdev->abs_vals); i++)
547 if (valuator_mask_isset(pEvdev->abs_vals, i))
548 valuator_mask_set(pEvdev->prox, i,
549 valuator_mask_get(pEvdev->abs_vals, i));
550 return 0;
551 }
552
553 for (i = 0; i < pEvdev->num_queue; i++)
554 {
555 if (pEvdev->queue[i].type == EV_QUEUE_PROXIMITY)
556 {
557 prox_state = pEvdev->queue[i].val;
558 break;
559 }
560 }
561
562 /* Wacom's last frame resets all values to 0, including x/y.
563 Skip over this. */
564 if (prox_state == 0) {
565 int v;
566 if (valuator_mask_fetch(pEvdev->abs_vals, 0, &v) && v == 0)
567 valuator_mask_unset(pEvdev->abs_vals, 0);
568 if (valuator_mask_fetch(pEvdev->abs_vals, 1, &v) && v == 0)
569 valuator_mask_unset(pEvdev->abs_vals, 1);
570 }
571
572 if ((prox_state && !pEvdev->in_proximity) ||
573 (!prox_state && pEvdev->in_proximity))
574 {
575 /* We're about to go into/out of proximity but have no abs events
576 * within the EV_SYN. Use the last coordinates we have. */
577 for (i = 0; i < valuator_mask_size(pEvdev->prox); i++)
578 if (!valuator_mask_isset(pEvdev->abs_vals, i) &&
579 valuator_mask_isset(pEvdev->prox, i))
580 valuator_mask_set(pEvdev->abs_vals, i,
581 valuator_mask_get(pEvdev->prox, i));
582 valuator_mask_zero(pEvdev->prox);
583
584 pEvdev->abs_queued = valuator_mask_size(pEvdev->abs_vals);
585 }
586
587 pEvdev->in_proximity = prox_state;
588 return 1;
589 }
590
591 /**
592 * Take a button input event and process it accordingly.
593 */
594 static void
EvdevProcessButtonEvent(InputInfoPtr pInfo,struct input_event * ev)595 EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
596 {
597 unsigned int button;
598 int value;
599 EvdevPtr pEvdev = pInfo->private;
600
601 button = EvdevUtilButtonEventToButtonNumber(pEvdev, ev->code);
602
603 /* Get the signed value, earlier kernels had this as unsigned */
604 value = ev->value;
605
606 /* Handle drag lock */
607 if (EvdevDragLockFilterEvent(pInfo, button, value))
608 return;
609
610 if (EvdevWheelEmuFilterButton(pInfo, button, value))
611 return;
612
613 if (EvdevMBEmuFilterEvent(pInfo, button, value))
614 return;
615
616 if (button)
617 EvdevQueueButtonEvent(pInfo, button, value);
618 else
619 EvdevQueueKbdEvent(pInfo, ev, value);
620 }
621
622 /**
623 * Take the relative motion input event and process it accordingly.
624 */
625 static void
EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo,struct input_event * ev)626 EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
627 {
628 int value;
629 EvdevPtr pEvdev = pInfo->private;
630 int map;
631
632 /* Get the signed value, earlier kernels had this as unsigned */
633 value = ev->value;
634
635 switch (ev->code) {
636 default:
637 /* Ignore EV_REL events if we never set up for them. */
638 if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS) &&
639 ev->code != REL_WHEEL && ev->code != REL_DIAL &&
640 ev->code != REL_HWHEEL)
641 return;
642
643 /* Handle mouse wheel emulation */
644 if (EvdevWheelEmuFilterMotion(pInfo, ev))
645 return;
646
647 pEvdev->rel_queued = 1;
648 map = pEvdev->rel_axis_map[ev->code];
649
650 if (valuator_mask_isset(pEvdev->rel_vals, map))
651 value += valuator_mask_get(pEvdev->rel_vals, map);
652
653 valuator_mask_set(pEvdev->rel_vals, map, value);
654 break;
655 }
656 }
657
658 static void
EvdevProcessTouch(InputInfoPtr pInfo)659 EvdevProcessTouch(InputInfoPtr pInfo)
660 {
661 EvdevPtr pEvdev = pInfo->private;
662 int type;
663 int slot = pEvdev->cur_slot;
664
665 if (slot < 0 || !pEvdev->mt_mask)
666 return;
667
668 if (!pEvdev->slots[slot].dirty)
669 return;
670
671 switch(pEvdev->slots[slot].state)
672 {
673 case SLOTSTATE_EMPTY:
674 return;
675 case SLOTSTATE_CLOSE:
676 type = XI_TouchEnd;
677 pEvdev->slots[slot].state = SLOTSTATE_EMPTY;
678 break;
679 case SLOTSTATE_OPEN:
680 type = XI_TouchBegin;
681 pEvdev->slots[slot].state = SLOTSTATE_UPDATE;
682 break;
683 case SLOTSTATE_UPDATE:
684 default:
685 type = XI_TouchUpdate;
686 break;
687 }
688
689 EvdevSwapAbsValuators(pEvdev, pEvdev->mt_mask);
690 EvdevApplyCalibration(pEvdev, pEvdev->mt_mask);
691
692 EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, type);
693
694 pEvdev->slots[slot].dirty = 0;
695
696 valuator_mask_zero(pEvdev->mt_mask);
697 }
698
699 static int
num_slots(EvdevPtr pEvdev)700 num_slots(EvdevPtr pEvdev)
701 {
702 int value;
703
704 if (pEvdev->mtdev)
705 value = pEvdev->mtdev->caps.slot.maximum + 1;
706 else
707 value = libevdev_get_num_slots(pEvdev->dev);
708
709 /* If we don't know how many slots there are, assume at least 10 */
710 return value > 1 ? value : 10;
711 }
712
713 static int
last_mt_vals_slot(EvdevPtr pEvdev)714 last_mt_vals_slot(EvdevPtr pEvdev)
715 {
716 int value = pEvdev->cur_slot;
717
718 return value < num_slots(pEvdev) ? value : -1;
719 }
720
721 static void
EvdevProcessTouchEvent(InputInfoPtr pInfo,struct input_event * ev)722 EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
723 {
724 EvdevPtr pEvdev = pInfo->private;
725 int map;
726
727 if (!pEvdev->mtdev &&
728 !libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_SLOT))
729 return;
730
731 if (pEvdev->fake_mt)
732 return;
733
734 if (ev->code == ABS_MT_SLOT) {
735 EvdevProcessTouch(pInfo);
736 if (ev->value >= num_slots(pEvdev) ) {
737 LogMessageVerbSigSafe(X_WARNING, 0,
738 "%s: Slot index %d out of bounds (max %d), touch events may be incorrect.\n",
739 pInfo->name,
740 ev->value,
741 num_slots(pEvdev) - 1);
742 return;
743 }
744 pEvdev->cur_slot = ev->value;
745 } else
746 {
747 int slot_index = last_mt_vals_slot(pEvdev);
748 if (slot_index < 0) {
749 LogMessageVerbSigSafe(X_WARNING, 0,
750 "%s: Invalid slot index %d, touch events may be incorrect.\n",
751 pInfo->name,
752 slot_index);
753 return;
754 }
755
756 pEvdev->slots[slot_index].dirty = 1;
757 if (ev->code == ABS_MT_TRACKING_ID) {
758 if (ev->value >= 0) {
759 pEvdev->slots[slot_index].state = SLOTSTATE_OPEN;
760
761 valuator_mask_copy(pEvdev->mt_mask,
762 pEvdev->last_mt_vals[slot_index]);
763 } else if (pEvdev->slots[slot_index].state != SLOTSTATE_EMPTY)
764 pEvdev->slots[slot_index].state = SLOTSTATE_CLOSE;
765 } else {
766 map = pEvdev->abs_axis_map[ev->code];
767 valuator_mask_set(pEvdev->mt_mask, map, ev->value);
768 valuator_mask_set(pEvdev->last_mt_vals[slot_index], map,
769 ev->value);
770 }
771 }
772 }
773
774 /**
775 * Take the absolute motion input event and process it accordingly.
776 */
777 static void
EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo,struct input_event * ev)778 EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
779 {
780 int value;
781 EvdevPtr pEvdev = pInfo->private;
782 int map;
783
784 /* Get the signed value, earlier kernels had this as unsigned */
785 value = ev->value;
786
787 /* Ignore EV_ABS events if we never set up for them. */
788 if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
789 return;
790
791 if (ev->code > ABS_MAX)
792 return;
793
794 /* Always store the current abs valuator, we need it to update old_vals
795 * which is required by wheel emulation */
796 map = pEvdev->abs_axis_map[ev->code];
797 if (map < 2)
798 valuator_mask_set(pEvdev->abs_vals, map, value);
799
800 if (EvdevWheelEmuFilterMotion(pInfo, ev))
801 return;
802
803 if (ev->code >= ABS_MT_SLOT) {
804 EvdevProcessTouchEvent(pInfo, ev);
805 } else if (!pEvdev->mt_mask) {
806 map = pEvdev->abs_axis_map[ev->code];
807
808 /* check if the event must be translated into relative */
809 if (map < 2 && (pEvdev->flags & EVDEV_RELATIVE_MODE)) {
810 int oldval;
811 if (valuator_mask_fetch(pEvdev->old_vals, map, &oldval)) {
812 valuator_mask_set(pEvdev->rel_vals, map, value - oldval);
813 pEvdev->rel_queued = 1;
814 }
815 } else {
816 valuator_mask_set(pEvdev->abs_vals, map, value);
817 pEvdev->abs_queued = 1;
818 }
819 }
820 }
821
822 /**
823 * Take the key press/release input event and process it accordingly.
824 */
825 static void
EvdevProcessKeyEvent(InputInfoPtr pInfo,struct input_event * ev)826 EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
827 {
828 int value, i;
829 EvdevPtr pEvdev = pInfo->private;
830
831 /* Get the signed value, earlier kernels had this as unsigned */
832 value = ev->value;
833
834 /* don't repeat mouse buttons */
835 if (ev->code >= BTN_MOUSE && ev->code < KEY_OK)
836 if (value == 2)
837 return;
838
839 for (i = 0; i < ArrayLength(proximity_bits); i++)
840 {
841 if (ev->code == proximity_bits[i])
842 {
843 EvdevProcessProximityEvent(pInfo, ev);
844 return;
845 }
846 }
847
848 switch (ev->code) {
849 case BTN_TOUCH:
850 /* For devices that have but don't use proximity, use
851 * BTN_TOUCH as the proximity notifier */
852 if (!pEvdev->use_proximity)
853 pEvdev->in_proximity = value ? ev->code : 0;
854 /* When !pEvdev->use_proximity, we don't report
855 * proximity events to the X server. However, we
856 * still want to keep track if one is in proximity or
857 * not. This is especially important for touchpad
858 * who report proximity information to the computer
859 * (but it is not sent to X) and who might send unreliable
860 * position information when not in_proximity.
861 */
862
863 if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)) ||
864 pEvdev->mt_mask)
865 break;
866 /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
867 * BTN_LEFT. */
868 ev->code = BTN_LEFT;
869 /* Intentional fallthrough! */
870
871 default:
872 EvdevProcessButtonEvent(pInfo, ev);
873 break;
874 }
875 }
876
877 /**
878 * Post the relative motion events.
879 */
880 void
EvdevPostRelativeMotionEvents(InputInfoPtr pInfo)881 EvdevPostRelativeMotionEvents(InputInfoPtr pInfo)
882 {
883 EvdevPtr pEvdev = pInfo->private;
884
885 if (pEvdev->rel_queued && pEvdev->in_proximity) {
886 xf86PostMotionEventM(pInfo->dev, Relative, pEvdev->rel_vals);
887 }
888 }
889
890 /**
891 * Post the absolute motion events.
892 */
893 void
EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo)894 EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo)
895 {
896 EvdevPtr pEvdev = pInfo->private;
897
898 /*
899 * Some devices only generate valid abs coords when BTN_TOOL_PEN is
900 * pressed. On wacom tablets, this means that the pen is in
901 * proximity of the tablet. After the pen is removed, BTN_TOOL_PEN is
902 * released, and a (0, 0) absolute event is generated. Checking
903 * pEvdev->in_proximity here lets us ignore that event.
904 * pEvdev->in_proximity is initialized to 1 so devices that don't use
905 * this scheme still just work.
906 */
907 if (pEvdev->abs_queued && pEvdev->in_proximity) {
908 xf86PostMotionEventM(pInfo->dev, Absolute, pEvdev->abs_vals);
909 }
910 }
911
912 static void
EvdevPostProximityEvents(InputInfoPtr pInfo,int which)913 EvdevPostProximityEvents(InputInfoPtr pInfo, int which)
914 {
915 int i;
916 EvdevPtr pEvdev = pInfo->private;
917
918 for (i = 0; pEvdev->prox_queued && i < pEvdev->num_queue; i++) {
919 switch (pEvdev->queue[i].type) {
920 case EV_QUEUE_KEY:
921 case EV_QUEUE_BTN:
922 case EV_QUEUE_TOUCH:
923 break;
924 case EV_QUEUE_PROXIMITY:
925 if (pEvdev->queue[i].val == which)
926 xf86PostProximityEventM(pInfo->dev, which, pEvdev->old_vals);
927 break;
928 }
929 }
930 }
931
932 /**
933 * Post the queued key/button events.
934 */
EvdevPostQueuedEvents(InputInfoPtr pInfo)935 static void EvdevPostQueuedEvents(InputInfoPtr pInfo)
936 {
937 int i;
938 EvdevPtr pEvdev = pInfo->private;
939
940 for (i = 0; i < pEvdev->num_queue; i++) {
941 switch (pEvdev->queue[i].type) {
942 case EV_QUEUE_KEY:
943 xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].detail.key,
944 pEvdev->queue[i].val);
945 break;
946 case EV_QUEUE_BTN:
947 if (Evdev3BEmuFilterEvent(pInfo,
948 pEvdev->queue[i].detail.key,
949 pEvdev->queue[i].val))
950 break;
951
952 if (pEvdev->abs_queued && pEvdev->in_proximity) {
953 xf86PostButtonEvent(pInfo->dev, Absolute, pEvdev->queue[i].detail.key,
954 pEvdev->queue[i].val, 0, 0);
955
956 } else
957 xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].detail.key,
958 pEvdev->queue[i].val, 0, 0);
959 break;
960 case EV_QUEUE_PROXIMITY:
961 break;
962 case EV_QUEUE_TOUCH:
963 xf86PostTouchEvent(pInfo->dev, pEvdev->queue[i].detail.touch,
964 pEvdev->queue[i].val, 0,
965 pEvdev->queue[i].touchMask);
966 break;
967 }
968 }
969 }
970
971 /**
972 * Take the synchronization input event and process it accordingly; the motion
973 * notify events are sent first, then any button/key press/release events.
974 */
975 static void
EvdevProcessSyncEvent(InputInfoPtr pInfo,struct input_event * ev)976 EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
977 {
978 int i;
979 EvdevPtr pEvdev = pInfo->private;
980
981 EvdevProcessProximityState(pInfo);
982
983 EvdevProcessValuators(pInfo);
984 EvdevProcessTouch(pInfo);
985
986 EvdevPostProximityEvents(pInfo, TRUE);
987 EvdevPostRelativeMotionEvents(pInfo);
988 EvdevPostAbsoluteMotionEvents(pInfo);
989 EvdevPostQueuedEvents(pInfo);
990 EvdevPostProximityEvents(pInfo, FALSE);
991
992 for (i = 0; i < ArrayLength(pEvdev->queue); i++)
993 {
994 EventQueuePtr queue = &pEvdev->queue[i];
995 queue->detail.key = 0;
996 queue->type = 0;
997 queue->val = 0;
998 /* don't reset the touchMask */
999 }
1000
1001 if (pEvdev->rel_vals)
1002 valuator_mask_zero(pEvdev->rel_vals);
1003 if (pEvdev->abs_vals)
1004 valuator_mask_zero(pEvdev->abs_vals);
1005 pEvdev->num_queue = 0;
1006 pEvdev->abs_queued = 0;
1007 pEvdev->rel_queued = 0;
1008 pEvdev->prox_queued = 0;
1009
1010 }
1011
1012 /**
1013 * Process the events from the device; nothing is actually posted to the server
1014 * until an EV_SYN event is received.
1015 */
1016 static void
EvdevProcessEvent(InputInfoPtr pInfo,struct input_event * ev)1017 EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
1018 {
1019 switch (ev->type) {
1020 case EV_REL:
1021 EvdevProcessRelativeMotionEvent(pInfo, ev);
1022 break;
1023 case EV_ABS:
1024 EvdevProcessAbsoluteMotionEvent(pInfo, ev);
1025 break;
1026 case EV_KEY:
1027 EvdevProcessKeyEvent(pInfo, ev);
1028 break;
1029 case EV_SYN:
1030 EvdevProcessSyncEvent(pInfo, ev);
1031 break;
1032 }
1033 }
1034
1035 static void
EvdevFreeMasks(EvdevPtr pEvdev)1036 EvdevFreeMasks(EvdevPtr pEvdev)
1037 {
1038 int i;
1039
1040 free(pEvdev->slots);
1041 pEvdev->slots = NULL;
1042 valuator_mask_free(&pEvdev->abs_vals);
1043 valuator_mask_free(&pEvdev->rel_vals);
1044 valuator_mask_free(&pEvdev->old_vals);
1045 valuator_mask_free(&pEvdev->prox);
1046 valuator_mask_free(&pEvdev->mt_mask);
1047 if (pEvdev->last_mt_vals)
1048 {
1049 for (i = 0; i < libevdev_get_num_slots(pEvdev->dev); i++)
1050 valuator_mask_free(&pEvdev->last_mt_vals[i]);
1051 free(pEvdev->last_mt_vals);
1052 pEvdev->last_mt_vals = NULL;
1053 }
1054 for (i = 0; i < EVDEV_MAXQUEUE; i++)
1055 valuator_mask_free(&pEvdev->queue[i].touchMask);
1056 }
1057
1058 static void
EvdevHandleMTDevEvent(InputInfoPtr pInfo,struct input_event * ev)1059 EvdevHandleMTDevEvent(InputInfoPtr pInfo, struct input_event *ev)
1060 {
1061 EvdevPtr pEvdev = pInfo->private;
1062
1063 mtdev_put_event(pEvdev->mtdev, ev);
1064 if (libevdev_event_is_code(ev, EV_SYN, SYN_REPORT)) {
1065 while (!mtdev_empty(pEvdev->mtdev)) {
1066 struct input_event e;
1067 mtdev_get_event(pEvdev->mtdev, &e);
1068 EvdevProcessEvent(pInfo, &e);
1069 }
1070 }
1071 }
1072
1073 static void
EvdevReadInput(InputInfoPtr pInfo)1074 EvdevReadInput(InputInfoPtr pInfo)
1075 {
1076 int rc = 0;
1077 EvdevPtr pEvdev = pInfo->private;
1078 struct input_event ev;
1079
1080 do {
1081 rc = libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
1082 if (rc < 0) {
1083 if (rc != -EAGAIN && rc != -EINTR && rc != -EWOULDBLOCK) {
1084 /* May happen after resume or at device detach */
1085 xf86RemoveEnabledDevice(pInfo);
1086 EvdevCloseDevice(pInfo);
1087 LogMessageVerbSigSafe(X_ERROR, 0, "%s: Read error: %s\n", pInfo->name,
1088 strerror(-rc));
1089 }
1090 break;
1091 } else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
1092 if (pEvdev->mtdev)
1093 EvdevHandleMTDevEvent(pInfo, &ev);
1094 else
1095 EvdevProcessEvent(pInfo, &ev);
1096 }
1097 else { /* SYN_DROPPED */
1098 rc = libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
1099 while (rc == LIBEVDEV_READ_STATUS_SYNC) {
1100 if (pEvdev->mtdev)
1101 EvdevHandleMTDevEvent(pInfo, &ev);
1102 else
1103 EvdevProcessEvent(pInfo, &ev);
1104 rc = libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
1105 }
1106 }
1107 } while (rc == LIBEVDEV_READ_STATUS_SUCCESS);
1108 }
1109
1110 static void
EvdevPtrCtrlProc(DeviceIntPtr device,PtrCtrl * ctrl)1111 EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
1112 {
1113 /* Nothing to do, dix handles all settings */
1114 }
1115
1116 static void
EvdevKbdCtrl(DeviceIntPtr device,KeybdCtrl * ctrl)1117 EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
1118 {
1119 static struct { int xbit, code; } bits[] = {
1120 { CAPSFLAG, LED_CAPSL },
1121 { NUMFLAG, LED_NUML },
1122 { SCROLLFLAG, LED_SCROLLL },
1123 { MODEFLAG, LED_KANA },
1124 { COMPOSEFLAG, LED_COMPOSE }
1125 };
1126
1127 InputInfoPtr pInfo;
1128 struct input_event ev[ArrayLength(bits) + 1];
1129 int i;
1130 int rc;
1131
1132 memset(ev, 0, sizeof(ev));
1133
1134 pInfo = device->public.devicePrivate;
1135 for (i = 0; i < ArrayLength(bits); i++) {
1136 ev[i].type = EV_LED;
1137 ev[i].code = bits[i].code;
1138 ev[i].value = (ctrl->leds & bits[i].xbit) > 0;
1139 }
1140
1141 ev[i].type = EV_SYN;
1142 ev[i].code = SYN_REPORT;
1143 ev[i].value = 0;
1144
1145 rc = write(pInfo->fd, ev, sizeof ev);
1146 if (rc != sizeof ev)
1147 xf86IDrvMsg(pInfo, X_ERROR, "Failed to set keyboard controls: %s\n", strerror(errno));
1148 }
1149
1150 static int
EvdevAddKeyClass(DeviceIntPtr device)1151 EvdevAddKeyClass(DeviceIntPtr device)
1152 {
1153 int rc = Success;
1154 XkbRMLVOSet rmlvo = {0},
1155 defaults;
1156 InputInfoPtr pInfo;
1157
1158 pInfo = device->public.devicePrivate;
1159
1160 XkbGetRulesDflts(&defaults);
1161
1162 /* sorry, no rules change allowed for you */
1163 xf86ReplaceStrOption(pInfo->options, "xkb_rules", "evdev");
1164 rmlvo.rules = xf86SetStrOption(pInfo->options, "xkb_rules", NULL);
1165 rmlvo.model = xf86SetStrOption(pInfo->options, "xkb_model", defaults.model);
1166 rmlvo.layout = xf86SetStrOption(pInfo->options, "xkb_layout", defaults.layout);
1167 rmlvo.variant = xf86SetStrOption(pInfo->options, "xkb_variant", defaults.variant);
1168 rmlvo.options = xf86SetStrOption(pInfo->options, "xkb_options", defaults.options);
1169
1170 if (!InitKeyboardDeviceStruct(device, &rmlvo, NULL, EvdevKbdCtrl))
1171 rc = !Success;
1172
1173 XkbFreeRMLVOSet(&rmlvo, FALSE);
1174 XkbFreeRMLVOSet(&defaults, FALSE);
1175
1176 return rc;
1177 }
1178
1179 /* MT axes are counted twice - once as ABS_X (which the kernel keeps for
1180 * backwards compatibility), once as ABS_MT_POSITION_X. So we need to keep a
1181 * mapping of those axes to make sure we only count them once
1182 */
1183 struct mt_axis_mappings {
1184 int mt_code;
1185 int code;
1186 Bool needs_mapping; /* TRUE if both code and mt_code are present */
1187 int mapping; /* Logical mapping of 'code' axis */
1188 };
1189
1190 static struct mt_axis_mappings mt_axis_mappings[] = {
1191 {ABS_MT_POSITION_X, ABS_X},
1192 {ABS_MT_POSITION_Y, ABS_Y},
1193 {ABS_MT_PRESSURE, ABS_PRESSURE},
1194 {ABS_MT_DISTANCE, ABS_DISTANCE},
1195 };
1196
1197 /**
1198 * return TRUE if the axis is not one we should count as true axis
1199 */
1200 static int
is_blacklisted_axis(int axis)1201 is_blacklisted_axis(int axis)
1202 {
1203 switch(axis)
1204 {
1205 case ABS_MT_SLOT:
1206 case ABS_MT_TRACKING_ID:
1207 return TRUE;
1208 default:
1209 return FALSE;
1210 }
1211 }
1212
1213 static int
EvdevAddFakeSingleTouchAxes(InputInfoPtr pInfo)1214 EvdevAddFakeSingleTouchAxes(InputInfoPtr pInfo)
1215 {
1216 EvdevPtr pEvdev = pInfo->private;
1217 int num_axes = 0;
1218 int i;
1219
1220 if (pEvdev->fake_mt)
1221 return 0;
1222
1223 /* Android drivers often have ABS_MT_POSITION_X but not ABS_X.
1224 Loop over the MT->legacy axis table and add fake axes. */
1225 for (i = 0; i < ArrayLength(mt_axis_mappings); i++)
1226 {
1227 int mt_code = mt_axis_mappings[i].mt_code;
1228 int code = mt_axis_mappings[i].code;
1229 const struct input_absinfo* abs;
1230
1231 if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, mt_code) ||
1232 libevdev_has_event_code(pEvdev->dev, EV_ABS, code))
1233 continue;
1234
1235 abs = libevdev_get_abs_info(pEvdev->dev, mt_code);
1236 if (libevdev_enable_event_code(pEvdev->dev, EV_ABS, code, abs))
1237 {
1238 xf86IDrvMsg(pInfo, X_ERROR, "Failed to fake axis %s.\n",
1239 libevdev_event_code_get_name(EV_ABS, code));
1240 return -1;
1241 }
1242 xf86IDrvMsg(pInfo, X_INFO, "Faking axis %s.\n",
1243 libevdev_event_code_get_name(EV_ABS, code));
1244 num_axes++;
1245 }
1246
1247 return num_axes;
1248 }
1249
1250 static void
EvdevCountMTAxes(EvdevPtr pEvdev,int * num_mt_axes_total,int * num_mt_axes,int * num_axes)1251 EvdevCountMTAxes(EvdevPtr pEvdev, int *num_mt_axes_total,
1252 int *num_mt_axes, int *num_axes)
1253 {
1254 int axis;
1255
1256 if (pEvdev->fake_mt)
1257 return;
1258
1259 /* Absolute multitouch axes: adjust mapping and axes counts. */
1260 for (axis = ABS_MT_SLOT; axis <= ABS_MAX; axis++)
1261 {
1262 int j;
1263 Bool skip = FALSE;
1264
1265 if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, axis))
1266 continue;
1267
1268 /* Setup mapping if axis is in MT->legacy axis table. */
1269 for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
1270 {
1271 if (mt_axis_mappings[j].mt_code == axis &&
1272 libevdev_has_event_code(pEvdev->dev, EV_ABS, mt_axis_mappings[j].code))
1273 {
1274 mt_axis_mappings[j].needs_mapping = TRUE;
1275 skip = TRUE;
1276 }
1277 }
1278
1279 if (!is_blacklisted_axis(axis))
1280 {
1281 (*num_mt_axes_total)++;
1282 if (!skip)
1283 (*num_mt_axes)++;
1284 }
1285 (*num_axes)--;
1286 }
1287 }
1288
1289 static int
EvdevAddAbsValuatorClass(DeviceIntPtr device,int num_scroll_axes)1290 EvdevAddAbsValuatorClass(DeviceIntPtr device, int num_scroll_axes)
1291 {
1292 InputInfoPtr pInfo;
1293 EvdevPtr pEvdev;
1294 int axis, i = 0;
1295 int num_axes = 0; /* number of non-MT axes */
1296 int num_mt_axes = 0, /* number of MT-only axes */
1297 num_mt_axes_total = 0; /* total number of MT axes, including
1298 double-counted ones, excluding blacklisted */
1299 int num_faked_axes;
1300 Atom *atoms;
1301 int mapping = 0;
1302
1303 pInfo = device->public.devicePrivate;
1304 pEvdev = pInfo->private;
1305
1306 if (!libevdev_has_event_type(pEvdev->dev, EV_ABS))
1307 goto out;
1308
1309 /* Find number of absolute axis, including MT ones, will decrease later. */
1310 for (i = 0; i <= ABS_MAX; i++)
1311 if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i))
1312 num_axes++;
1313
1314 if (num_axes < 1)
1315 goto out;
1316
1317 num_faked_axes = EvdevAddFakeSingleTouchAxes(pInfo);
1318 if (num_faked_axes < 0)
1319 goto out;
1320
1321 num_axes += num_faked_axes;
1322
1323 EvdevCountMTAxes(pEvdev, &num_mt_axes_total, &num_mt_axes, &num_axes);
1324
1325 /* Panic if, after faking ABS_X etc, we still only have mt-axes. */
1326 if (num_axes == 0 && num_mt_axes > 0) {
1327 xf86IDrvMsg(pInfo, X_ERROR,
1328 "found only multitouch-axes. That shouldn't happen.\n");
1329 goto out;
1330 }
1331
1332
1333
1334 num_axes += num_scroll_axes;
1335
1336 if (num_axes + num_mt_axes > MAX_VALUATORS) {
1337 xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS);
1338 num_axes = MAX_VALUATORS;
1339 }
1340
1341 if (num_axes < 1 && num_mt_axes_total < 1) {
1342 xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n",
1343 device->name);
1344 return !Success;
1345 }
1346
1347 pEvdev->num_vals = num_axes;
1348 if (num_axes > 0) {
1349 pEvdev->abs_vals = valuator_mask_new(num_axes);
1350 pEvdev->old_vals = valuator_mask_new(num_axes);
1351 pEvdev->rel_vals = valuator_mask_new(num_axes);
1352 /* One needs rel_vals for an absolute device because
1353 * a) their might be some (relative) scroll axes
1354 * b) the device could be set in EVDEV_RELATIVE_MODE
1355 */
1356 if (!pEvdev->abs_vals || !pEvdev->rel_vals || !pEvdev->old_vals) {
1357 xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate valuator masks.\n");
1358 goto out;
1359 }
1360 }
1361
1362 if (num_mt_axes_total > 0) {
1363 int nslots = num_slots(pEvdev);
1364
1365 pEvdev->num_mt_vals = num_mt_axes_total;
1366 pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total);
1367 if (!pEvdev->mt_mask) {
1368 xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n",
1369 device->name);
1370 goto out;
1371 }
1372
1373 pEvdev->slots = calloc(nslots, sizeof(*pEvdev->slots));
1374 if (!pEvdev->slots) {
1375 xf86Msg(X_ERROR, "%s: failed to allocate slot state array.\n",
1376 device->name);
1377 goto out;
1378 }
1379 for (i = 0; i < nslots; i++) {
1380 pEvdev->slots[i].state = SLOTSTATE_EMPTY;
1381 pEvdev->slots[i].dirty = 0;
1382 }
1383
1384 pEvdev->last_mt_vals = calloc(nslots, sizeof(ValuatorMask *));
1385 if (!pEvdev->last_mt_vals) {
1386 xf86IDrvMsg(pInfo, X_ERROR,
1387 "%s: failed to allocate MT last values mask array.\n",
1388 device->name);
1389 goto out;
1390 }
1391
1392 for (i = 0; i < nslots; i++) {
1393 pEvdev->last_mt_vals[i] = valuator_mask_new(num_mt_axes_total);
1394 if (!pEvdev->last_mt_vals[i]) {
1395 xf86IDrvMsg(pInfo, X_ERROR,
1396 "%s: failed to allocate MT last values mask.\n",
1397 device->name);
1398 goto out;
1399 }
1400 }
1401
1402 for (i = 0; i < EVDEV_MAXQUEUE; i++) {
1403 pEvdev->queue[i].touchMask =
1404 valuator_mask_new(num_mt_axes_total);
1405 if (!pEvdev->queue[i].touchMask) {
1406 xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for "
1407 "evdev event queue.\n", device->name);
1408 goto out;
1409 }
1410 }
1411 }
1412 atoms = malloc((pEvdev->num_vals + num_mt_axes) * sizeof(Atom));
1413
1414 i = 2;
1415 for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
1416 int j;
1417 pEvdev->abs_axis_map[axis] = -1;
1418 if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, axis) ||
1419 is_blacklisted_axis(axis))
1420 continue;
1421
1422 if (axis == ABS_X)
1423 mapping = 0;
1424 else if (axis == ABS_Y)
1425 mapping = 1;
1426 else
1427 mapping = i;
1428
1429 for (j = 0; !pEvdev->fake_mt && j < ArrayLength(mt_axis_mappings); j++)
1430 {
1431 if (mt_axis_mappings[j].code == axis)
1432 mt_axis_mappings[j].mapping = mapping;
1433 else if (mt_axis_mappings[j].mt_code == axis &&
1434 mt_axis_mappings[j].needs_mapping)
1435 mapping = mt_axis_mappings[j].mapping;
1436 }
1437 pEvdev->abs_axis_map[axis] = mapping;
1438 if (mapping == i)
1439 i++;
1440 }
1441
1442 if (num_scroll_axes > 0)
1443 {
1444 mapping++; /* continue from abs axis mapping */
1445
1446 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL))
1447 pEvdev->rel_axis_map[REL_HWHEEL] = mapping++;
1448 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL))
1449 pEvdev->rel_axis_map[REL_DIAL] = mapping++;
1450 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL))
1451 pEvdev->rel_axis_map[REL_WHEEL] = mapping++;
1452 }
1453
1454 EvdevInitAxesLabels(pEvdev, Absolute, pEvdev->num_vals + num_mt_axes, atoms);
1455
1456 if (!InitValuatorClassDeviceStruct(device, num_axes + num_mt_axes, atoms,
1457 GetMotionHistorySize(), Absolute)) {
1458 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize valuator class device.\n");
1459 goto out;
1460 }
1461
1462 if (num_mt_axes_total > 0)
1463 {
1464 int num_touches = 0;
1465 int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
1466 XIDependentTouch : XIDirectTouch;
1467
1468 num_touches = num_slots(pEvdev);
1469
1470 if (!InitTouchClassDeviceStruct(device, num_touches, mode,
1471 num_mt_axes_total)) {
1472 xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n",
1473 device->name);
1474 goto out;
1475 }
1476
1477 for (i = 0; i < num_touches; i++) {
1478 for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) {
1479 if (pEvdev->abs_axis_map[axis] >= 0) {
1480 int val = pEvdev->mtdev ? 0 : libevdev_get_current_slot(pEvdev->dev);
1481 /* XXX: read initial values from mtdev when it adds support
1482 * for doing so. */
1483 valuator_mask_set(pEvdev->last_mt_vals[i],
1484 pEvdev->abs_axis_map[axis], val);
1485 }
1486 }
1487 }
1488 }
1489
1490 for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) {
1491 const struct input_absinfo *abs;
1492 int axnum = pEvdev->abs_axis_map[axis];
1493 int resolution = 0;
1494
1495 if (axnum == -1)
1496 continue;
1497
1498 abs = libevdev_get_abs_info(pEvdev->dev, axis);
1499 #ifdef __linux__
1500 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30)
1501 /* Kernel provides units/mm, X wants units/m */
1502 resolution = abs->resolution * 1000;
1503 #endif
1504 #else
1505 /* Kernel provides units/mm, X wants units/m */
1506 resolution = abs->resolution * 1000;
1507 #endif
1508
1509 xf86InitValuatorAxisStruct(device, axnum,
1510 atoms[axnum],
1511 abs->minimum,
1512 abs->maximum,
1513 resolution, 0, resolution, Absolute);
1514 xf86InitValuatorDefaults(device, axnum);
1515 }
1516
1517 for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) {
1518 const struct input_absinfo *abs;
1519 int axnum = pEvdev->abs_axis_map[axis];
1520 int resolution = 0;
1521 int j;
1522 BOOL skip = FALSE;
1523
1524 if (axnum < 0)
1525 continue;
1526
1527 abs = libevdev_get_abs_info(pEvdev->dev, axis);
1528
1529 for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
1530 if (mt_axis_mappings[j].mt_code == axis &&
1531 mt_axis_mappings[j].needs_mapping)
1532 {
1533 skip = TRUE;
1534 break;
1535 }
1536
1537 /* MT axis is mapped, don't set up twice */
1538 if (skip)
1539 continue;
1540
1541 resolution = abs->resolution * 1000;
1542
1543 xf86InitValuatorAxisStruct(device, axnum,
1544 atoms[axnum],
1545 abs->minimum,
1546 abs->maximum,
1547 resolution, 0, resolution,
1548 Absolute);
1549 }
1550
1551 if (num_scroll_axes)
1552 {
1553 int idx;
1554 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL))
1555 {
1556 idx = REL_WHEEL;
1557 xf86InitValuatorAxisStruct(device,
1558 pEvdev->rel_axis_map[idx],
1559 atoms[pEvdev->rel_axis_map[idx]],
1560 NO_AXIS_LIMITS, NO_AXIS_LIMITS,
1561 0, 0, 0, Relative);
1562 SetScrollValuator(device, pEvdev->rel_axis_map[idx],
1563 SCROLL_TYPE_VERTICAL,
1564 -pEvdev->smoothScroll.vert_delta,
1565 SCROLL_FLAG_PREFERRED);
1566 }
1567
1568 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL))
1569 {
1570 idx = REL_HWHEEL;
1571 xf86InitValuatorAxisStruct(device,
1572 pEvdev->rel_axis_map[idx],
1573 atoms[pEvdev->rel_axis_map[idx]],
1574 NO_AXIS_LIMITS, NO_AXIS_LIMITS,
1575 0, 0, 0, Relative);
1576 SetScrollValuator(device, pEvdev->rel_axis_map[idx],
1577 SCROLL_TYPE_HORIZONTAL,
1578 pEvdev->smoothScroll.horiz_delta,
1579 SCROLL_FLAG_NONE);
1580 }
1581
1582 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL))
1583 {
1584 idx = REL_DIAL;
1585 xf86InitValuatorAxisStruct(device,
1586 pEvdev->rel_axis_map[idx],
1587 atoms[pEvdev->rel_axis_map[idx]],
1588 NO_AXIS_LIMITS, NO_AXIS_LIMITS,
1589 0, 0, 0, Relative);
1590 SetScrollValuator(device, pEvdev->rel_axis_map[idx],
1591 SCROLL_TYPE_HORIZONTAL,
1592 pEvdev->smoothScroll.dial_delta,
1593 SCROLL_FLAG_NONE);
1594 }
1595 }
1596
1597 free(atoms);
1598
1599 for (i = 0; i < ArrayLength(proximity_bits); i++)
1600 {
1601 if (!pEvdev->use_proximity)
1602 break;
1603
1604 if (libevdev_has_event_code(pEvdev->dev, EV_KEY, proximity_bits[i]))
1605 {
1606 InitProximityClassDeviceStruct(device);
1607 pEvdev->prox = valuator_mask_new(num_axes);
1608 if (!pEvdev->prox) {
1609 xf86IDrvMsg(pInfo, X_ERROR,
1610 "failed to allocate proximity valuator " "mask.\n");
1611 goto out;
1612 }
1613 break;
1614 }
1615 }
1616
1617 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
1618 xf86IDrvMsg(pInfo, X_ERROR,
1619 "failed to initialize pointer feedback class device.\n");
1620 goto out;
1621 }
1622
1623 if (pEvdev->flags & EVDEV_TOUCHPAD)
1624 pEvdev->flags |= EVDEV_RELATIVE_MODE;
1625 else
1626 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
1627
1628 if (xf86FindOption(pInfo->options, "Mode"))
1629 {
1630 char *mode;
1631 mode = xf86SetStrOption(pInfo->options, "Mode", NULL);
1632 if (!strcasecmp("absolute", mode))
1633 pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
1634 else if (!strcasecmp("relative", mode))
1635 pEvdev->flags |= EVDEV_RELATIVE_MODE;
1636 else
1637 xf86IDrvMsg(pInfo, X_INFO, "unknown mode, use default\n");
1638 free(mode);
1639 }
1640
1641 return Success;
1642
1643 out:
1644 EvdevFreeMasks(pEvdev);
1645 return !Success;
1646 }
1647
1648 static int
EvdevSetScrollValuators(DeviceIntPtr device)1649 EvdevSetScrollValuators(DeviceIntPtr device)
1650 {
1651 InputInfoPtr pInfo;
1652 EvdevPtr pEvdev;
1653 int axnum;
1654
1655 pInfo = device->public.devicePrivate;
1656 pEvdev = pInfo->private;
1657
1658 axnum = pEvdev->rel_axis_map[REL_WHEEL];
1659 if (axnum != -1) {
1660 SetScrollValuator(device, axnum, SCROLL_TYPE_VERTICAL,
1661 -pEvdev->smoothScroll.vert_delta,
1662 SCROLL_FLAG_PREFERRED);
1663 }
1664
1665 axnum = pEvdev->rel_axis_map[REL_DIAL];
1666 if (axnum != -1) {
1667 SetScrollValuator(device, axnum, SCROLL_TYPE_HORIZONTAL,
1668 pEvdev->smoothScroll.dial_delta,
1669 SCROLL_FLAG_NONE);
1670 }
1671
1672 axnum = pEvdev->rel_axis_map[REL_HWHEEL];
1673 if (axnum != -1) {
1674 SetScrollValuator(device, axnum, SCROLL_TYPE_HORIZONTAL,
1675 pEvdev->smoothScroll.horiz_delta,
1676 SCROLL_FLAG_NONE);
1677 }
1678
1679 return Success;
1680 }
1681
1682 static int
EvdevAddRelValuatorClass(DeviceIntPtr device,int num_scroll_axes)1683 EvdevAddRelValuatorClass(DeviceIntPtr device, int num_scroll_axes)
1684 {
1685 InputInfoPtr pInfo;
1686 EvdevPtr pEvdev;
1687 int num_axes = 0, axis, map, i = 0;
1688 Atom *atoms;
1689
1690 pInfo = device->public.devicePrivate;
1691 pEvdev = pInfo->private;
1692
1693 if (!libevdev_has_event_type(pEvdev->dev, EV_REL))
1694 goto out;
1695
1696 for (i = 0; i <= REL_MAX; i++) {
1697 if (i == REL_WHEEL || i == REL_HWHEEL || i == REL_DIAL)
1698 continue;
1699
1700 if (libevdev_has_event_code(pEvdev->dev, EV_REL, i))
1701 num_axes++;
1702 }
1703
1704 /* If we have only relative scroll axes, then we punt axis init to
1705 EvdevInitAbsValuators if possible */
1706 if (num_axes < 1 &&
1707 (num_scroll_axes == 0 || pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
1708 goto out;
1709
1710 num_axes += num_scroll_axes;
1711
1712 if (num_axes > MAX_VALUATORS) {
1713 xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS);
1714 num_axes = MAX_VALUATORS;
1715 }
1716
1717 pEvdev->num_vals = num_axes;
1718 if (num_axes > 0) {
1719 pEvdev->rel_vals = valuator_mask_new(num_axes);
1720 if (!pEvdev->rel_vals)
1721 goto out;
1722 }
1723 atoms = malloc(pEvdev->num_vals * sizeof(Atom));
1724
1725 for (axis = REL_X, map = 0; map < MAX_VALUATORS && axis <= REL_MAX; axis++)
1726 {
1727 pEvdev->rel_axis_map[axis] = -1;
1728 if (!libevdev_has_event_code(pEvdev->dev, EV_REL, axis))
1729 continue;
1730 pEvdev->rel_axis_map[axis] = map;
1731 map++;
1732 }
1733
1734 EvdevInitAxesLabels(pEvdev, Relative, pEvdev->num_vals, atoms);
1735
1736 if (!InitValuatorClassDeviceStruct(device, num_axes, atoms,
1737 GetMotionHistorySize(), Relative)) {
1738 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize valuator class device.\n");
1739 goto out;
1740 }
1741
1742 if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
1743 xf86IDrvMsg(pInfo, X_ERROR, "failed to initialize pointer feedback class "
1744 "device.\n");
1745 goto out;
1746 }
1747
1748 for (axis = REL_X; axis <= REL_MAX; axis++)
1749 {
1750 int axnum = pEvdev->rel_axis_map[axis];
1751
1752 if (axnum == -1)
1753 continue;
1754 xf86InitValuatorAxisStruct(device, axnum, atoms[axnum], -1, -1, 1, 0, 1,
1755 Relative);
1756 xf86InitValuatorDefaults(device, axnum);
1757 }
1758
1759 EvdevSetScrollValuators(device);
1760
1761 free(atoms);
1762
1763 return Success;
1764
1765 out:
1766 valuator_mask_free(&pEvdev->rel_vals);
1767 return !Success;
1768 }
1769
1770 static int
EvdevAddButtonClass(DeviceIntPtr device)1771 EvdevAddButtonClass(DeviceIntPtr device)
1772 {
1773 InputInfoPtr pInfo;
1774 EvdevPtr pEvdev;
1775 Atom *labels;
1776
1777 pInfo = device->public.devicePrivate;
1778 pEvdev = pInfo->private;
1779
1780 labels = malloc(pEvdev->num_buttons * sizeof(Atom));
1781 EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels);
1782
1783 if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons, labels,
1784 pEvdev->btnmap))
1785 return !Success;
1786
1787 free(labels);
1788 return Success;
1789 }
1790
1791 /**
1792 * Init the button mapping for the device. By default, this is a 1:1 mapping,
1793 * i.e. Button 1 maps to Button 1, Button 2 to 2, etc.
1794 *
1795 * If a mapping has been specified, the mapping is the default, with the
1796 * user-defined ones overwriting the defaults.
1797 * i.e. a user-defined mapping of "3 2 1" results in a mapping of 3 2 1 4 5 6 ...
1798 *
1799 * Invalid button mappings revert to the default.
1800 *
1801 * Note that index 0 is unused, button 0 does not exist.
1802 * This mapping is initialised for all devices, but only applied if the device
1803 * has buttons (in EvdevAddButtonClass).
1804 */
1805 static void
EvdevInitButtonMapping(InputInfoPtr pInfo)1806 EvdevInitButtonMapping(InputInfoPtr pInfo)
1807 {
1808 int i, nbuttons = 1;
1809 char *mapping = NULL;
1810 EvdevPtr pEvdev = pInfo->private;
1811
1812 /* Check for user-defined button mapping */
1813 if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL)))
1814 {
1815 char *map, *s = NULL;
1816 int btn = 0;
1817
1818 xf86IDrvMsg(pInfo, X_CONFIG, "ButtonMapping '%s'\n", mapping);
1819 map = mapping;
1820 do
1821 {
1822 btn = strtol(map, &s, 10);
1823
1824 if (s == map || btn < 0 || btn > EVDEV_MAXBUTTONS)
1825 {
1826 xf86IDrvMsg(pInfo, X_ERROR,
1827 "... Invalid button mapping. Using defaults\n");
1828 nbuttons = 1; /* ensure defaults start at 1 */
1829 break;
1830 }
1831
1832 pEvdev->btnmap[nbuttons++] = btn;
1833 map = s;
1834 } while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS);
1835 free(mapping);
1836 }
1837
1838 for (i = nbuttons; i < ArrayLength(pEvdev->btnmap); i++)
1839 pEvdev->btnmap[i] = i;
1840
1841 }
1842
1843 static int
EvdevCountScrollAxes(EvdevPtr pEvdev)1844 EvdevCountScrollAxes(EvdevPtr pEvdev)
1845 {
1846 int num_scroll_axes = 0;
1847
1848 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL))
1849 num_scroll_axes++;
1850 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL))
1851 num_scroll_axes++;
1852 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL))
1853 num_scroll_axes++;
1854
1855 return num_scroll_axes;
1856 }
1857
1858 static void
EvdevInitAnyValuators(DeviceIntPtr device,EvdevPtr pEvdev)1859 EvdevInitAnyValuators(DeviceIntPtr device, EvdevPtr pEvdev)
1860 {
1861 InputInfoPtr pInfo = device->public.devicePrivate;
1862 int num_scroll_axes = EvdevCountScrollAxes(pEvdev);
1863
1864 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS &&
1865 EvdevAddRelValuatorClass(device, num_scroll_axes) == Success)
1866 xf86IDrvMsg(pInfo, X_INFO, "initialized for relative axes.\n");
1867 /* FIXME: EvdevAddAbsValuatorClass overwrites the valuators initialized
1868 in EvdevAddRelValuatorClass and leaks the latter's memory */
1869 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS &&
1870 EvdevAddAbsValuatorClass(device, num_scroll_axes) == Success)
1871 xf86IDrvMsg(pInfo, X_INFO, "initialized for absolute axes.\n");
1872 }
1873
1874 static void
EvdevInitAbsValuators(DeviceIntPtr device,EvdevPtr pEvdev)1875 EvdevInitAbsValuators(DeviceIntPtr device, EvdevPtr pEvdev)
1876 {
1877 InputInfoPtr pInfo = device->public.devicePrivate;
1878 int num_scroll_axes = EvdevCountScrollAxes(pEvdev);
1879
1880 if (EvdevAddAbsValuatorClass(device, num_scroll_axes) == Success) {
1881 xf86IDrvMsg(pInfo, X_INFO,"initialized for absolute axes.\n");
1882 } else {
1883 xf86IDrvMsg(pInfo, X_ERROR,"failed to initialize for absolute axes.\n");
1884 pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
1885 }
1886 }
1887
1888 static void
EvdevInitRelValuators(DeviceIntPtr device,EvdevPtr pEvdev)1889 EvdevInitRelValuators(DeviceIntPtr device, EvdevPtr pEvdev)
1890 {
1891 InputInfoPtr pInfo = device->public.devicePrivate;
1892 int has_abs_axes = pEvdev->flags & EVDEV_ABSOLUTE_EVENTS;
1893 int num_scroll_axes = EvdevCountScrollAxes(pEvdev);
1894
1895 if (EvdevAddRelValuatorClass(device, num_scroll_axes) == Success) {
1896
1897 xf86IDrvMsg(pInfo, X_INFO,"initialized for relative axes.\n");
1898
1899 if (has_abs_axes) {
1900 xf86IDrvMsg(pInfo, X_WARNING,"ignoring absolute axes.\n");
1901 pEvdev->flags &= ~EVDEV_ABSOLUTE_EVENTS;
1902 }
1903
1904 } else {
1905 xf86IDrvMsg(pInfo, X_ERROR,"failed to initialize for relative axes.\n");
1906
1907 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
1908
1909 if (has_abs_axes)
1910 EvdevInitAbsValuators(device, pEvdev);
1911 }
1912 }
1913
1914 static void
EvdevInitTouchDevice(DeviceIntPtr device,EvdevPtr pEvdev)1915 EvdevInitTouchDevice(DeviceIntPtr device, EvdevPtr pEvdev)
1916 {
1917 InputInfoPtr pInfo = device->public.devicePrivate;
1918
1919 if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) {
1920 xf86IDrvMsg(pInfo, X_WARNING, "touchpads, tablets and touchscreens "
1921 "ignore relative axes.\n");
1922 pEvdev->flags &= ~EVDEV_RELATIVE_EVENTS;
1923 }
1924
1925 EvdevInitAbsValuators(device, pEvdev);
1926 }
1927
1928 static int
EvdevInit(DeviceIntPtr device)1929 EvdevInit(DeviceIntPtr device)
1930 {
1931 InputInfoPtr pInfo;
1932 EvdevPtr pEvdev;
1933
1934 pInfo = device->public.devicePrivate;
1935 pEvdev = pInfo->private;
1936
1937 if (pEvdev->flags & EVDEV_KEYBOARD_EVENTS)
1938 EvdevAddKeyClass(device);
1939 if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
1940 EvdevAddButtonClass(device);
1941
1942 /* We don't allow relative and absolute axes on the same device. The
1943 * reason is that some devices (MS Optical Desktop 2000) register both
1944 * rel and abs axes for x/y.
1945 *
1946 * The abs axes register min/max; this min/max then also applies to the
1947 * relative device (the mouse) and caps it at 0..255 for both axes.
1948 * So, unless you have a small screen, you won't be enjoying it much;
1949 * consequently, absolute axes are generally ignored.
1950 *
1951 * However, currenly only a device with absolute axes can be registered
1952 * as a touch{pad,screen}. Thus, given such a device, absolute axes are
1953 * used and relative axes are ignored.
1954 */
1955
1956 if ((pEvdev->flags & (EVDEV_UNIGNORE_RELATIVE|EVDEV_UNIGNORE_ABSOLUTE)) == EVDEV_UNIGNORE_RELATIVE)
1957 EvdevInitRelValuators(device, pEvdev);
1958 else if (pEvdev->flags & EVDEV_UNIGNORE_ABSOLUTE)
1959 EvdevInitAnyValuators(device, pEvdev);
1960 else if (pEvdev->flags & (EVDEV_TOUCHPAD | EVDEV_TOUCHSCREEN | EVDEV_TABLET))
1961 EvdevInitTouchDevice(device, pEvdev);
1962 else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
1963 EvdevInitRelValuators(device, pEvdev);
1964 else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
1965 EvdevInitAbsValuators(device, pEvdev);
1966
1967 /* We drop the return value, the only time we ever want the handlers to
1968 * unregister is when the device dies. In which case we don't have to
1969 * unregister anyway */
1970 EvdevInitProperty(device);
1971 XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
1972 EvdevMBEmuInitProperty(device);
1973 Evdev3BEmuInitProperty(device);
1974 EvdevWheelEmuInitProperty(device);
1975 EvdevDragLockInitProperty(device);
1976 EvdevAppleInitProperty(device);
1977
1978 return Success;
1979 }
1980
1981 /**
1982 * Init all extras (wheel emulation, etc.) and grab the device.
1983 */
1984 static int
EvdevOn(DeviceIntPtr device)1985 EvdevOn(DeviceIntPtr device)
1986 {
1987 InputInfoPtr pInfo;
1988 EvdevPtr pEvdev;
1989 int rc = Success;
1990
1991 pInfo = device->public.devicePrivate;
1992 pEvdev = pInfo->private;
1993 /* after PreInit fd is still open */
1994 rc = EvdevOpenDevice(pInfo);
1995 if (rc != Success)
1996 return rc;
1997
1998 EvdevGrabDevice(pInfo, 1, 0);
1999
2000 xf86FlushInput(pInfo->fd);
2001 xf86AddEnabledDevice(pInfo);
2002 EvdevMBEmuOn(pInfo);
2003 Evdev3BEmuOn(pInfo);
2004 pEvdev->flags |= EVDEV_INITIALIZED;
2005 device->public.on = TRUE;
2006
2007 return Success;
2008 }
2009
2010
2011 static int
EvdevProc(DeviceIntPtr device,int what)2012 EvdevProc(DeviceIntPtr device, int what)
2013 {
2014 InputInfoPtr pInfo;
2015 EvdevPtr pEvdev;
2016
2017 pInfo = device->public.devicePrivate;
2018 pEvdev = pInfo->private;
2019
2020 switch (what)
2021 {
2022 case DEVICE_INIT:
2023 return EvdevInit(device);
2024
2025 case DEVICE_ON:
2026 return EvdevOn(device);
2027
2028 case DEVICE_OFF:
2029 if (pEvdev->flags & EVDEV_INITIALIZED)
2030 {
2031 EvdevMBEmuFinalize(pInfo);
2032 Evdev3BEmuFinalize(pInfo);
2033 }
2034 if (pInfo->fd != -1)
2035 {
2036 EvdevGrabDevice(pInfo, 0, 1);
2037 xf86RemoveEnabledDevice(pInfo);
2038 EvdevCloseDevice(pInfo);
2039 }
2040 pEvdev->min_maj = 0;
2041 pEvdev->flags &= ~EVDEV_INITIALIZED;
2042 device->public.on = FALSE;
2043 break;
2044
2045 case DEVICE_CLOSE:
2046 xf86IDrvMsg(pInfo, X_INFO, "Close\n");
2047 EvdevCloseDevice(pInfo);
2048 EvdevFreeMasks(pEvdev);
2049 pEvdev->min_maj = 0;
2050 break;
2051
2052 default:
2053 return BadValue;
2054 }
2055
2056 return Success;
2057 }
2058
2059 /**
2060 * Get as much information as we can from the fd and cache it.
2061 *
2062 * @return Success if the information was cached, or !Success otherwise.
2063 */
2064 static int
EvdevCache(InputInfoPtr pInfo)2065 EvdevCache(InputInfoPtr pInfo)
2066 {
2067 EvdevPtr pEvdev = pInfo->private;
2068 int i;
2069
2070 /*
2071 * Do not try to validate absinfo data since it is not expected
2072 * to be static, always refresh it in evdev structure.
2073 */
2074 for (i = ABS_X; i <= ABS_MAX; i++) {
2075 if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i)) {
2076 const struct input_absinfo *abs = libevdev_get_abs_info(pEvdev->dev, i);
2077 xf86IDrvMsgVerb(pInfo, X_PROBED, 6, "absolute axis %#x [%d..%d]\n",
2078 i, abs->minimum, abs->maximum);
2079 }
2080 }
2081
2082 return Success;
2083 }
2084
2085 /**
2086 * Issue an EVIOCGRAB on the device file, either as a grab or to ungrab, or
2087 * both. Return TRUE on success, otherwise FALSE. Failing the release is a
2088 * still considered a success, because it's not as if you could do anything
2089 * about it.
2090 */
2091 static BOOL
EvdevGrabDevice(InputInfoPtr pInfo,int grab,int ungrab)2092 EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab)
2093 {
2094 EvdevPtr pEvdev = pInfo->private;
2095
2096 if (pEvdev->grabDevice)
2097 {
2098 int rc;
2099 if (grab && (rc = libevdev_grab(pEvdev->dev, LIBEVDEV_GRAB)) < 0) {
2100 xf86IDrvMsg(pInfo, X_WARNING, "Grab failed (%s)\n",
2101 strerror(-rc));
2102 return FALSE;
2103 } else if (ungrab && (rc = libevdev_grab(pEvdev->dev, LIBEVDEV_UNGRAB)) < 0)
2104 xf86IDrvMsg(pInfo, X_WARNING, "Release failed (%s)\n",
2105 strerror(-rc));
2106 }
2107
2108 return TRUE;
2109 }
2110
2111 /**
2112 * Some devices only have other axes (e.g. wheels), but we
2113 * still need x/y for these. The server relies on devices having
2114 * x/y as axes 0/1 and core/XI 1.x clients expect it too (#44655)
2115 */
2116 static void
EvdevForceXY(InputInfoPtr pInfo,int mode)2117 EvdevForceXY(InputInfoPtr pInfo, int mode)
2118 {
2119 EvdevPtr pEvdev = pInfo->private;
2120
2121 xf86IDrvMsg(pInfo, X_INFO, "Forcing %s x/y axes to exist.\n",
2122 (mode == Relative) ? "relative" : "absolute");
2123
2124 if (mode == Relative)
2125 {
2126 libevdev_enable_event_code(pEvdev->dev, EV_REL, REL_X, NULL);
2127 libevdev_enable_event_code(pEvdev->dev, EV_REL, REL_Y, NULL);
2128 } else if (mode == Absolute)
2129 {
2130 struct input_absinfo abs;
2131
2132 abs.minimum = 0;
2133 abs.maximum = 1000;
2134 abs.value = 0;
2135 abs.fuzz = 0;
2136 abs.flat = 0;
2137 abs.resolution = 0;
2138
2139 libevdev_enable_event_code(pEvdev->dev, EV_ABS, ABS_X, &abs);
2140 libevdev_enable_event_code(pEvdev->dev, EV_ABS, ABS_Y, &abs);
2141 }
2142 }
2143
2144 static int
EvdevProbe(InputInfoPtr pInfo)2145 EvdevProbe(InputInfoPtr pInfo)
2146 {
2147 int i, has_rel_axes, has_abs_axes, has_keys, num_buttons, has_scroll;
2148 int has_lmr; /* left middle right */
2149 int has_mt; /* multitouch */
2150 int ignore_abs = 0, ignore_rel = 0;
2151 EvdevPtr pEvdev = pInfo->private;
2152 int rc = 1;
2153
2154 xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n",
2155 libevdev_get_id_vendor(pEvdev->dev),
2156 libevdev_get_id_product(pEvdev->dev));
2157
2158 /* Trinary state for ignoring axes:
2159 - unset: do the normal thing.
2160 - TRUE: explicitly ignore them.
2161 - FALSE: unignore axes, use them at all cost if they're present.
2162 */
2163 if (xf86FindOption(pInfo->options, "IgnoreRelativeAxes"))
2164 {
2165 if (xf86SetBoolOption(pInfo->options, "IgnoreRelativeAxes", FALSE))
2166 ignore_rel = TRUE;
2167 else
2168 pEvdev->flags |= EVDEV_UNIGNORE_RELATIVE;
2169
2170 }
2171 if (xf86FindOption(pInfo->options, "IgnoreAbsoluteAxes"))
2172 {
2173 if (xf86SetBoolOption(pInfo->options, "IgnoreAbsoluteAxes", FALSE))
2174 ignore_abs = TRUE;
2175 else
2176 pEvdev->flags |= EVDEV_UNIGNORE_ABSOLUTE;
2177 }
2178
2179 has_rel_axes = FALSE;
2180 has_abs_axes = FALSE;
2181 has_keys = FALSE;
2182 has_scroll = FALSE;
2183 has_lmr = FALSE;
2184 has_mt = FALSE;
2185 num_buttons = 0;
2186
2187 /* count all buttons */
2188 for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
2189 {
2190 int mapping = 0;
2191 if (libevdev_has_event_code(pEvdev->dev, EV_KEY, i))
2192 {
2193 mapping = EvdevUtilButtonEventToButtonNumber(pEvdev, i);
2194 if (mapping > num_buttons)
2195 num_buttons = mapping;
2196 }
2197 }
2198
2199 has_lmr = libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_LEFT) ||
2200 libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_MIDDLE) ||
2201 libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_RIGHT);
2202
2203 if (num_buttons)
2204 {
2205 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
2206 pEvdev->num_buttons = num_buttons;
2207 xf86IDrvMsg(pInfo, X_PROBED, "Found %d mouse buttons\n", num_buttons);
2208 }
2209
2210 for (i = 0; i < REL_MAX; i++) {
2211 if (libevdev_has_event_code(pEvdev->dev, EV_REL, i)) {
2212 has_rel_axes = TRUE;
2213 break;
2214 }
2215 }
2216
2217 if (has_rel_axes) {
2218 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL) ||
2219 libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL) ||
2220 libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL)) {
2221 xf86IDrvMsg(pInfo, X_PROBED, "Found scroll wheel(s)\n");
2222 has_scroll = TRUE;
2223 if (!num_buttons)
2224 xf86IDrvMsg(pInfo, X_INFO,
2225 "Forcing buttons for scroll wheel(s)\n");
2226 num_buttons = (num_buttons < 3) ? 7 : num_buttons + 4;
2227 pEvdev->num_buttons = num_buttons;
2228 }
2229
2230 if (!ignore_rel)
2231 {
2232 xf86IDrvMsg(pInfo, X_PROBED, "Found relative axes\n");
2233 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
2234
2235 if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_X) &&
2236 libevdev_has_event_code(pEvdev->dev, EV_REL, REL_Y)) {
2237 xf86IDrvMsg(pInfo, X_PROBED, "Found x and y relative axes\n");
2238 } else if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_X) ||
2239 !libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_Y))
2240 EvdevForceXY(pInfo, Relative);
2241 } else {
2242 xf86IDrvMsg(pInfo, X_INFO, "Relative axes present but ignored.\n");
2243 has_rel_axes = FALSE;
2244 }
2245 }
2246
2247 for (i = 0; i < ABS_MAX; i++) {
2248 if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i)) {
2249 has_abs_axes = TRUE;
2250 break;
2251 }
2252 }
2253
2254 for (i = ABS_MT_SLOT; i < ABS_MAX; i++) {
2255 if (libevdev_has_event_code(pEvdev->dev, EV_ABS, i)) {
2256 has_mt = TRUE;
2257 break;
2258 }
2259 }
2260
2261 if (libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_SLOT) &&
2262 libevdev_get_num_slots(pEvdev->dev) == -1)
2263 pEvdev->fake_mt = TRUE;
2264
2265 if (ignore_abs && has_abs_axes)
2266 {
2267 xf86IDrvMsg(pInfo, X_INFO, "Absolute axes present but ignored.\n");
2268 has_abs_axes = FALSE;
2269 } else if (has_abs_axes) {
2270 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute axes\n");
2271 pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
2272
2273 if (has_mt) {
2274 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute multitouch axes\n");
2275 if (num_buttons == 0) {
2276 if (libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_JOYSTICK)) {
2277 xf86IDrvMsg(pInfo, X_INFO, "Device is a Joystick with MT without buttons. Ignoring it.\n");
2278 goto out;
2279 } else {
2280 xf86IDrvMsg(pInfo, X_INFO, "No buttons found, faking one.\n");
2281 num_buttons = 1;
2282 pEvdev->num_buttons = num_buttons;
2283 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
2284 }
2285 }
2286 if (pEvdev->fake_mt)
2287 xf86IDrvMsg(pInfo, X_PROBED, "Fake MT device detected\n");
2288 }
2289
2290 if ((libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_X) &&
2291 libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_Y))) {
2292 xf86IDrvMsg(pInfo, X_PROBED, "Found x and y absolute axes\n");
2293 if (libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_TOOL_PEN) ||
2294 libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_STYLUS) ||
2295 libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_STYLUS2))
2296 {
2297 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute tablet.\n");
2298 pEvdev->flags |= EVDEV_TABLET;
2299 if (!pEvdev->num_buttons)
2300 {
2301 pEvdev->num_buttons = 7; /* LMR + scroll wheels */
2302 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
2303 }
2304 } else if (libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_PRESSURE) ||
2305 libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_TOUCH)) {
2306 if (has_lmr || libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_TOOL_FINGER)) {
2307 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchpad.\n");
2308 pEvdev->flags |= EVDEV_TOUCHPAD;
2309 } else {
2310 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchscreen\n");
2311 pEvdev->flags |= EVDEV_TOUCHSCREEN;
2312 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
2313 }
2314 } else if (!(libevdev_has_event_code(pEvdev->dev, EV_REL, REL_X) &&
2315 libevdev_has_event_code(pEvdev->dev, EV_REL, REL_Y)) && has_lmr) {
2316 /* some touchscreens use BTN_LEFT rather than BTN_TOUCH */
2317 xf86IDrvMsg(pInfo, X_PROBED, "Found absolute touchscreen\n");
2318 pEvdev->flags |= EVDEV_TOUCHSCREEN;
2319 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
2320 }
2321 } else {
2322 if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_POSITION_X) ||
2323 !libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_POSITION_Y))
2324 EvdevForceXY(pInfo, Absolute);
2325 }
2326 }
2327
2328 for (i = 0; i < BTN_MISC; i++) {
2329 if (libevdev_has_event_code(pEvdev->dev, EV_KEY, i)) {
2330 xf86IDrvMsg(pInfo, X_PROBED, "Found keys\n");
2331 pEvdev->flags |= EVDEV_KEYBOARD_EVENTS;
2332 has_keys = TRUE;
2333 break;
2334 }
2335 }
2336
2337 if (has_rel_axes || has_abs_axes)
2338 {
2339 char *str;
2340 int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 };
2341
2342 pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE);
2343 pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE);
2344 pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE);
2345
2346 pEvdev->resolution = xf86SetIntOption(pInfo->options, "Resolution", 0);
2347 if (pEvdev->resolution < 0) {
2348 xf86IDrvMsg(pInfo, X_ERROR, "Resolution must be a positive number");
2349 pEvdev->resolution = 0;
2350 }
2351
2352 str = xf86CheckStrOption(pInfo->options, "Calibration", NULL);
2353 if (str) {
2354 num_calibration = sscanf(str, "%d %d %d %d",
2355 &calibration[0], &calibration[1],
2356 &calibration[2], &calibration[3]);
2357 free(str);
2358 if (num_calibration == 4)
2359 EvdevSetCalibration(pInfo, num_calibration, calibration);
2360 else
2361 xf86IDrvMsg(pInfo, X_ERROR,
2362 "Insufficient calibration factors (%d). Ignoring calibration\n",
2363 num_calibration);
2364 }
2365 }
2366
2367 if (has_rel_axes || has_abs_axes || num_buttons) {
2368 pInfo->flags |= XI86_SEND_DRAG_EVENTS;
2369 if (pEvdev->flags & EVDEV_TOUCHPAD) {
2370 xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchpad\n");
2371 pInfo->type_name = XI_TOUCHPAD;
2372 pEvdev->use_proximity = 0;
2373 } else if (pEvdev->flags & EVDEV_TABLET) {
2374 xf86IDrvMsg(pInfo, X_INFO, "Configuring as tablet\n");
2375 pInfo->type_name = XI_TABLET;
2376 } else if (pEvdev->flags & EVDEV_TOUCHSCREEN) {
2377 xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchscreen\n");
2378 pInfo->type_name = XI_TOUCHSCREEN;
2379 } else {
2380 if (!libevdev_has_event_code(pEvdev->dev, EV_REL, REL_X) ||
2381 !libevdev_has_event_code(pEvdev->dev, EV_REL, REL_Y)) {
2382 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
2383 EvdevForceXY(pInfo, Relative);
2384 }
2385 xf86IDrvMsg(pInfo, X_INFO, "Configuring as mouse\n");
2386 pInfo->type_name = XI_MOUSE;
2387 }
2388
2389 rc = 0;
2390 }
2391
2392 if (has_keys) {
2393 xf86IDrvMsg(pInfo, X_INFO, "Configuring as keyboard\n");
2394 pInfo->type_name = XI_KEYBOARD;
2395 rc = 0;
2396 }
2397
2398 if (has_scroll &&
2399 (has_rel_axes || has_abs_axes || num_buttons || has_keys))
2400 {
2401 xf86IDrvMsg(pInfo, X_INFO, "Adding scrollwheel support\n");
2402 pEvdev->flags |= EVDEV_BUTTON_EVENTS;
2403 pEvdev->flags |= EVDEV_RELATIVE_EVENTS;
2404
2405 pEvdev->smoothScroll.vert_delta =
2406 xf86SetIntOption(pInfo->options, "VertScrollDelta", 1);
2407 pEvdev->smoothScroll.horiz_delta =
2408 xf86SetIntOption(pInfo->options, "HorizScrollDelta", 1);
2409 pEvdev->smoothScroll.dial_delta =
2410 xf86SetIntOption(pInfo->options, "DialDelta", 1);
2411 }
2412
2413 out:
2414 if (rc)
2415 xf86IDrvMsg(pInfo, X_WARNING, "Don't know how to use device\n");
2416
2417 return rc;
2418 }
2419
2420 static void
EvdevSetCalibration(InputInfoPtr pInfo,int num_calibration,int calibration[4])2421 EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4])
2422 {
2423 EvdevPtr pEvdev = pInfo->private;
2424
2425 if (num_calibration == 0) {
2426 pEvdev->flags &= ~EVDEV_CALIBRATED;
2427 pEvdev->calibration.min_x = 0;
2428 pEvdev->calibration.max_x = 0;
2429 pEvdev->calibration.min_y = 0;
2430 pEvdev->calibration.max_y = 0;
2431 } else if (num_calibration == 4) {
2432 pEvdev->flags |= EVDEV_CALIBRATED;
2433 pEvdev->calibration.min_x = calibration[0];
2434 pEvdev->calibration.max_x = calibration[1];
2435 pEvdev->calibration.min_y = calibration[2];
2436 pEvdev->calibration.max_y = calibration[3];
2437 }
2438 }
2439
2440 /**
2441 * Open an mtdev device for this device. mtdev is a bit too generous with
2442 * memory usage, so only do so for multitouch protocol A devices.
2443 *
2444 * @return FALSE on error, TRUE if mtdev was initiated or the device doesn't
2445 * need it
2446 */
2447 static Bool
EvdevOpenMTDev(InputInfoPtr pInfo)2448 EvdevOpenMTDev(InputInfoPtr pInfo)
2449 {
2450 EvdevPtr pEvdev = pInfo->private;
2451
2452 if (pEvdev->mtdev) {
2453 pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
2454 return TRUE;
2455 } else if (libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_SLOT)) {
2456 pEvdev->cur_slot = libevdev_get_current_slot(pEvdev->dev);
2457 return TRUE;
2458 }
2459
2460 if (pInfo->fd < 0) {
2461 xf86Msg(X_ERROR, "%s: Bug. fd < 0\n", pInfo->name);
2462 return FALSE;
2463 }
2464
2465 if (!libevdev_has_event_type(pEvdev->dev, EV_ABS))
2466 return TRUE;
2467
2468 /* don't need mtdev for protocol B devices */
2469 if (libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_SLOT))
2470 return TRUE;
2471
2472 if (!libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_POSITION_X) ||
2473 !libevdev_has_event_code(pEvdev->dev, EV_ABS, ABS_MT_POSITION_Y))
2474 return TRUE;
2475
2476 xf86IDrvMsg(pInfo, X_INFO, "Using mtdev for this device\n");
2477 pEvdev->mtdev = mtdev_new_open(pInfo->fd);
2478 if (pEvdev->mtdev)
2479 pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
2480 else {
2481 xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
2482 EvdevCloseDevice(pInfo);
2483 return FALSE;
2484 }
2485
2486 return TRUE;
2487 }
2488
2489 static int
EvdevOpenDevice(InputInfoPtr pInfo)2490 EvdevOpenDevice(InputInfoPtr pInfo)
2491 {
2492 EvdevPtr pEvdev = pInfo->private;
2493 char *device = pEvdev->device;
2494
2495 if (!device)
2496 {
2497 device = xf86CheckStrOption(pInfo->options, "Device", NULL);
2498 if (!device) {
2499 xf86IDrvMsg(pInfo, X_ERROR, "No device specified.\n");
2500 return BadValue;
2501 }
2502
2503 pEvdev->device = device;
2504 xf86IDrvMsg(pInfo, X_CONFIG, "Device: \"%s\"\n", device);
2505 }
2506
2507 if (!(pInfo->flags & XI86_SERVER_FD) && pInfo->fd < 0)
2508 {
2509 do {
2510 pInfo->fd = open(device, O_RDWR | O_NONBLOCK, 0);
2511 } while (pInfo->fd < 0 && errno == EINTR);
2512 }
2513
2514 if (pInfo->fd < 0) {
2515 xf86IDrvMsg(pInfo, X_ERROR, "Unable to open evdev device \"%s\" (%s).\n", device, strerror(errno));
2516 return BadValue;
2517 }
2518
2519 if (libevdev_get_fd(pEvdev->dev) != -1) {
2520 struct input_event ev;
2521
2522 libevdev_change_fd(pEvdev->dev, pInfo->fd);
2523 /* re-sync libevdev's view of the device, but
2524 we don't care about the actual events here */
2525 libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
2526 while (libevdev_next_event(pEvdev->dev, LIBEVDEV_READ_FLAG_SYNC, &ev) == LIBEVDEV_READ_STATUS_SYNC)
2527 ;
2528 } else {
2529 int rc = libevdev_set_fd(pEvdev->dev, pInfo->fd);
2530 if (rc < 0) {
2531 xf86IDrvMsg(pInfo, X_ERROR, "Unable to query fd: %s\n", strerror(-rc));
2532 return BadValue;
2533 }
2534 }
2535
2536 /* Check major/minor of device node to avoid adding duplicate devices. */
2537 pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
2538 if (EvdevIsDuplicate(pInfo))
2539 {
2540 xf86IDrvMsg(pInfo, X_WARNING, "device file is duplicate. Ignoring.\n");
2541 EvdevCloseDevice(pInfo);
2542 return BadMatch;
2543 }
2544
2545 if (!EvdevOpenMTDev(pInfo)) {
2546 xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
2547 EvdevCloseDevice(pInfo);
2548 return BadValue;
2549 }
2550
2551 return Success;
2552 }
2553
2554 static void
EvdevCloseDevice(InputInfoPtr pInfo)2555 EvdevCloseDevice(InputInfoPtr pInfo)
2556 {
2557 EvdevPtr pEvdev = pInfo->private;
2558 if (!(pInfo->flags & XI86_SERVER_FD) && pInfo->fd >= 0)
2559 {
2560 close(pInfo->fd);
2561 pInfo->fd = -1;
2562 }
2563
2564 if (pEvdev->mtdev)
2565 {
2566 mtdev_close_delete(pEvdev->mtdev);
2567 pEvdev->mtdev = NULL;
2568 }
2569
2570 }
2571
2572
2573 static void
EvdevUnInit(InputDriverPtr drv,InputInfoPtr pInfo,int flags)2574 EvdevUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2575 {
2576 EvdevPtr pEvdev = pInfo ? pInfo->private : NULL;
2577 if (pEvdev)
2578 {
2579 /* Release string allocated in EvdevOpenDevice. */
2580 free(pEvdev->device);
2581 pEvdev->device = NULL;
2582
2583 free(pEvdev->type_name);
2584 pEvdev->type_name = NULL;
2585
2586 libevdev_free(pEvdev->dev);
2587 }
2588 xf86DeleteInput(pInfo, flags);
2589 }
2590
2591 static EvdevPtr
EvdevAlloc(InputInfoPtr pInfo)2592 EvdevAlloc(InputInfoPtr pInfo)
2593 {
2594 int i;
2595 EvdevPtr pEvdev = calloc(sizeof(EvdevRec), 1);
2596
2597 if (!pEvdev)
2598 return NULL;
2599
2600 pEvdev->dev = libevdev_new();
2601 if (!pEvdev->dev) {
2602 free(pEvdev);
2603 return NULL;
2604 }
2605
2606 /*
2607 * We initialize pEvdev->in_proximity to 1 so that device that doesn't use
2608 * proximity will still report events.
2609 */
2610 pEvdev->in_proximity = 1;
2611 pEvdev->use_proximity = 1;
2612
2613 pEvdev->cur_slot = -1;
2614
2615 for (i = 0; i < ArrayLength(pEvdev->rel_axis_map); i++)
2616 pEvdev->rel_axis_map[i] = -1;
2617 for (i = 0; i < ArrayLength(pEvdev->abs_axis_map); i++)
2618 pEvdev->abs_axis_map[i] = -1;
2619
2620 pEvdev->rel_axis_map[0] = 0;
2621 pEvdev->rel_axis_map[1] = 1;
2622
2623 pEvdev->type_name = NULL;
2624
2625 return pEvdev;
2626 }
2627
2628 static int
EvdevPreInit(InputDriverPtr drv,InputInfoPtr pInfo,int flags)2629 EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2630 {
2631 EvdevPtr pEvdev;
2632 int rc = BadAlloc;
2633
2634 if (!(pEvdev = EvdevAlloc(pInfo)))
2635 goto error;
2636
2637 pInfo->private = pEvdev;
2638 pInfo->type_name = "UNKNOWN";
2639 pInfo->device_control = EvdevProc;
2640 pInfo->read_input = EvdevReadInput;
2641 pInfo->switch_mode = EvdevSwitchMode;
2642
2643 rc = EvdevOpenDevice(pInfo);
2644 if (rc != Success)
2645 goto error;
2646
2647 /* Grabbing the event device stops in-kernel event forwarding. In other
2648 words, it disables rfkill and the "Macintosh mouse button emulation".
2649 Note that this needs a server that sets the console to RAW mode. */
2650 pEvdev->grabDevice = xf86CheckBoolOption(pInfo->options, "GrabDevice", 0);
2651
2652 /* If grabDevice is set, ungrab immediately since we only want to grab
2653 * between DEVICE_ON and DEVICE_OFF. If we never get DEVICE_ON, don't
2654 * hold a grab. */
2655
2656 if (!EvdevGrabDevice(pInfo, 1, 1))
2657 {
2658 xf86IDrvMsg(pInfo, X_WARNING, "Device may already be configured.\n");
2659 rc = BadMatch;
2660 goto error;
2661 }
2662
2663 EvdevInitButtonMapping(pInfo);
2664
2665 if (EvdevCache(pInfo) || EvdevProbe(pInfo)) {
2666 rc = BadMatch;
2667 goto error;
2668 }
2669
2670 /* Overwrite type_name with custom-defined one (#62831).
2671 Note: pInfo->type_name isn't freed so we need to manually do this
2672 */
2673 pEvdev->type_name = xf86SetStrOption(pInfo->options,
2674 "TypeName",
2675 pInfo->type_name);
2676 pInfo->type_name = pEvdev->type_name;
2677
2678 if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
2679 {
2680 EvdevMBEmuPreInit(pInfo);
2681 Evdev3BEmuPreInit(pInfo);
2682 EvdevWheelEmuPreInit(pInfo);
2683 EvdevDragLockPreInit(pInfo);
2684 }
2685
2686 return Success;
2687
2688 error:
2689 EvdevCloseDevice(pInfo);
2690 return rc;
2691 }
2692
2693 _X_EXPORT InputDriverRec EVDEV = {
2694 1,
2695 "evdev",
2696 NULL,
2697 EvdevPreInit,
2698 EvdevUnInit,
2699 NULL,
2700 NULL,
2701 #ifdef XI86_DRV_CAP_SERVER_FD
2702 XI86_DRV_CAP_SERVER_FD
2703 #endif
2704 };
2705
2706 static void
EvdevUnplug(pointer p)2707 EvdevUnplug(pointer p)
2708 {
2709 }
2710
2711 static pointer
EvdevPlug(pointer module,pointer options,int * errmaj,int * errmin)2712 EvdevPlug(pointer module,
2713 pointer options,
2714 int *errmaj,
2715 int *errmin)
2716 {
2717 xf86AddInputDriver(&EVDEV, module, 0);
2718 return module;
2719 }
2720
2721 static XF86ModuleVersionInfo EvdevVersionRec =
2722 {
2723 "evdev",
2724 MODULEVENDORSTRING,
2725 MODINFOSTRING1,
2726 MODINFOSTRING2,
2727 XORG_VERSION_CURRENT,
2728 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
2729 ABI_CLASS_XINPUT,
2730 ABI_XINPUT_VERSION,
2731 MOD_CLASS_XINPUT,
2732 {0, 0, 0, 0}
2733 };
2734
2735 _X_EXPORT XF86ModuleData evdevModuleData =
2736 {
2737 &EvdevVersionRec,
2738 EvdevPlug,
2739 EvdevUnplug
2740 };
2741
2742
2743 /* Return an index value for a given button event code
2744 * returns 0 on non-button event.
2745 */
2746 unsigned int
EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev,int code)2747 EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code)
2748 {
2749 switch (code)
2750 {
2751 /* Mouse buttons */
2752 case BTN_LEFT:
2753 return 1;
2754 case BTN_MIDDLE:
2755 return 2;
2756 case BTN_RIGHT:
2757 return 3;
2758 case BTN_SIDE ... BTN_JOYSTICK - 1:
2759 return 8 + code - BTN_SIDE;
2760
2761 /* Generic buttons */
2762 case BTN_0 ... BTN_2:
2763 return 1 + code - BTN_0;
2764 case BTN_3 ... BTN_MOUSE - 1:
2765 return 8 + code - BTN_3;
2766
2767 /* Tablet stylus buttons */
2768 case BTN_TOUCH ... BTN_STYLUS2:
2769 return 1 + code - BTN_TOUCH;
2770
2771 /* The rest */
2772 default:
2773 /* Ignore */
2774 return 0;
2775 }
2776 }
2777
EvdevInitOneAxisLabel(EvdevPtr pEvdev,int mapped_axis,const char ** labels,int label_idx,Atom * atoms)2778 static void EvdevInitOneAxisLabel(EvdevPtr pEvdev, int mapped_axis,
2779 const char **labels, int label_idx, Atom *atoms)
2780 {
2781 Atom atom;
2782
2783 if (mapped_axis == -1)
2784 return;
2785
2786 atom = XIGetKnownProperty(labels[label_idx]);
2787 if (!atom) /* Should not happen */
2788 return;
2789
2790 atoms[mapped_axis] = atom;
2791 }
2792
EvdevInitAxesLabels(EvdevPtr pEvdev,int mode,int natoms,Atom * atoms)2793 static void EvdevInitAxesLabels(EvdevPtr pEvdev, int mode, int natoms, Atom *atoms)
2794 {
2795 int axis;
2796
2797 memset(atoms, 0, natoms * sizeof(Atom));
2798
2799 /* rel[0] and [1] are always mapped, so we get the rel labels. if we
2800 have abs x/y, the labels will be overwritten with the right one */
2801 for (axis = 0; axis < ArrayLength(rel_labels); axis++)
2802 EvdevInitOneAxisLabel(pEvdev, pEvdev->rel_axis_map[axis], rel_labels, axis, atoms);
2803
2804 for (axis = 0; axis < ArrayLength(abs_labels); axis++)
2805 EvdevInitOneAxisLabel(pEvdev, pEvdev->abs_axis_map[axis], abs_labels, axis, atoms);
2806 }
2807
EvdevInitButtonLabels(EvdevPtr pEvdev,int natoms,Atom * atoms)2808 static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
2809 {
2810 Atom atom;
2811 int button, bmap;
2812
2813 /* First, make sure all atoms are initialized */
2814 atom = XIGetKnownProperty(BTN_LABEL_PROP_BTN_UNKNOWN);
2815 for (button = 0; button < natoms; button++)
2816 atoms[button] = atom;
2817
2818 for (button = BTN_MISC; button < BTN_JOYSTICK; button++)
2819 {
2820 int group = (button % 0x100)/16;
2821 int idx = button - ((button/16) * 16);
2822
2823 if (group >= ArrayLength(btn_labels))
2824 break;
2825
2826 if (!libevdev_has_event_code(pEvdev->dev, EV_KEY, button))
2827 continue;
2828
2829 if (!btn_labels[group][idx])
2830 continue;
2831
2832 atom = XIGetKnownProperty(btn_labels[group][idx]);
2833 if (!atom)
2834 continue;
2835
2836 /* Props are 0-indexed, button numbers start with 1 */
2837 bmap = EvdevUtilButtonEventToButtonNumber(pEvdev, button) - 1;
2838 atoms[bmap] = atom;
2839 }
2840
2841 /* wheel buttons, hardcoded anyway */
2842 if (natoms > 3)
2843 atoms[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
2844 if (natoms > 4)
2845 atoms[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
2846 if (natoms > 5)
2847 atoms[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
2848 if (natoms > 6)
2849 atoms[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
2850 }
2851
2852 static void
EvdevInitProperty(DeviceIntPtr dev)2853 EvdevInitProperty(DeviceIntPtr dev)
2854 {
2855 InputInfoPtr pInfo = dev->public.devicePrivate;
2856 EvdevPtr pEvdev = pInfo->private;
2857 int rc;
2858 char *device_node;
2859
2860 CARD32 product[2];
2861
2862 prop_product_id = MakeAtom(XI_PROP_PRODUCT_ID, strlen(XI_PROP_PRODUCT_ID), TRUE);
2863 product[0] = libevdev_get_id_vendor(pEvdev->dev);
2864 product[1] = libevdev_get_id_product(pEvdev->dev);
2865 rc = XIChangeDeviceProperty(dev, prop_product_id, XA_INTEGER, 32,
2866 PropModeReplace, 2, product, FALSE);
2867 if (rc != Success)
2868 return;
2869
2870 XISetDevicePropertyDeletable(dev, prop_product_id, FALSE);
2871
2872 /* Device node property */
2873 device_node = strdup(pEvdev->device);
2874 prop_device = MakeAtom(XI_PROP_DEVICE_NODE,
2875 strlen(XI_PROP_DEVICE_NODE), TRUE);
2876 rc = XIChangeDeviceProperty(dev, prop_device, XA_STRING, 8,
2877 PropModeReplace,
2878 strlen(device_node), device_node,
2879 FALSE);
2880 free(device_node);
2881
2882 if (rc != Success)
2883 return;
2884
2885 if (EvdevDeviceIsVirtual(pEvdev->device))
2886 {
2887 BOOL virtual = 1;
2888 prop_virtual = MakeAtom(XI_PROP_VIRTUAL_DEVICE,
2889 strlen(XI_PROP_VIRTUAL_DEVICE), TRUE);
2890 rc = XIChangeDeviceProperty(dev, prop_virtual, XA_INTEGER, 8,
2891 PropModeReplace, 1, &virtual, FALSE);
2892 if (rc != Success)
2893 return;
2894
2895 XISetDevicePropertyDeletable(dev, prop_virtual, FALSE);
2896 }
2897
2898
2899 XISetDevicePropertyDeletable(dev, prop_device, FALSE);
2900
2901 if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_ABSOLUTE_EVENTS))
2902 {
2903 BOOL invert[2];
2904 invert[0] = pEvdev->invert_x;
2905 invert[1] = pEvdev->invert_y;
2906
2907 prop_invert = MakeAtom(EVDEV_PROP_INVERT_AXES, strlen(EVDEV_PROP_INVERT_AXES), TRUE);
2908
2909 rc = XIChangeDeviceProperty(dev, prop_invert, XA_INTEGER, 8,
2910 PropModeReplace, 2,
2911 invert, FALSE);
2912 if (rc != Success)
2913 return;
2914
2915 XISetDevicePropertyDeletable(dev, prop_invert, FALSE);
2916
2917 prop_calibration = MakeAtom(EVDEV_PROP_CALIBRATION,
2918 strlen(EVDEV_PROP_CALIBRATION), TRUE);
2919 if (pEvdev->flags & EVDEV_CALIBRATED) {
2920 int calibration[4];
2921
2922 calibration[0] = pEvdev->calibration.min_x;
2923 calibration[1] = pEvdev->calibration.max_x;
2924 calibration[2] = pEvdev->calibration.min_y;
2925 calibration[3] = pEvdev->calibration.max_y;
2926
2927 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
2928 32, PropModeReplace, 4, calibration,
2929 FALSE);
2930 } else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) {
2931 rc = XIChangeDeviceProperty(dev, prop_calibration, XA_INTEGER,
2932 32, PropModeReplace, 0, NULL,
2933 FALSE);
2934 }
2935 if (rc != Success)
2936 return;
2937
2938 XISetDevicePropertyDeletable(dev, prop_calibration, FALSE);
2939
2940 prop_swap = MakeAtom(EVDEV_PROP_SWAP_AXES,
2941 strlen(EVDEV_PROP_SWAP_AXES), TRUE);
2942
2943 rc = XIChangeDeviceProperty(dev, prop_swap, XA_INTEGER, 8,
2944 PropModeReplace, 1, &pEvdev->swap_axes, FALSE);
2945 if (rc != Success)
2946 return;
2947
2948 XISetDevicePropertyDeletable(dev, prop_swap, FALSE);
2949
2950 /* Axis labelling */
2951 if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
2952 {
2953 int mode;
2954 int num_axes = pEvdev->num_vals + pEvdev->num_mt_vals;
2955 Atom atoms[num_axes];
2956
2957 if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
2958 mode = Absolute;
2959 else if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
2960 mode = Relative;
2961 else {
2962 xf86IDrvMsg(pInfo, X_ERROR, "BUG: mode is neither absolute nor relative\n");
2963 mode = Absolute;
2964 }
2965
2966 EvdevInitAxesLabels(pEvdev, mode, num_axes, atoms);
2967 rc = XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32,
2968 PropModeReplace, num_axes, atoms, FALSE);
2969 if (rc != Success)
2970 return;
2971
2972 XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE);
2973 }
2974 /* Button labelling */
2975 if ((pEvdev->num_buttons > 0) && (prop_btn_label = XIGetKnownProperty(BTN_LABEL_PROP)))
2976 {
2977 Atom atoms[EVDEV_MAXBUTTONS];
2978 EvdevInitButtonLabels(pEvdev, EVDEV_MAXBUTTONS, atoms);
2979 rc = XIChangeDeviceProperty(dev, prop_btn_label, XA_ATOM, 32,
2980 PropModeReplace, pEvdev->num_buttons, atoms, FALSE);
2981 if (rc != Success)
2982 return;
2983
2984 XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE);
2985 }
2986
2987 {
2988 int smooth_scroll_values[3] = {
2989 pEvdev->smoothScroll.vert_delta,
2990 pEvdev->smoothScroll.horiz_delta,
2991 pEvdev->smoothScroll.dial_delta
2992 };
2993 prop_scroll_dist = MakeAtom(EVDEV_PROP_SCROLL_DISTANCE,
2994 strlen(EVDEV_PROP_SCROLL_DISTANCE), TRUE);
2995 rc = XIChangeDeviceProperty(dev, prop_scroll_dist, XA_INTEGER, 32,
2996 PropModeReplace, 3, smooth_scroll_values, FALSE);
2997 if (rc != Success)
2998 return;
2999
3000 XISetDevicePropertyDeletable(dev, prop_scroll_dist, FALSE);
3001 }
3002
3003 }
3004
3005 }
3006
3007 static int
EvdevSetProperty(DeviceIntPtr dev,Atom atom,XIPropertyValuePtr val,BOOL checkonly)3008 EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
3009 BOOL checkonly)
3010 {
3011 InputInfoPtr pInfo = dev->public.devicePrivate;
3012 EvdevPtr pEvdev = pInfo->private;
3013
3014 if (atom == prop_invert)
3015 {
3016 BOOL* data;
3017 if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
3018 return BadMatch;
3019
3020 if (!checkonly)
3021 {
3022 data = (BOOL*)val->data;
3023 pEvdev->invert_x = data[0];
3024 pEvdev->invert_y = data[1];
3025 }
3026 } else if (atom == prop_calibration)
3027 {
3028 if (val->format != 32 || val->type != XA_INTEGER)
3029 return BadMatch;
3030 if (val->size != 4 && val->size != 0)
3031 return BadMatch;
3032
3033 if (!checkonly)
3034 EvdevSetCalibration(pInfo, val->size, val->data);
3035 } else if (atom == prop_swap)
3036 {
3037 if (val->format != 8 || val->type != XA_INTEGER || val->size != 1)
3038 return BadMatch;
3039
3040 if (!checkonly)
3041 pEvdev->swap_axes = *((BOOL*)val->data);
3042 } else if (atom == prop_scroll_dist)
3043 {
3044 if (val->format != 32 || val->type != XA_INTEGER || val->size != 3)
3045 return BadMatch;
3046
3047 if (!checkonly) {
3048 int *data = (int *)val->data;
3049 pEvdev->smoothScroll.vert_delta = data[0];
3050 pEvdev->smoothScroll.horiz_delta = data[1];
3051 pEvdev->smoothScroll.dial_delta = data[2];
3052 EvdevSetScrollValuators(dev);
3053 }
3054 } else if (atom == prop_axis_label || atom == prop_btn_label ||
3055 atom == prop_product_id || atom == prop_device ||
3056 atom == prop_virtual)
3057 return BadAccess; /* Read-only properties */
3058
3059 return Success;
3060 }
3061