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