1 /*
2  * Copyright © 2004-2007 Peter Osterlund
3  * Copyright © 2008-2012 Red Hat, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software
6  * and its documentation for any purpose is hereby granted without
7  * fee, provided that the above copyright notice appear in all copies
8  * and that both that copyright notice and this permission notice
9  * appear in supporting documentation, and that the name of Red Hat
10  * not be used in advertising or publicity pertaining to distribution
11  * of the software without specific, written prior permission.  Red
12  * Hat makes no representations about the suitability of this software
13  * for any purpose.  It is provided "as is" without express or implied
14  * warranty.
15  *
16  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
18  * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
20  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Authors:
25  *      Peter Osterlund (petero2@telia.com)
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include <xorg-server.h>
33 #include <xserver-properties.h>
34 #include "eventcomm.h"
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <dirent.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <time.h>
43 #include "synproto.h"
44 #include "synapticsstr.h"
45 #include <xf86.h>
46 #include <libevdev/libevdev.h>
47 
48 #ifndef INPUT_PROP_BUTTONPAD
49 #define INPUT_PROP_BUTTONPAD 0x02
50 #endif
51 #ifndef INPUT_PROP_SEMI_MT
52 #define INPUT_PROP_SEMI_MT 0x03
53 #endif
54 #ifndef INPUT_PROP_TOPBUTTONPAD
55 #define INPUT_PROP_TOPBUTTONPAD 0x04
56 #endif
57 #ifndef ABS_MT_TOOL_Y
58 #define ABS_MT_TOOL_Y 0x3d
59 #endif
60 
61 #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
62 
63 #define LONG_BITS (sizeof(long) * 8)
64 #define NBITS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
65 #define OFF(x)   ((x) % LONG_BITS)
66 #define LONG(x)  ((x) / LONG_BITS)
67 #define TEST_BIT(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
68 
69 #define ABS_MT_MIN ABS_MT_SLOT
70 #define ABS_MT_MAX ABS_MT_TOOL_Y
71 #define ABS_MT_CNT (ABS_MT_MAX - ABS_MT_MIN + 1)
72 
73 /**
74  * Protocol-specific data.
75  */
76 struct eventcomm_proto_data {
77     /**
78      * Do we need to grab the event device?
79      * Note that in the current flow, this variable is always false and
80      * exists for readability of the code.
81      */
82     BOOL need_grab;
83     int st_to_mt_offset[2];
84     double st_to_mt_scale[2];
85     int axis_map[ABS_MT_CNT];
86     int cur_slot;
87     ValuatorMask **last_mt_vals;
88     int num_touches;
89 
90     struct libevdev *evdev;
91     enum libevdev_read_flag read_flag;
92 
93     int have_monotonic_clock;
94 };
95 
96 #ifdef HAVE_LIBEVDEV_DEVICE_LOG_FUNCS
97 static void
98 libevdev_log_func(const struct libevdev *dev,
99                   enum libevdev_log_priority priority,
100                   void *data,
101                   const char *file, int line, const char *func,
102                   const char *format, va_list args)
103 _X_ATTRIBUTE_PRINTF(7, 0);
104 
105 static void
libevdev_log_func(const struct libevdev * dev,enum libevdev_log_priority priority,void * data,const char * file,int line,const char * func,const char * format,va_list args)106 libevdev_log_func(const struct libevdev *dev,
107                   enum libevdev_log_priority priority,
108                   void *data,
109                   const char *file, int line, const char *func,
110                   const char *format, va_list args)
111 {
112     int verbosity;
113 
114     switch(priority) {
115         case LIBEVDEV_LOG_ERROR: verbosity = 0; break;
116         case LIBEVDEV_LOG_INFO: verbosity = 4; break;
117         case LIBEVDEV_LOG_DEBUG:
118         default:
119             verbosity = 10;
120             break;
121     }
122 
123     LogVMessageVerbSigSafe(X_NOTICE, verbosity, format, args);
124 }
125 #endif
126 
127 struct eventcomm_proto_data *
EventProtoDataAlloc(int fd)128 EventProtoDataAlloc(int fd)
129 {
130     struct eventcomm_proto_data *proto_data;
131     int rc;
132 
133 
134     proto_data = calloc(1, sizeof(struct eventcomm_proto_data));
135     if (!proto_data)
136         return NULL;
137 
138     proto_data->st_to_mt_scale[0] = 1;
139     proto_data->st_to_mt_scale[1] = 1;
140 
141     proto_data->evdev = libevdev_new();
142     if (!proto_data->evdev) {
143         rc = -1;
144         goto out;
145     }
146 
147 #ifdef HAVE_LIBEVDEV_DEVICE_LOG_FUNCS
148     libevdev_set_device_log_function(proto_data->evdev, libevdev_log_func,
149                                      LIBEVDEV_LOG_DEBUG, NULL);
150 #endif
151 
152     rc = libevdev_set_fd(proto_data->evdev, fd);
153     if (rc < 0) {
154         goto out;
155     }
156 
157     proto_data->read_flag = LIBEVDEV_READ_FLAG_NORMAL;
158 
159 out:
160     if (rc < 0) {
161         if (proto_data && proto_data->evdev)
162             libevdev_free(proto_data->evdev);
163         free(proto_data);
164         proto_data = NULL;
165     }
166 
167     return proto_data;
168 }
169 
170 static void
UninitializeTouch(InputInfoPtr pInfo)171 UninitializeTouch(InputInfoPtr pInfo)
172 {
173     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
174     struct eventcomm_proto_data *proto_data =
175         (struct eventcomm_proto_data *) priv->proto_data;
176 
177     if (!priv->has_touch)
178         return;
179 
180     if (proto_data->last_mt_vals) {
181         int i;
182 
183         for (i = 0; i < priv->num_slots; i++)
184             valuator_mask_free(&proto_data->last_mt_vals[i]);
185         free(proto_data->last_mt_vals);
186         proto_data->last_mt_vals = NULL;
187     }
188 
189     proto_data->num_touches = 0;
190 }
191 
192 static void
InitializeTouch(InputInfoPtr pInfo)193 InitializeTouch(InputInfoPtr pInfo)
194 {
195     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
196     struct eventcomm_proto_data *proto_data =
197         (struct eventcomm_proto_data *) priv->proto_data;
198     int i;
199 
200     if (!priv->has_touch)
201         return;
202 
203     proto_data->cur_slot = libevdev_get_current_slot(proto_data->evdev);
204     proto_data->num_touches = 0;
205 
206     proto_data->last_mt_vals = calloc(priv->num_slots, sizeof(ValuatorMask *));
207     if (!proto_data->last_mt_vals) {
208         xf86IDrvMsg(pInfo, X_WARNING,
209                     "failed to allocate MT last values mask array\n");
210         UninitializeTouch(pInfo);
211         return;
212     }
213 
214     for (i = 0; i < priv->num_slots; i++) {
215         int j;
216 
217         proto_data->last_mt_vals[i] = valuator_mask_new(4 + priv->num_mt_axes);
218         if (!proto_data->last_mt_vals[i]) {
219             xf86IDrvMsg(pInfo, X_WARNING,
220                         "failed to allocate MT last values mask\n");
221             UninitializeTouch(pInfo);
222             return;
223         }
224 
225         /* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X
226          * and Y. */
227         valuator_mask_set(proto_data->last_mt_vals[i], 0, 0);
228         valuator_mask_set(proto_data->last_mt_vals[i], 1, 0);
229         for (j = 0; j < priv->num_mt_axes; j++)
230             valuator_mask_set(proto_data->last_mt_vals[i], 4 + j, 0);
231     }
232 }
233 
234 static Bool
EventDeviceOnHook(InputInfoPtr pInfo,SynapticsParameters * para)235 EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters * para)
236 {
237     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
238     struct eventcomm_proto_data *proto_data =
239         (struct eventcomm_proto_data *) priv->proto_data;
240     int ret;
241 
242     if (libevdev_get_fd(proto_data->evdev) != -1) {
243         struct input_event ev;
244 
245         libevdev_change_fd(proto_data->evdev, pInfo->fd);
246 
247         /* re-sync libevdev's state, but we don't care about the actual
248            events here */
249         libevdev_next_event(proto_data->evdev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
250         while (libevdev_next_event(proto_data->evdev,
251                     LIBEVDEV_READ_FLAG_SYNC, &ev) == LIBEVDEV_READ_STATUS_SYNC)
252             ;
253 
254     } else
255         libevdev_set_fd(proto_data->evdev, pInfo->fd);
256 
257 
258     if (para->grab_event_device) {
259         /* Try to grab the event device so that data don't leak to /dev/input/mice */
260 
261         ret = libevdev_grab(proto_data->evdev, LIBEVDEV_GRAB);
262         if (ret < 0) {
263             xf86IDrvMsg(pInfo, X_WARNING, "can't grab event device, errno=%d\n",
264                         -ret);
265             return FALSE;
266         }
267     }
268 
269     proto_data->need_grab = FALSE;
270 
271     ret = libevdev_set_clock_id(proto_data->evdev, CLOCK_MONOTONIC);
272     proto_data->have_monotonic_clock = (ret == 0);
273 
274     InitializeTouch(pInfo);
275 
276     return TRUE;
277 }
278 
279 static Bool
EventDeviceOffHook(InputInfoPtr pInfo)280 EventDeviceOffHook(InputInfoPtr pInfo)
281 {
282     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
283     struct eventcomm_proto_data *proto_data = priv->proto_data;
284 
285     UninitializeTouch(pInfo);
286     libevdev_grab(proto_data->evdev, LIBEVDEV_UNGRAB);
287     libevdev_set_log_function(NULL, NULL);
288     libevdev_set_log_priority(LIBEVDEV_LOG_INFO); /* reset to default */
289 
290     return Success;
291 }
292 
293 /**
294  * Test if the device on the file descriptior is recognized as touchpad
295  * device. Required bits for touchpad recognition are:
296  * - ABS_X + ABS_Y for absolute axes
297  * - ABS_PRESSURE or BTN_TOUCH
298  * - BTN_TOOL_FINGER
299  * - BTN_TOOL_PEN is _not_ set
300  *
301  * @param evdev Libevdev handle
302  *
303  * @return TRUE if the device is a touchpad or FALSE otherwise.
304  */
305 static Bool
event_query_is_touchpad(struct libevdev * evdev)306 event_query_is_touchpad(struct libevdev *evdev)
307 {
308     /* Check for ABS_X, ABS_Y, ABS_PRESSURE and BTN_TOOL_FINGER */
309     if (!libevdev_has_event_type(evdev, EV_SYN) ||
310         !libevdev_has_event_type(evdev, EV_ABS) ||
311         !libevdev_has_event_type(evdev, EV_KEY))
312         return FALSE;
313 
314     if (!libevdev_has_event_code(evdev, EV_ABS, ABS_X) ||
315         !libevdev_has_event_code(evdev, EV_ABS, ABS_Y))
316         return FALSE;
317 
318     /* we expect touchpad either report raw pressure or touches */
319     if (!libevdev_has_event_code(evdev, EV_KEY, BTN_TOUCH) &&
320         !libevdev_has_event_code(evdev, EV_ABS, ABS_PRESSURE))
321         return FALSE;
322 
323     /* all Synaptics-like touchpad report BTN_TOOL_FINGER */
324     if (!libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_FINGER) ||
325         libevdev_has_event_code(evdev, EV_ABS, BTN_TOOL_PEN)) /* Don't match wacom tablets */
326         return FALSE;
327 
328     if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT)) {
329         if (libevdev_get_num_slots(evdev) == -1)
330             return FALSE; /* Ignore fake MT devices */
331 
332         if (!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ||
333             !libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y))
334             return FALSE;
335     }
336 
337     return TRUE;
338 }
339 
340 #define PRODUCT_ANY 0x0000
341 
342 struct model_lookup_t {
343     short vendor;
344     short product_start;
345     short product_end;
346     enum TouchpadModel model;
347 };
348 
349 
350 static struct model_lookup_t model_lookup_table[] = {
351     {0x0002, 0x0007, 0x0007, MODEL_SYNAPTICS},
352     {0x0002, 0x0008, 0x0008, MODEL_ALPS},
353     {0x05ac, PRODUCT_ANY, 0x222, MODEL_APPLETOUCH},
354     {0x05ac, 0x223, 0x228, MODEL_UNIBODY_MACBOOK},
355     {0x05ac, 0x229, 0x22b, MODEL_APPLETOUCH},
356     {0x05ac, 0x22c, PRODUCT_ANY, MODEL_UNIBODY_MACBOOK},
357     {0x0002, 0x000e, 0x000e, MODEL_ELANTECH},
358     {0x0, 0x0, 0x0, 0x0}
359 };
360 
361 /**
362  * Check for the vendor/product id on the file descriptor and compare
363  * with the built-in model LUT. This information is used in synaptics.c to
364  * initialize model-specific dimensions.
365  *
366  * @param fd The file descriptor to a event device.
367  * @param[out] model_out The type of touchpad model detected.
368  *
369  * @return TRUE on success or FALSE otherwise.
370  */
371 static Bool
event_query_model(struct libevdev * evdev,enum TouchpadModel * model_out,unsigned short * vendor_id,unsigned short * product_id)372 event_query_model(struct libevdev *evdev, enum TouchpadModel *model_out,
373                   unsigned short *vendor_id, unsigned short *product_id)
374 {
375     int vendor, product;
376     struct model_lookup_t *model_lookup;
377 
378     vendor = libevdev_get_id_vendor(evdev);
379     product = libevdev_get_id_product(evdev);
380 
381     for (model_lookup = model_lookup_table; model_lookup->vendor;
382          model_lookup++) {
383         if (model_lookup->vendor == vendor &&
384             (model_lookup->product_start == PRODUCT_ANY ||
385              model_lookup->product_start <= product) &&
386             (model_lookup->product_end == PRODUCT_ANY ||
387              model_lookup->product_end >= product))
388             *model_out = model_lookup->model;
389     }
390 
391     *vendor_id = vendor;
392     *product_id = product;
393 
394     return TRUE;
395 }
396 
397 /**
398  * Get absinfo information from the given file descriptor for the given
399  * ABS_FOO code and store the information in min, max, fuzz and res.
400  *
401  * @param fd File descriptor to an event device
402  * @param code Event code (e.g. ABS_X)
403  * @param[out] min Minimum axis range
404  * @param[out] max Maximum axis range
405  * @param[out] fuzz Fuzz of this axis. If NULL, fuzz is ignored.
406  * @param[out] res Axis resolution. If NULL or the current kernel does not
407  * support the resolution field, res is ignored
408  *
409  * @return Zero on success, or errno otherwise.
410  */
411 static int
event_get_abs(struct libevdev * evdev,int code,int * min,int * max,int * fuzz,int * res)412 event_get_abs(struct libevdev *evdev, int code,
413               int *min, int *max, int *fuzz, int *res)
414 {
415     const struct input_absinfo *abs;
416 
417     abs = libevdev_get_abs_info(evdev, code);
418     *min = abs->minimum;
419     *max = abs->maximum;
420 
421     /* We dont trust a zero fuzz as it probably is just a lazy value */
422     if (fuzz && abs->fuzz > 0)
423         *fuzz = abs->fuzz;
424 #ifdef __linux__
425 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)
426     if (res)
427         *res = abs->resolution;
428 #endif
429 #elif defined(__FreeBSD__) || defined(__DragonFly__)
430     if (res)
431         *res = abs->resolution;
432 #endif
433 
434     return 0;
435 }
436 
437 /* Query device for axis ranges */
438 static void
event_query_axis_ranges(InputInfoPtr pInfo)439 event_query_axis_ranges(InputInfoPtr pInfo)
440 {
441     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
442     struct eventcomm_proto_data *proto_data = priv->proto_data;
443     char buf[256] = { 0 };
444 
445     /* The kernel's fuzziness concept seems a bit weird, but it can more or
446      * less be applied as hysteresis directly, i.e. no factor here. */
447     event_get_abs(proto_data->evdev, ABS_X, &priv->minx, &priv->maxx,
448                   &priv->synpara.hyst_x, &priv->resx);
449 
450     event_get_abs(proto_data->evdev, ABS_Y, &priv->miny, &priv->maxy,
451                   &priv->synpara.hyst_y, &priv->resy);
452 
453     if (priv->minx == priv->maxx || priv->miny == priv->maxy) {
454         xf86IDrvMsg(pInfo, X_ERROR, "Kernel bug: min == max on ABS_X/Y\n");
455         return;
456     }
457 
458     priv->has_pressure = libevdev_has_event_code(proto_data->evdev, EV_ABS, ABS_PRESSURE);
459     priv->has_width = libevdev_has_event_code(proto_data->evdev, EV_ABS, ABS_TOOL_WIDTH);
460 
461     if (priv->has_pressure)
462         event_get_abs(proto_data->evdev, ABS_PRESSURE, &priv->minp, &priv->maxp,
463                       NULL, NULL);
464 
465     if (priv->has_width)
466         event_get_abs(proto_data->evdev, ABS_TOOL_WIDTH,
467                       &priv->minw, &priv->maxw, NULL, NULL);
468 
469     if (priv->has_touch) {
470         int st_minx = priv->minx;
471         int st_maxx = priv->maxx;
472         int st_miny = priv->miny;
473         int st_maxy = priv->maxy;
474 
475         event_get_abs(proto_data->evdev, ABS_MT_POSITION_X, &priv->minx,
476                       &priv->maxx, &priv->synpara.hyst_x, &priv->resx);
477         event_get_abs(proto_data->evdev, ABS_MT_POSITION_Y, &priv->miny,
478                       &priv->maxy, &priv->synpara.hyst_y, &priv->resy);
479 
480         if (priv->minx == priv->maxx || priv->miny == priv->maxy) {
481             xf86IDrvMsg(pInfo, X_ERROR, "Kernel bug: min == max on ABS_MT_POSITION_X/Y\n");
482             return;
483         }
484 
485         proto_data->st_to_mt_offset[0] = priv->minx - st_minx;
486         proto_data->st_to_mt_scale[0] =
487             (priv->maxx - priv->minx) / (st_maxx - st_minx);
488         proto_data->st_to_mt_offset[1] = priv->miny - st_miny;
489         proto_data->st_to_mt_scale[1] =
490             (priv->maxy - priv->miny) / (st_maxy - st_miny);
491     }
492 
493     priv->has_left = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_LEFT);
494     priv->has_right = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_RIGHT);
495     priv->has_middle = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_MIDDLE);
496     priv->has_double = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_TOOL_DOUBLETAP);
497     priv->has_triple = libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_TOOL_TRIPLETAP);
498 
499     if (libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_0) ||
500         libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_1) ||
501         libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_2) ||
502         libevdev_has_event_code(proto_data->evdev, EV_KEY, BTN_3))
503         priv->has_scrollbuttons = 1;
504 
505     /* Now print the device information */
506     xf86IDrvMsg(pInfo, X_PROBED, "x-axis range %d - %d (res %d)\n",
507                 priv->minx, priv->maxx, priv->resx);
508     xf86IDrvMsg(pInfo, X_PROBED, "y-axis range %d - %d (res %d)\n",
509                 priv->miny, priv->maxy, priv->resy);
510     if (priv->has_pressure)
511         xf86IDrvMsg(pInfo, X_PROBED, "pressure range %d - %d\n",
512                     priv->minp, priv->maxp);
513     else
514         xf86IDrvMsg(pInfo, X_INFO,
515                     "device does not report pressure, will use touch data.\n");
516     if (priv->has_width)
517         xf86IDrvMsg(pInfo, X_PROBED, "finger width range %d - %d\n",
518                     priv->minw, priv->maxw);
519     else
520         xf86IDrvMsg(pInfo, X_INFO, "device does not report finger width.\n");
521 
522     if (priv->has_left)
523         strcat(buf, " left");
524     if (priv->has_right)
525         strcat(buf, " right");
526     if (priv->has_middle)
527         strcat(buf, " middle");
528     if (priv->has_double)
529         strcat(buf, " double");
530     if (priv->has_triple)
531         strcat(buf, " triple");
532     if (priv->has_scrollbuttons)
533         strcat(buf, " scroll-buttons");
534 
535     xf86IDrvMsg(pInfo, X_PROBED, "buttons:%s\n", buf);
536 }
537 
538 static Bool
EventQueryHardware(InputInfoPtr pInfo)539 EventQueryHardware(InputInfoPtr pInfo)
540 {
541     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
542     struct eventcomm_proto_data *proto_data = priv->proto_data;
543 
544     if (!event_query_is_touchpad(proto_data->evdev))
545         return FALSE;
546 
547     xf86IDrvMsg(pInfo, X_PROBED, "touchpad found\n");
548 
549     return TRUE;
550 }
551 
552 static Bool
SynapticsReadEvent(InputInfoPtr pInfo,struct input_event * ev)553 SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev)
554 {
555     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
556     struct eventcomm_proto_data *proto_data = priv->proto_data;
557     int rc;
558     static struct timeval last_event_time;
559 
560     rc = libevdev_next_event(proto_data->evdev, proto_data->read_flag, ev);
561     if (rc < 0) {
562         if (rc != -EAGAIN) {
563             LogMessageVerbSigSafe(X_ERROR, 0, "%s: Read error %d\n", pInfo->name,
564                     errno);
565             xf86RemoveEnabledDevice(pInfo);
566         } else if (proto_data->read_flag == LIBEVDEV_READ_FLAG_SYNC) {
567             proto_data->read_flag = LIBEVDEV_READ_FLAG_NORMAL;
568             return SynapticsReadEvent(pInfo, ev);
569         }
570 
571         return FALSE;
572     }
573 
574     /* SYN_DROPPED received in normal mode. Create a normal EV_SYN
575        so we process what's in the queue atm, then ensure we sync
576        next time */
577     if (rc == LIBEVDEV_READ_STATUS_SYNC &&
578         proto_data->read_flag == LIBEVDEV_READ_FLAG_NORMAL) {
579         proto_data->read_flag = LIBEVDEV_READ_FLAG_SYNC;
580         ev->type = EV_SYN;
581         ev->code = SYN_REPORT;
582         ev->value = 0;
583         ev->time = last_event_time;
584     } else if (ev->type == EV_SYN)
585         last_event_time = ev->time;
586 
587     return TRUE;
588 }
589 
590 static Bool
EventTouchSlotPreviouslyOpen(SynapticsPrivate * priv,int slot)591 EventTouchSlotPreviouslyOpen(SynapticsPrivate * priv, int slot)
592 {
593     int i;
594 
595     for (i = 0; i < priv->num_active_touches; i++)
596         if (priv->open_slots[i] == slot)
597             return TRUE;
598 
599     return FALSE;
600 }
601 
602 static void
EventProcessTouchEvent(InputInfoPtr pInfo,struct SynapticsHwState * hw,struct input_event * ev)603 EventProcessTouchEvent(InputInfoPtr pInfo, struct SynapticsHwState *hw,
604                        struct input_event *ev)
605 {
606     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
607     struct eventcomm_proto_data *proto_data = priv->proto_data;
608 
609     if (!priv->has_touch)
610         return;
611 
612     if (ev->code == ABS_MT_SLOT) {
613         proto_data->cur_slot = ev->value;
614     }
615     else {
616         int slot_index = proto_data->cur_slot;
617 
618         if (slot_index < 0)
619             return;
620 
621         if (hw->slot_state[slot_index] == SLOTSTATE_OPEN_EMPTY)
622             hw->slot_state[slot_index] = SLOTSTATE_UPDATE;
623         if (ev->code == ABS_MT_TRACKING_ID) {
624             if (ev->value >= 0) {
625                 hw->slot_state[slot_index] = SLOTSTATE_OPEN;
626                 proto_data->num_touches++;
627                 valuator_mask_copy(hw->mt_mask[slot_index],
628                                    proto_data->last_mt_vals[slot_index]);
629             }
630             else if (hw->slot_state[slot_index] != SLOTSTATE_EMPTY) {
631                 hw->slot_state[slot_index] = SLOTSTATE_CLOSE;
632                 proto_data->num_touches--;
633             }
634 
635             /* When there are no fingers on the touchpad, set width and
636              * pressure to zero as ABS_MT_TOUCH_MAJOR and ABS_MT_PRESSURE
637              * are not zero when fingers are released. */
638             if (proto_data->num_touches == 0) {
639                 hw->fingerWidth = 0;
640                 hw->z = 0;
641             }
642         }
643         else {
644             ValuatorMask *mask = proto_data->last_mt_vals[slot_index];
645             int map = proto_data->axis_map[ev->code - ABS_MT_TOUCH_MAJOR];
646             int last_val = valuator_mask_get(mask, map);
647 
648             valuator_mask_set(hw->mt_mask[slot_index], map, ev->value);
649             if (EventTouchSlotPreviouslyOpen(priv, slot_index)) {
650                 if (ev->code == ABS_MT_POSITION_X)
651                     hw->cumulative_dx += ev->value - last_val;
652                 else if (ev->code == ABS_MT_POSITION_Y)
653                     hw->cumulative_dy += ev->value - last_val;
654                 else if (ev->code == ABS_MT_TOUCH_MAJOR &&
655                          priv->has_mt_palm_detect)
656                     hw->fingerWidth = ev->value;
657                 else if (ev->code == ABS_MT_PRESSURE &&
658                          priv->has_mt_palm_detect)
659                     hw->z = ev->value;
660             }
661 
662             valuator_mask_set(mask, map, ev->value);
663         }
664     }
665 }
666 
667 /**
668  * Count the number of fingers based on the CommData information.
669  * The CommData struct contains the event information based on previous
670  * struct input_events, now we're just counting based on that.
671  *
672  * @param comm Assembled information from previous events.
673  * @return The number of fingers currently set.
674  */
675 static int
count_fingers(InputInfoPtr pInfo,const struct CommData * comm)676 count_fingers(InputInfoPtr pInfo, const struct CommData *comm)
677 {
678     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
679     struct eventcomm_proto_data *proto_data = priv->proto_data;
680     int fingers = 0;
681 
682     if (comm->oneFinger)
683         fingers = 1;
684     else if (comm->twoFingers)
685         fingers = 2;
686     else if (comm->threeFingers)
687         fingers = 3;
688 
689     if (priv->has_touch && proto_data->num_touches > fingers)
690         fingers = proto_data->num_touches;
691 
692     return fingers;
693 }
694 
695 static inline double
apply_st_scaling(struct eventcomm_proto_data * proto_data,int value,int axis)696 apply_st_scaling(struct eventcomm_proto_data *proto_data, int value, int axis)
697 {
698     return value * proto_data->st_to_mt_scale[axis] +
699         proto_data->st_to_mt_offset[axis];
700 }
701 
702 Bool
EventReadHwState(InputInfoPtr pInfo,struct CommData * comm,struct SynapticsHwState * hwRet)703 EventReadHwState(InputInfoPtr pInfo,
704                  struct CommData *comm, struct SynapticsHwState *hwRet)
705 {
706     struct input_event ev;
707     Bool v;
708     struct SynapticsHwState *hw = comm->hwState;
709     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
710     SynapticsParameters *para = &priv->synpara;
711     struct eventcomm_proto_data *proto_data = priv->proto_data;
712     Bool sync_cumulative = FALSE;
713 
714     SynapticsResetTouchHwState(hw, FALSE);
715 
716     /* Reset cumulative values if buttons were not previously pressed and no
717      * two-finger scrolling is ongoing, or no finger was previously present. */
718     if (((!hw->left && !hw->right && !hw->middle) &&
719         !(priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on)) ||
720         hw->z < para->finger_low) {
721         hw->cumulative_dx = hw->x;
722         hw->cumulative_dy = hw->y;
723         sync_cumulative = TRUE;
724     }
725 
726     while (SynapticsReadEvent(pInfo, &ev)) {
727         switch (ev.type) {
728         case EV_SYN:
729             switch (ev.code) {
730             case SYN_REPORT:
731                 hw->numFingers = count_fingers(pInfo, comm);
732                 if (proto_data->have_monotonic_clock)
733                     hw->millis = 1000 * ev.time.tv_sec + ev.time.tv_usec / 1000;
734                 else
735                     hw->millis = GetTimeInMillis();
736                 SynapticsCopyHwState(hwRet, hw);
737                 return TRUE;
738             }
739             break;
740         case EV_KEY:
741             /* ignore hw repeat events */
742             if (ev.value > 1)
743                 break;
744 
745             v = (ev.value ? TRUE : FALSE);
746             switch (ev.code) {
747             case BTN_LEFT:
748                 hw->left = v;
749                 break;
750             case BTN_RIGHT:
751                 hw->right = v;
752                 break;
753             case BTN_MIDDLE:
754                 hw->middle = v;
755                 break;
756             case BTN_FORWARD:
757                 hw->up = v;
758                 break;
759             case BTN_BACK:
760                 hw->down = v;
761                 break;
762             case BTN_0:
763                 hw->multi[0] = v;
764                 break;
765             case BTN_1:
766                 hw->multi[1] = v;
767                 break;
768             case BTN_2:
769                 hw->multi[2] = v;
770                 break;
771             case BTN_3:
772                 hw->multi[3] = v;
773                 break;
774             case BTN_4:
775                 hw->multi[4] = v;
776                 break;
777             case BTN_5:
778                 hw->multi[5] = v;
779                 break;
780             case BTN_6:
781                 hw->multi[6] = v;
782                 break;
783             case BTN_7:
784                 hw->multi[7] = v;
785                 break;
786             case BTN_TOOL_FINGER:
787                 comm->oneFinger = v;
788                 break;
789             case BTN_TOOL_DOUBLETAP:
790                 comm->twoFingers = v;
791                 break;
792             case BTN_TOOL_TRIPLETAP:
793                 comm->threeFingers = v;
794                 break;
795             case BTN_TOUCH:
796                 if (!priv->has_pressure)
797                     hw->z = v ? para->finger_high + 1 : 0;
798                 break;
799             }
800             break;
801         case EV_ABS:
802             if (ev.code < ABS_MT_SLOT) {
803                 switch (ev.code) {
804                 case ABS_X:
805                     hw->x = apply_st_scaling(proto_data, ev.value, 0);
806                     if (sync_cumulative)
807                         hw->cumulative_dx = hw->x;
808                     break;
809                 case ABS_Y:
810                     hw->y = apply_st_scaling(proto_data, ev.value, 1);
811                     if (sync_cumulative)
812                         hw->cumulative_dy = hw->y;
813                     break;
814                 case ABS_PRESSURE:
815                     hw->z = ev.value;
816                     break;
817                 case ABS_TOOL_WIDTH:
818                     hw->fingerWidth = ev.value;
819                     break;
820                 }
821             }
822             else
823                 EventProcessTouchEvent(pInfo, hw, &ev);
824             break;
825         }
826     }
827     return FALSE;
828 }
829 
830 /* filter for the AutoDevProbe scandir on /dev/input */
831 static int
EventDevOnly(const struct dirent * dir)832 EventDevOnly(const struct dirent *dir)
833 {
834     return strncmp(EVENT_DEV_NAME, dir->d_name, 5) == 0;
835 }
836 
837 static void
event_query_touch(InputInfoPtr pInfo)838 event_query_touch(InputInfoPtr pInfo)
839 {
840     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
841     SynapticsParameters *para = &priv->synpara;
842     struct eventcomm_proto_data *proto_data = priv->proto_data;
843     struct libevdev *dev = proto_data->evdev;
844     int axis;
845 
846     priv->max_touches = 0;
847     priv->num_mt_axes = 0;
848 
849 #ifdef EVIOCGPROP
850     if (libevdev_has_property(dev, INPUT_PROP_SEMI_MT)) {
851         xf86IDrvMsg(pInfo, X_INFO,
852                     "ignoring touch events for semi-multitouch device\n");
853         priv->has_semi_mt = TRUE;
854     }
855 
856     if (libevdev_has_property(dev, INPUT_PROP_BUTTONPAD)) {
857         xf86IDrvMsg(pInfo, X_INFO, "found clickpad property\n");
858         para->clickpad = TRUE;
859     }
860 
861     if (libevdev_has_property(dev, INPUT_PROP_TOPBUTTONPAD)) {
862         xf86IDrvMsg(pInfo, X_INFO, "found top buttonpad property\n");
863         para->has_secondary_buttons = TRUE;
864     }
865 #endif
866 
867 
868     if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT)) {
869         for (axis = ABS_MT_SLOT + 1; axis <= ABS_MT_MAX; axis++) {
870             if (!libevdev_has_event_code(dev, EV_ABS, axis))
871                 continue;
872 
873             priv->has_touch = TRUE;
874 
875             /* X and Y axis info is handled by synaptics already and we don't
876                expose the tracking ID */
877             if (axis == ABS_MT_POSITION_X ||
878                 axis == ABS_MT_POSITION_Y ||
879                 axis == ABS_MT_TRACKING_ID)
880                 continue;
881 
882             priv->num_mt_axes++;
883         }
884     }
885 
886     if (priv->has_touch) {
887         int axnum;
888 
889         static const char *labels[ABS_MT_MAX] = {
890             AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR,
891             AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR,
892             AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR,
893             AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR,
894             AXIS_LABEL_PROP_ABS_MT_ORIENTATION,
895             AXIS_LABEL_PROP_ABS_MT_POSITION_X,
896             AXIS_LABEL_PROP_ABS_MT_POSITION_Y,
897             AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE,
898             AXIS_LABEL_PROP_ABS_MT_BLOB_ID,
899             AXIS_LABEL_PROP_ABS_MT_TRACKING_ID,
900             AXIS_LABEL_PROP_ABS_MT_PRESSURE,
901             AXIS_LABEL_PROP_ABS_MT_DISTANCE,
902             AXIS_LABEL_PROP_ABS_MT_TOOL_X,
903             AXIS_LABEL_PROP_ABS_MT_TOOL_Y,
904         };
905 
906         priv->max_touches = libevdev_get_num_slots(dev);
907         priv->touch_axes = malloc(priv->num_mt_axes *
908                                   sizeof(SynapticsTouchAxisRec));
909         if (!priv->touch_axes) {
910             priv->has_touch = FALSE;
911             return;
912         }
913 
914         if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_TOUCH_MAJOR) &&
915             libevdev_has_event_code(dev, EV_ABS, ABS_MT_PRESSURE))
916             priv->has_mt_palm_detect = TRUE;
917 
918         axnum = 0;
919         for (axis = ABS_MT_SLOT + 1; axis <= ABS_MT_MAX; axis++) {
920             int axis_idx = axis - ABS_MT_TOUCH_MAJOR;
921 
922             if (!libevdev_has_event_code(dev, EV_ABS, axis))
923                 continue;
924 
925             switch (axis) {
926                 /* X and Y axis info is handled by synaptics already, we just
927                  * need to map the evdev codes to the valuator numbers */
928                 case ABS_MT_POSITION_X:
929                     proto_data->axis_map[axis_idx] = 0;
930                     break;
931 
932                 case ABS_MT_POSITION_Y:
933                     proto_data->axis_map[axis_idx] = 1;
934                     break;
935 
936                     /* Skip tracking ID info */
937                 case ABS_MT_TRACKING_ID:
938                     break;
939 
940                 default:
941                     if (axis_idx >= sizeof(labels)/sizeof(labels[0])) {
942                         xf86IDrvMsg(pInfo, X_ERROR,
943                                     "Axis %d out of label range. This is a bug\n",
944                                     axis);
945                         priv->touch_axes[axnum].label = NULL;
946                     } else
947                         priv->touch_axes[axnum].label = labels[axis_idx];
948                     priv->touch_axes[axnum].min = libevdev_get_abs_minimum(dev, axis);
949                     priv->touch_axes[axnum].max = libevdev_get_abs_maximum(dev, axis);
950                     /* Kernel provides units/mm, X wants units/m */
951                     priv->touch_axes[axnum].res = libevdev_get_abs_resolution(dev, axis) * 1000;
952                     /* Valuators 0-3 are used for X, Y, and scrolling */
953                     proto_data->axis_map[axis_idx] = 4 + axnum;
954                     axnum++;
955                     break;
956             }
957         }
958     }
959 }
960 
961 /**
962  * Probe the open device for dimensions.
963  */
964 static void
EventReadDevDimensions(InputInfoPtr pInfo)965 EventReadDevDimensions(InputInfoPtr pInfo)
966 {
967     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
968     struct eventcomm_proto_data *proto_data = priv->proto_data;
969     int i;
970 
971     proto_data = EventProtoDataAlloc(pInfo->fd);
972     priv->proto_data = proto_data;
973 
974     for (i = 0; i < ABS_MT_CNT; i++)
975         proto_data->axis_map[i] = -1;
976     proto_data->cur_slot = -1;
977 
978     if (event_query_is_touchpad(proto_data->evdev)) {
979         event_query_touch(pInfo);
980         event_query_axis_ranges(pInfo);
981     }
982     event_query_model(proto_data->evdev, &priv->model, &priv->id_vendor,
983                       &priv->id_product);
984 
985     xf86IDrvMsg(pInfo, X_PROBED, "Vendor %#hx Product %#hx\n",
986                 priv->id_vendor, priv->id_product);
987 }
988 
989 static Bool
EventAutoDevProbe(InputInfoPtr pInfo,const char * device)990 EventAutoDevProbe(InputInfoPtr pInfo, const char *device)
991 {
992     /* We are trying to find the right eventX device or fall back to
993        the psaux protocol and the given device from XF86Config */
994     int i;
995     Bool touchpad_found = FALSE;
996     struct dirent **namelist;
997 
998     if (device) {
999         int fd = -1;
1000 
1001         if (pInfo->flags & XI86_SERVER_FD)
1002             fd = pInfo->fd;
1003         else
1004             SYSCALL(fd = open(device, O_RDONLY));
1005 
1006         if (fd >= 0) {
1007             int rc;
1008             struct libevdev *evdev;
1009 
1010             rc = libevdev_new_from_fd(fd, &evdev);
1011             if (rc >= 0) {
1012                 touchpad_found = event_query_is_touchpad(evdev);
1013                 libevdev_free(evdev);
1014             }
1015 
1016             if (!(pInfo->flags & XI86_SERVER_FD))
1017                 SYSCALL(close(fd));
1018         }
1019 
1020         /* if a device is set and not a touchpad (or already grabbed),
1021          * we must return FALSE.  Otherwise, we'll add a device that
1022          * wasn't requested for and repeat
1023          * f5687a6741a19ef3081e7fd83ac55f6df8bcd5c2. */
1024         return touchpad_found;
1025     }
1026 
1027     i = scandir(DEV_INPUT_EVENT, &namelist, EventDevOnly, alphasort);
1028     if (i < 0) {
1029         xf86IDrvMsg(pInfo, X_ERROR, "Couldn't open %s\n", DEV_INPUT_EVENT);
1030         return FALSE;
1031     }
1032     else if (i == 0) {
1033         xf86IDrvMsg(pInfo, X_ERROR,
1034                     "The /dev/input/event* device nodes seem to be missing\n");
1035         free(namelist);
1036         return FALSE;
1037     }
1038 
1039     while (i--) {
1040         char fname[64];
1041         int fd = -1;
1042 
1043         if (!touchpad_found) {
1044             int rc;
1045             struct libevdev *evdev;
1046 
1047             sprintf(fname, "%s/%s", DEV_INPUT_EVENT, namelist[i]->d_name);
1048             SYSCALL(fd = open(fname, O_RDONLY));
1049             if (fd < 0)
1050                 continue;
1051 
1052             rc = libevdev_new_from_fd(fd, &evdev);
1053             if (rc >= 0) {
1054                 touchpad_found = event_query_is_touchpad(evdev);
1055                 libevdev_free(evdev);
1056                 if (touchpad_found) {
1057                     xf86IDrvMsg(pInfo, X_PROBED, "auto-dev sets device to %s\n",
1058                                 fname);
1059                     pInfo->options = xf86ReplaceStrOption(pInfo->options,
1060                                                           "Device",
1061                                                           fname);
1062                 }
1063             }
1064             SYSCALL(close(fd));
1065         }
1066         free(namelist[i]);
1067     }
1068 
1069     free(namelist);
1070 
1071     if (!touchpad_found) {
1072         xf86IDrvMsg(pInfo, X_ERROR, "no synaptics event device found\n");
1073         return FALSE;
1074     }
1075 
1076     return TRUE;
1077 }
1078 
1079 struct SynapticsProtocolOperations event_proto_operations = {
1080     EventDeviceOnHook,
1081     EventDeviceOffHook,
1082     EventQueryHardware,
1083     EventReadHwState,
1084     EventAutoDevProbe,
1085     EventReadDevDimensions
1086 };
1087