1 /*
2  * Copyright � 1999 Henry Davies
3  * Copyright � 2001 Stefan Gmeiner
4  * Copyright � 2002 S. Lehner
5  * Copyright � 2002 Peter Osterlund
6  * Copyright � 2002 Linuxcare Inc. David Kennedy
7  * Copyright � 2003 Hartwig Felger
8  * Copyright � 2003 J�rg B�sner
9  * Copyright � 2003 Fred Hucht
10  * Copyright � 2004 Alexei Gilchrist
11  * Copyright � 2004 Matthias Ihmig
12  * Copyright � 2006 Stefan Bethge
13  * Copyright � 2006 Christian Thaeter
14  * Copyright � 2007 Joseph P. Skudlarek
15  * Copyright � 2008 Fedor P. Goncharov
16  * Copyright � 2008-2012 Red Hat, Inc.
17  * Copyright � 2011 The Chromium OS Authors
18  *
19  * Permission to use, copy, modify, distribute, and sell this software
20  * and its documentation for any purpose is hereby granted without
21  * fee, provided that the above copyright notice appear in all copies
22  * and that both that copyright notice and this permission notice
23  * appear in supporting documentation, and that the name of Red Hat
24  * not be used in advertising or publicity pertaining to distribution
25  * of the software without specific, written prior permission.  Red
26  * Hat makes no representations about the suitability of this software
27  * for any purpose.  It is provided "as is" without express or implied
28  * warranty.
29  *
30  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
31  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
32  * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
33  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
34  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
35  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
36  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37  *
38  * Authors:
39  *      Joseph P. Skudlarek <Jskud@Jskud.com>
40  *      Christian Thaeter <chth@gmx.net>
41  *      Stefan Bethge <stefan.bethge@web.de>
42  *      Matthias Ihmig <m.ihmig@gmx.net>
43  *      Alexei Gilchrist <alexei@physics.uq.edu.au>
44  *      J�rg B�sner <ich@joerg-boesner.de>
45  *      Hartwig Felger <hgfelger@hgfelger.de>
46  *      Peter Osterlund <petero2@telia.com>
47  *      S. Lehner <sam_x@bluemail.ch>
48  *      Stefan Gmeiner <riddlebox@freesurf.ch>
49  *      Henry Davies <hdavies@ameritech.net> for the
50  *      Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com>
51  *      Fred Hucht <fred@thp.Uni-Duisburg.de>
52  *      Fedor P. Goncharov <fedgo@gorodok.net>
53  *      Simon Thum <simon.thum@gmx.de>
54  *
55  * Trademarks are the property of their respective owners.
56  */
57 
58 #ifdef HAVE_CONFIG_H
59 #include "config.h"
60 #endif
61 
62 #include <xorg-server.h>
63 #include <unistd.h>
64 #include <misc.h>
65 #include <xf86.h>
66 #include <math.h>
67 #include <stdio.h>
68 #include <xf86_OSproc.h>
69 #include <xf86Xinput.h>
70 #include <exevents.h>
71 
72 #include <X11/Xatom.h>
73 #include <X11/extensions/XI2.h>
74 #include <xserver-properties.h>
75 #include <ptrveloc.h>
76 
77 #include "synapticsstr.h"
78 #include "synaptics-properties.h"
79 
80 enum EdgeType {
81     NO_EDGE = 0,
82     BOTTOM_EDGE = 1,
83     TOP_EDGE = 2,
84     LEFT_EDGE = 4,
85     RIGHT_EDGE = 8,
86     LEFT_BOTTOM_EDGE = BOTTOM_EDGE | LEFT_EDGE,
87     RIGHT_BOTTOM_EDGE = BOTTOM_EDGE | RIGHT_EDGE,
88     RIGHT_TOP_EDGE = TOP_EDGE | RIGHT_EDGE,
89     LEFT_TOP_EDGE = TOP_EDGE | LEFT_EDGE
90 };
91 
92 /*
93  * We expect to be receiving a steady 80 packets/sec (which gives 40
94  * reports/sec with more than one finger on the pad, as Advanced Gesture Mode
95  * requires two PS/2 packets per report).  Instead of a random scattering of
96  * magic 13 and 20ms numbers scattered throughout the driver, introduce
97  * POLL_MS as 14ms, which is slightly less than 80Hz.  13ms is closer to
98  * 80Hz, but if the kernel event reporting was even slightly delayed,
99  * we would produce synthetic motion followed immediately by genuine
100  * motion, so use 14.
101  *
102  * We use this to call back at a constant rate to at least produce the
103  * illusion of smooth motion.  It works a lot better than you'd expect.
104 */
105 #define POLL_MS 14
106 
107 #define MAX(a, b) (((a)>(b))?(a):(b))
108 #define MIN(a, b) (((a)<(b))?(a):(b))
109 #define TIME_DIFF(a, b) ((int)((a)-(b)))
110 
111 #define SQR(x) ((x) * (x))
112 
113 #ifndef M_PI
114 #define M_PI 3.14159265358979323846
115 #endif
116 
117 #define INPUT_BUFFER_SIZE 200
118 
119 /*****************************************************************************
120  * Forward declaration
121  ****************************************************************************/
122 static int SynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
123 static void SynapticsUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
124 static Bool DeviceControl(DeviceIntPtr, int);
125 static void ReadInput(InputInfoPtr);
126 static int HandleState(InputInfoPtr, struct SynapticsHwState *, CARD32 now,
127                        Bool from_timer);
128 static int ControlProc(InputInfoPtr, xDeviceCtl *);
129 static int SwitchMode(ClientPtr, DeviceIntPtr, int);
130 static int DeviceInit(DeviceIntPtr);
131 static int DeviceOn(DeviceIntPtr);
132 static int DeviceOff(DeviceIntPtr);
133 static int DeviceClose(DeviceIntPtr);
134 static Bool QueryHardware(InputInfoPtr);
135 static void ReadDevDimensions(InputInfoPtr);
136 #ifndef NO_DRIVER_SCALING
137 static void ScaleCoordinates(SynapticsPrivate * priv,
138                              struct SynapticsHwState *hw);
139 static void CalculateScalingCoeffs(SynapticsPrivate * priv);
140 #endif
141 static void SanitizeDimensions(InputInfoPtr pInfo);
142 
143 void InitDeviceProperties(InputInfoPtr pInfo);
144 int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
145                 BOOL checkonly);
146 
147 const static struct {
148     const char *name;
149     struct SynapticsProtocolOperations *proto_ops;
150 } protocols[] = {
151 #ifdef BUILD_EVENTCOMM
152     { "event", &event_proto_operations },
153 #endif
154 #ifdef BUILD_PSMCOMM
155     { "psm", &psm_proto_operations },
156 #endif
157 #ifdef BUILD_PS2COMM
158     { "psaux", &psaux_proto_operations },
159     { "alps", &alps_proto_operations },
160 #endif
161     { NULL, NULL }
162 };
163 
164 InputDriverRec SYNAPTICS = {
165     1,
166     "synaptics",
167     NULL,
168     SynapticsPreInit,
169     SynapticsUnInit,
170     NULL,
171     NULL,
172 #ifdef XI86_DRV_CAP_SERVER_FD
173     XI86_DRV_CAP_SERVER_FD
174 #endif
175 };
176 
177 static XF86ModuleVersionInfo VersionRec = {
178     "synaptics",
179     MODULEVENDORSTRING,
180     MODINFOSTRING1,
181     MODINFOSTRING2,
182     XORG_VERSION_CURRENT,
183     PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
184     ABI_CLASS_XINPUT,
185     ABI_XINPUT_VERSION,
186     MOD_CLASS_XINPUT,
187     {0, 0, 0, 0}
188 };
189 
190 static pointer
SetupProc(pointer module,pointer options,int * errmaj,int * errmin)191 SetupProc(pointer module, pointer options, int *errmaj, int *errmin)
192 {
193     xf86AddInputDriver(&SYNAPTICS, module, 0);
194     return module;
195 }
196 
197 _X_EXPORT XF86ModuleData synapticsModuleData = {
198     &VersionRec,
199     &SetupProc,
200     NULL
201 };
202 
203 /*****************************************************************************
204  *	Function Definitions
205  ****************************************************************************/
206 static inline void
SynapticsCloseFd(InputInfoPtr pInfo)207 SynapticsCloseFd(InputInfoPtr pInfo)
208 {
209     if (pInfo->fd > -1 && !(pInfo->flags & XI86_SERVER_FD)) {
210         xf86CloseSerial(pInfo->fd);
211         pInfo->fd = -1;
212     }
213 }
214 
215 /**
216  * Fill in default dimensions for backends that cannot query the hardware.
217  * Eventually, we want the edges to be 1900/5400 for x, 1900/4000 for y.
218  * These values are based so that calculate_edge_widths() will give us the
219  * right values.
220  *
221  * The default values 1900, etc. come from the dawn of time, when men where
222  * men, or possibly apes.
223  */
224 static void
SanitizeDimensions(InputInfoPtr pInfo)225 SanitizeDimensions(InputInfoPtr pInfo)
226 {
227     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
228 
229     if (priv->minx >= priv->maxx) {
230         priv->minx = 1615;
231         priv->maxx = 5685;
232         priv->resx = 0;
233 
234         xf86IDrvMsg(pInfo, X_PROBED,
235                     "invalid x-axis range.  defaulting to %d - %d\n",
236                     priv->minx, priv->maxx);
237     }
238 
239     if (priv->miny >= priv->maxy) {
240         priv->miny = 1729;
241         priv->maxy = 4171;
242         priv->resy = 0;
243 
244         xf86IDrvMsg(pInfo, X_PROBED,
245                     "invalid y-axis range.  defaulting to %d - %d\n",
246                     priv->miny, priv->maxy);
247     }
248 
249     if (priv->minp >= priv->maxp) {
250         priv->minp = 0;
251         priv->maxp = 255;
252 
253         xf86IDrvMsg(pInfo, X_PROBED,
254                     "invalid pressure range.  defaulting to %d - %d\n",
255                     priv->minp, priv->maxp);
256     }
257 
258     if (priv->minw >= priv->maxw) {
259         priv->minw = 0;
260         priv->maxw = 15;
261 
262         xf86IDrvMsg(pInfo, X_PROBED,
263                     "invalid finger width range.  defaulting to %d - %d\n",
264                     priv->minw, priv->maxw);
265     }
266 }
267 
268 static Bool
SetDeviceAndProtocol(InputInfoPtr pInfo)269 SetDeviceAndProtocol(InputInfoPtr pInfo)
270 {
271     SynapticsPrivate *priv = pInfo->private;
272     char *proto, *device;
273     int i;
274 
275     proto = xf86SetStrOption(pInfo->options, "Protocol", NULL);
276     device = xf86SetStrOption(pInfo->options, "Device", NULL);
277 
278     /* If proto is auto-dev, unset and let the code do the rest */
279     if (proto && !strcmp(proto, "auto-dev")) {
280         free(proto);
281         proto = NULL;
282     }
283 
284     for (i = 0; protocols[i].name; i++) {
285         if ((!device || !proto) &&
286             protocols[i].proto_ops->AutoDevProbe &&
287             protocols[i].proto_ops->AutoDevProbe(pInfo, device))
288             break;
289         else if (proto && !strcmp(proto, protocols[i].name))
290             break;
291     }
292     free(proto);
293     free(device);
294 
295     priv->proto_ops = protocols[i].proto_ops;
296 
297     return (priv->proto_ops != NULL);
298 }
299 
300 static void
calculate_edge_widths(SynapticsPrivate * priv,int * l,int * r,int * t,int * b)301 calculate_edge_widths(SynapticsPrivate * priv, int *l, int *r, int *t, int *b)
302 {
303     int width, height;
304     int ewidth, eheight;        /* edge width/height */
305 
306     width = abs(priv->maxx - priv->minx);
307     height = abs(priv->maxy - priv->miny);
308 
309     if (priv->model == MODEL_SYNAPTICS) {
310         ewidth = width * .07;
311         eheight = height * .07;
312     }
313     else if (priv->model == MODEL_ALPS) {
314         ewidth = width * .15;
315         eheight = height * .15;
316     }
317     else if (priv->model == MODEL_APPLETOUCH ||
318              priv->model == MODEL_UNIBODY_MACBOOK) {
319         ewidth = width * .085;
320         eheight = height * .085;
321     }
322     else {
323         ewidth = width * .04;
324         eheight = height * .054;
325     }
326 
327     *l = priv->minx + ewidth;
328     *r = priv->maxx - ewidth;
329     *t = priv->miny + eheight;
330     *b = priv->maxy - eheight;
331 }
332 
333 static void
calculate_tap_hysteresis(SynapticsPrivate * priv,int range,int * fingerLow,int * fingerHigh)334 calculate_tap_hysteresis(SynapticsPrivate * priv, int range,
335                          int *fingerLow, int *fingerHigh)
336 {
337     switch (priv->model) {
338     case MODEL_ELANTECH:
339         /* All Elantech touchpads don't need the Z filtering to get the
340          * number of fingers correctly. See Documentation/elantech.txt
341          * in the kernel.
342          */
343         *fingerLow = priv->minp + 1;
344         *fingerHigh = priv->minp + 1;
345         break;
346     case MODEL_UNIBODY_MACBOOK:
347         *fingerLow = 70;
348         *fingerHigh = 75;
349         break;
350     default:
351         *fingerLow = priv->minp + range * (25.0 / 256);
352         *fingerHigh = priv->minp + range * (30.0 / 256);
353         break;
354     }
355 }
356 
357 /* Area options support both percent values and absolute values. This is
358  * awkward. The xf86Set* calls will print to the log, but they'll
359  * also print an error if we request a percent value but only have an
360  * int. So - check first for percent, then call xf86Set* again to get
361  * the log message.
362  */
363 static int
set_percent_option(pointer options,const char * optname,const int range,const int offset,const int default_value)364 set_percent_option(pointer options, const char *optname,
365                    const int range, const int offset, const int default_value)
366 {
367     int result;
368     double percent = xf86CheckPercentOption(options, optname, -1);
369 
370     if (percent >= 0.0) {
371         percent = xf86SetPercentOption(options, optname, -1);
372         result = percent / 100.0 * range + offset;
373     } else
374         result = xf86SetIntOption(options, optname, default_value);
375 
376     return result;
377 }
378 
379 Bool
SynapticsIsSoftButtonAreasValid(int * values)380 SynapticsIsSoftButtonAreasValid(int *values)
381 {
382     Bool right_disabled = FALSE;
383     Bool middle_disabled = FALSE;
384 
385     enum {
386         /* right button left, right, top, bottom */
387         RBL = 0,
388         RBR = 1,
389         RBT = 2,
390         RBB = 3,
391         /* middle button left, right, top, bottom */
392         MBL = 4,
393         MBR = 5,
394         MBT = 6,
395         MBB = 7,
396     };
397 
398     /* Check right button area */
399     if ((((values[RBL] != 0) && (values[RBR] != 0)) && (values[RBL] > values[RBR])) ||
400         (((values[RBT] != 0) && (values[RBB] != 0)) && (values[RBT] > values[RBB])))
401         return FALSE;
402 
403     /* Check middle button area */
404     if ((((values[MBL] != 0) && (values[MBR] != 0)) && (values[MBL] > values[MBR])) ||
405         (((values[MBT] != 0) && (values[MBB] != 0)) && (values[MBT] > values[MBB])))
406         return FALSE;
407 
408     if (values[RBL] == 0 && values[RBR] == 0 && values[RBT] == 0 && values[RBB] == 0)
409         right_disabled = TRUE;
410 
411     if (values[MBL] == 0 && values[MBR] == 0 && values[MBT] == 0 && values[MBB] == 0)
412         middle_disabled = TRUE;
413 
414     if (!right_disabled &&
415         ((values[RBL] && values[RBL] == values[RBR]) ||
416          (values[RBT] && values[RBT] == values[RBB])))
417         return FALSE;
418 
419     if (!middle_disabled &&
420         ((values[MBL] && values[MBL] == values[MBR]) ||
421          (values[MBT] && values[MBT] == values[MBB])))
422         return FALSE;
423 
424     /* Check for overlapping button areas */
425     if (!right_disabled && !middle_disabled) {
426         int right_left = values[RBL] ? values[RBL] : INT_MIN;
427         int right_right = values[RBR] ? values[RBR] : INT_MAX;
428         int right_top = values[RBT] ? values[RBT] : INT_MIN;
429         int right_bottom = values[RBB] ? values[RBB] : INT_MAX;
430         int middle_left = values[MBL] ? values[MBL] : INT_MIN;
431         int middle_right = values[MBR] ? values[MBR] : INT_MAX;
432         int middle_top = values[MBT] ? values[MBT] : INT_MIN;
433         int middle_bottom = values[MBB] ? values[MBB] : INT_MAX;
434 
435         /* If areas overlap in the Y axis */
436         if ((right_bottom <= middle_bottom && right_bottom >= middle_top) ||
437             (right_top <= middle_bottom && right_top >= middle_top)) {
438             /* Check for overlapping left edges */
439             if ((right_left < middle_left && right_right > middle_left) ||
440                 (middle_left < right_left && middle_right > right_left))
441                 return FALSE;
442 
443             /* Check for overlapping right edges */
444             if ((right_right > middle_right && right_left < middle_right) ||
445                 (middle_right > right_right && middle_left < right_right))
446                 return FALSE;
447         }
448 
449         /* If areas overlap in the X axis */
450         if ((right_left >= middle_left && right_left <= middle_right) ||
451             (right_right >= middle_left && right_right <= middle_right)) {
452             /* Check for overlapping top edges */
453             if ((right_top < middle_top && right_bottom > middle_top) ||
454                 (middle_top < right_top && middle_bottom > right_top))
455                 return FALSE;
456 
457             /* Check for overlapping bottom edges */
458             if ((right_bottom > middle_bottom && right_top < middle_bottom) ||
459                 (middle_bottom > right_bottom && middle_top < right_bottom))
460                 return FALSE;
461         }
462     }
463 
464     return TRUE;
465 }
466 
467 static void
set_softbutton_areas_option(InputInfoPtr pInfo,char * option_name,int offset)468 set_softbutton_areas_option(InputInfoPtr pInfo, char *option_name, int offset)
469 {
470     SynapticsPrivate *priv = pInfo->private;
471     SynapticsParameters *pars = &priv->synpara;
472     int values[8];
473     int in_percent = 0;         /* bitmask for which ones are in % */
474     char *option_string;
475     char *next_num;
476     char *end_str;
477     int i;
478     int width, height;
479 
480     if (!pars->clickpad)
481         return;
482 
483     option_string = xf86SetStrOption(pInfo->options, option_name, NULL);
484     if (!option_string)
485         return;
486 
487     next_num = option_string;
488 
489     for (i = 0; i < 8 && *next_num != '\0'; i++) {
490         long int value = strtol(next_num, &end_str, 0);
491 
492         if (value > INT_MAX || value < -INT_MAX)
493             goto fail;
494 
495         values[i] = value;
496 
497         if (next_num != end_str) {
498             if (*end_str == '%') {
499                 in_percent |= 1 << i;
500                 end_str++;
501             }
502             next_num = end_str;
503         }
504         else
505             goto fail;
506     }
507 
508     if (i < 8 || *next_num != '\0')
509         goto fail;
510 
511     width = priv->maxx - priv->minx;
512     height = priv->maxy - priv->miny;
513 
514     for (i = 0; in_percent && i < 8; i++) {
515         int base, size;
516 
517         if ((in_percent & (1 << i)) == 0 || values[i] == 0)
518             continue;
519 
520         size = ((i % 4) < 2) ? width : height;
521         base = ((i % 4) < 2) ? priv->minx : priv->miny;
522         values[i] = base + size * values[i] / 100.0;
523     }
524 
525     if (!SynapticsIsSoftButtonAreasValid(values))
526         goto fail;
527 
528     memcpy(pars->softbutton_areas[offset], values, 4 * sizeof(int));
529     memcpy(pars->softbutton_areas[offset + 1], values + 4, 4 * sizeof(int));
530 
531     free(option_string);
532 
533     return;
534 
535  fail:
536     xf86IDrvMsg(pInfo, X_ERROR,
537                 "invalid %s value '%s', keeping defaults\n",
538                 option_name, option_string);
539     free(option_string);
540 }
541 
542 static void
set_primary_softbutton_areas_option(InputInfoPtr pInfo)543 set_primary_softbutton_areas_option(InputInfoPtr pInfo)
544 {
545     set_softbutton_areas_option(pInfo, "SoftButtonAreas", BOTTOM_BUTTON_AREA);
546 }
547 
548 static void
set_secondary_softbutton_areas_option(InputInfoPtr pInfo)549 set_secondary_softbutton_areas_option(InputInfoPtr pInfo)
550 {
551     set_softbutton_areas_option(pInfo, "SecondarySoftButtonAreas", TOP_BUTTON_AREA);
552 }
553 
554 static void
set_default_parameters(InputInfoPtr pInfo)555 set_default_parameters(InputInfoPtr pInfo)
556 {
557     SynapticsPrivate *priv = pInfo->private;    /* read-only */
558     pointer opts = pInfo->options;      /* read-only */
559     SynapticsParameters *pars = &priv->synpara; /* modified */
560 
561     int horizScrollDelta, vertScrollDelta;      /* pixels */
562     int tapMove;                /* pixels */
563     int l, r, t, b;             /* left, right, top, bottom */
564     double accelFactor;         /* 1/pixels */
565     int fingerLow, fingerHigh;  /* pressure */
566     int emulateTwoFingerMinZ;   /* pressure */
567     int emulateTwoFingerMinW;   /* width */
568     int pressureMotionMinZ, pressureMotionMaxZ; /* pressure */
569     int palmMinWidth, palmMinZ; /* pressure */
570     int tapButton1, tapButton2, tapButton3;
571     int clickFinger1, clickFinger2, clickFinger3;
572     Bool vertEdgeScroll, horizEdgeScroll;
573     Bool vertTwoFingerScroll, horizTwoFingerScroll;
574     int horizResolution = 1;
575     int vertResolution = 1;
576     int width, height, diag, range;
577     int horizHyst, vertHyst;
578     int middle_button_timeout;
579     int grab_event_device = 0;
580     const char *source;
581 
582     /* The synaptics specs specify typical edge widths of 4% on x, and 5.4% on
583      * y (page 7) [Synaptics TouchPad Interfacing Guide, 510-000080 - A
584      * Second Edition, http://www.synaptics.com/support/dev_support.cfm, 8 Sep
585      * 2008]. We use 7% for both instead for synaptics devices, and 15% for
586      * ALPS models.
587      * http://bugs.freedesktop.org/show_bug.cgi?id=21214
588      *
589      * If the range was autodetected, apply these edge widths to all four
590      * sides.
591      */
592 
593     width = abs(priv->maxx - priv->minx);
594     height = abs(priv->maxy - priv->miny);
595     diag = sqrt(width * width + height * height);
596 
597     calculate_edge_widths(priv, &l, &r, &t, &b);
598 
599     /* Again, based on typical x/y range and defaults */
600     horizScrollDelta = diag * .020;
601     vertScrollDelta = diag * .020;
602     tapMove = diag * .044;
603     accelFactor = 200.0 / diag; /* trial-and-error */
604 
605     /* hysteresis, assume >= 0 is a detected value (e.g. evdev fuzz) */
606     horizHyst = pars->hyst_x >= 0 ? pars->hyst_x : diag * 0.005;
607     vertHyst = pars->hyst_y >= 0 ? pars->hyst_y : diag * 0.005;
608 
609     range = priv->maxp - priv->minp + 1;
610 
611     calculate_tap_hysteresis(priv, range, &fingerLow, &fingerHigh);
612 
613     /* scaling based on defaults and a pressure of 256 */
614     emulateTwoFingerMinZ = priv->minp + range * (282.0 / 256);
615     pressureMotionMinZ = priv->minp + range * (30.0 / 256);
616     pressureMotionMaxZ = priv->minp + range * (160.0 / 256);
617     palmMinZ = priv->minp + range * (200.0 / 256);
618 
619     range = priv->maxw - priv->minw + 1;
620 
621     /* scaling based on defaults below and a tool width of 16 */
622     palmMinWidth = priv->minw + range * (10.0 / 16);
623     emulateTwoFingerMinW = priv->minw + range * (7.0 / 16);
624 
625     /* Enable tap if we don't have a phys left button */
626     tapButton1 = priv->has_left ? 0 : 1;
627     tapButton2 = priv->has_left ? 0 : 3;
628     tapButton3 = priv->has_left ? 0 : 2;
629 
630     /* Enable multifinger-click if only have one physical button,
631        otherwise clickFinger is always button 1. */
632     clickFinger1 = 1;
633     clickFinger2 = (priv->has_right || priv->has_middle) ? 1 : 3;
634     clickFinger3 = (priv->has_right || priv->has_middle) ? 1 : 2;
635 
636     /* Enable vert edge scroll if we can't detect doubletap */
637     vertEdgeScroll = priv->has_double ? FALSE : TRUE;
638     horizEdgeScroll = FALSE;
639 
640     /* Enable twofinger scroll if we can detect doubletap */
641     vertTwoFingerScroll = priv->has_double ? TRUE : FALSE;
642     horizTwoFingerScroll = FALSE;
643 
644     /* Use resolution reported by hardware if available */
645     if ((priv->resx > 0) && (priv->resy > 0)) {
646         horizResolution = priv->resx;
647         vertResolution = priv->resy;
648     }
649 
650     /* set the parameters */
651     pars->left_edge = xf86SetIntOption(opts, "LeftEdge", l);
652     pars->right_edge = xf86SetIntOption(opts, "RightEdge", r);
653     pars->top_edge = xf86SetIntOption(opts, "TopEdge", t);
654     pars->bottom_edge = xf86SetIntOption(opts, "BottomEdge", b);
655 
656     pars->area_top_edge =
657         set_percent_option(opts, "AreaTopEdge", height, priv->miny, 0);
658     pars->area_bottom_edge =
659         set_percent_option(opts, "AreaBottomEdge", height, priv->miny, 0);
660     pars->area_left_edge =
661         set_percent_option(opts, "AreaLeftEdge", width, priv->minx, 0);
662     pars->area_right_edge =
663         set_percent_option(opts, "AreaRightEdge", width, priv->minx, 0);
664 
665     pars->hyst_x =
666         set_percent_option(opts, "HorizHysteresis", width, 0, horizHyst);
667     pars->hyst_y =
668         set_percent_option(opts, "VertHysteresis", height, 0, vertHyst);
669 
670     pars->finger_low = xf86SetIntOption(opts, "FingerLow", fingerLow);
671     pars->finger_high = xf86SetIntOption(opts, "FingerHigh", fingerHigh);
672     pars->tap_time = xf86SetIntOption(opts, "MaxTapTime", 180);
673     pars->tap_move = xf86SetIntOption(opts, "MaxTapMove", tapMove);
674     pars->tap_time_2 = xf86SetIntOption(opts, "MaxDoubleTapTime", 180);
675     pars->click_time = xf86SetIntOption(opts, "ClickTime", 100);
676     pars->clickpad = xf86SetBoolOption(opts, "ClickPad", pars->clickpad);       /* Probed */
677     if (pars->clickpad)
678         pars->has_secondary_buttons = xf86SetBoolOption(opts,
679                                                         "HasSecondarySoftButtons",
680                                                         pars->has_secondary_buttons);
681     pars->clickpad_ignore_motion_time = 100; /* ms */
682     /* middle mouse button emulation on a clickpad? nah, you're joking */
683     middle_button_timeout = pars->clickpad ? 0 : 75;
684     pars->emulate_mid_button_time =
685         xf86SetIntOption(opts, "EmulateMidButtonTime", middle_button_timeout);
686     pars->emulate_twofinger_z =
687         xf86SetIntOption(opts, "EmulateTwoFingerMinZ", emulateTwoFingerMinZ);
688     pars->emulate_twofinger_w =
689         xf86SetIntOption(opts, "EmulateTwoFingerMinW", emulateTwoFingerMinW);
690     pars->scroll_dist_vert =
691         xf86SetIntOption(opts, "VertScrollDelta", vertScrollDelta);
692     pars->scroll_dist_horiz =
693         xf86SetIntOption(opts, "HorizScrollDelta", horizScrollDelta);
694     pars->scroll_edge_vert =
695         xf86SetBoolOption(opts, "VertEdgeScroll", vertEdgeScroll);
696     pars->scroll_edge_horiz =
697         xf86SetBoolOption(opts, "HorizEdgeScroll", horizEdgeScroll);
698     pars->scroll_edge_corner = xf86SetBoolOption(opts, "CornerCoasting", FALSE);
699     pars->scroll_twofinger_vert =
700         xf86SetBoolOption(opts, "VertTwoFingerScroll", vertTwoFingerScroll);
701     pars->scroll_twofinger_horiz =
702         xf86SetBoolOption(opts, "HorizTwoFingerScroll", horizTwoFingerScroll);
703     pars->touchpad_off = xf86SetIntOption(opts, "TouchpadOff", TOUCHPAD_ON);
704 
705     if (priv->has_scrollbuttons) {
706         pars->updown_button_scrolling =
707             xf86SetBoolOption(opts, "UpDownScrolling", TRUE);
708         pars->leftright_button_scrolling =
709             xf86SetBoolOption(opts, "LeftRightScrolling", TRUE);
710         pars->updown_button_repeat =
711             xf86SetBoolOption(opts, "UpDownScrollRepeat", TRUE);
712         pars->leftright_button_repeat =
713             xf86SetBoolOption(opts, "LeftRightScrollRepeat", TRUE);
714     }
715     pars->scroll_button_repeat =
716         xf86SetIntOption(opts, "ScrollButtonRepeat", 100);
717 
718     pars->locked_drags = xf86SetBoolOption(opts, "LockedDrags", FALSE);
719     pars->locked_drag_time = xf86SetIntOption(opts, "LockedDragTimeout", 5000);
720     pars->tap_action[RT_TAP] = xf86SetIntOption(opts, "RTCornerButton", 0);
721     pars->tap_action[RB_TAP] = xf86SetIntOption(opts, "RBCornerButton", 0);
722     pars->tap_action[LT_TAP] = xf86SetIntOption(opts, "LTCornerButton", 0);
723     pars->tap_action[LB_TAP] = xf86SetIntOption(opts, "LBCornerButton", 0);
724     pars->tap_action[F1_TAP] = xf86SetIntOption(opts, "TapButton1", tapButton1);
725     pars->tap_action[F2_TAP] = xf86SetIntOption(opts, "TapButton2", tapButton2);
726     pars->tap_action[F3_TAP] = xf86SetIntOption(opts, "TapButton3", tapButton3);
727     pars->click_action[F1_CLICK1] =
728         xf86SetIntOption(opts, "ClickFinger1", clickFinger1);
729     pars->click_action[F2_CLICK1] =
730         xf86SetIntOption(opts, "ClickFinger2", clickFinger2);
731     pars->click_action[F3_CLICK1] =
732         xf86SetIntOption(opts, "ClickFinger3", clickFinger3);
733     pars->circular_scrolling =
734         xf86SetBoolOption(opts, "CircularScrolling", FALSE);
735     pars->circular_trigger = xf86SetIntOption(opts, "CircScrollTrigger", 0);
736     pars->circular_pad = xf86SetBoolOption(opts, "CircularPad", FALSE);
737     pars->palm_detect = xf86SetBoolOption(opts, "PalmDetect", FALSE);
738     pars->palm_min_width = xf86SetIntOption(opts, "PalmMinWidth", palmMinWidth);
739     pars->palm_min_z = xf86SetIntOption(opts, "PalmMinZ", palmMinZ);
740     pars->single_tap_timeout = xf86SetIntOption(opts, "SingleTapTimeout", 180);
741     pars->press_motion_min_z =
742         xf86SetIntOption(opts, "PressureMotionMinZ", pressureMotionMinZ);
743     pars->press_motion_max_z =
744         xf86SetIntOption(opts, "PressureMotionMaxZ", pressureMotionMaxZ);
745 
746     pars->min_speed = xf86SetRealOption(opts, "MinSpeed", 0.4);
747     pars->max_speed = xf86SetRealOption(opts, "MaxSpeed", 0.7);
748     pars->accl = xf86SetRealOption(opts, "AccelFactor", accelFactor);
749     pars->scroll_dist_circ = xf86SetRealOption(opts, "CircScrollDelta", 0.1);
750     pars->coasting_speed = xf86SetRealOption(opts, "CoastingSpeed", 20.0);
751     pars->coasting_friction = xf86SetRealOption(opts, "CoastingFriction", 50);
752     pars->press_motion_min_factor =
753         xf86SetRealOption(opts, "PressureMotionMinFactor", 1.0);
754     pars->press_motion_max_factor =
755         xf86SetRealOption(opts, "PressureMotionMaxFactor", 1.0);
756 
757     /* Only grab the device by default if it's not coming from a config
758        backend. This way we avoid the device being added twice and sending
759        duplicate events.
760       */
761     source = xf86CheckStrOption(opts, "_source", NULL);
762     if (source == NULL || strncmp(source, "server/", 7) != 0)
763         grab_event_device = TRUE;
764     pars->grab_event_device = xf86SetBoolOption(opts, "GrabEventDevice", grab_event_device);
765 
766     pars->tap_and_drag_gesture =
767         xf86SetBoolOption(opts, "TapAndDragGesture", TRUE);
768     pars->resolution_horiz =
769         xf86SetIntOption(opts, "HorizResolution", horizResolution);
770     pars->resolution_vert =
771         xf86SetIntOption(opts, "VertResolution", vertResolution);
772     if (pars->resolution_horiz <= 0) {
773         xf86IDrvMsg(pInfo, X_ERROR,
774                     "Invalid X resolution, using 1 instead.\n");
775         pars->resolution_horiz = 1;
776     }
777     if (pars->resolution_vert <= 0) {
778         xf86IDrvMsg(pInfo, X_ERROR,
779                     "Invalid Y resolution, using 1 instead.\n");
780         pars->resolution_vert = 1;
781     }
782 
783     /* Touchpad sampling rate is too low to detect all movements.
784        A user may lift one finger and put another one down within the same
785        EV_SYN or even between samplings so the driver doesn't notice at all.
786 
787        We limit the movement to 20 mm within one event, that is more than
788        recordings showed is needed (17mm on a T440).
789       */
790     if (pars->resolution_horiz > 1 &&
791         pars->resolution_vert > 1)
792         pars->maxDeltaMM = 20;
793     else {
794         /* on devices without resolution set the vector length to 0.25 of
795            the touchpad diagonal */
796         pars->maxDeltaMM = diag * 0.25;
797     }
798 
799 
800     /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
801     if (pars->top_edge > pars->bottom_edge) {
802         int tmp = pars->top_edge;
803 
804         pars->top_edge = pars->bottom_edge;
805         pars->bottom_edge = tmp;
806         xf86IDrvMsg(pInfo, X_WARNING,
807                     "TopEdge is bigger than BottomEdge. Fixing.\n");
808     }
809 
810     set_primary_softbutton_areas_option(pInfo);
811     if (pars->has_secondary_buttons)
812         set_secondary_softbutton_areas_option(pInfo);
813 }
814 
815 static double
SynapticsAccelerationProfile(DeviceIntPtr dev,DeviceVelocityPtr vel,double velocity,double thr,double acc)816 SynapticsAccelerationProfile(DeviceIntPtr dev,
817                              DeviceVelocityPtr vel,
818                              double velocity, double thr, double acc)
819 {
820     InputInfoPtr pInfo = dev->public.devicePrivate;
821     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
822     SynapticsParameters *para = &priv->synpara;
823 
824     double accelfct;
825 
826     /*
827      * synaptics accel was originally base on device coordinate based
828      * velocity, which we recover this way so para->accl retains its scale.
829      */
830     velocity /= vel->const_acceleration;
831 
832     /* speed up linear with finger velocity */
833     accelfct = velocity * para->accl;
834 
835     /* clip acceleration factor */
836     if (accelfct > para->max_speed * acc)
837         accelfct = para->max_speed * acc;
838     else if (accelfct < para->min_speed)
839         accelfct = para->min_speed;
840 
841     /* modify speed according to pressure */
842     if (priv->moving_state == MS_TOUCHPAD_RELATIVE) {
843         int minZ = para->press_motion_min_z;
844         int maxZ = para->press_motion_max_z;
845         double minFctr = para->press_motion_min_factor;
846         double maxFctr = para->press_motion_max_factor;
847 
848         if (priv->hwState->z <= minZ) {
849             accelfct *= minFctr;
850         }
851         else if (priv->hwState->z >= maxZ) {
852             accelfct *= maxFctr;
853         }
854         else {
855             accelfct *=
856                 minFctr + (priv->hwState->z - minZ) * (maxFctr -
857                                                        minFctr) / (maxZ - minZ);
858         }
859     }
860 
861     return accelfct;
862 }
863 
864 static int
SynapticsPreInit(InputDriverPtr drv,InputInfoPtr pInfo,int flags)865 SynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
866 {
867     SynapticsPrivate *priv;
868 
869     /* allocate memory for SynapticsPrivateRec */
870     priv = calloc(1, sizeof(SynapticsPrivate));
871     if (!priv)
872         return BadAlloc;
873 
874     pInfo->type_name = XI_TOUCHPAD;
875     pInfo->device_control = DeviceControl;
876     pInfo->read_input = ReadInput;
877     pInfo->control_proc = ControlProc;
878     pInfo->switch_mode = SwitchMode;
879     pInfo->private = priv;
880 
881     /* allocate now so we don't allocate in the signal handler */
882     priv->timer = TimerSet(NULL, 0, 0, NULL, NULL);
883     if (!priv->timer) {
884         free(priv);
885         return BadAlloc;
886     }
887 
888     /* may change pInfo->options */
889     if (!SetDeviceAndProtocol(pInfo)) {
890         xf86IDrvMsg(pInfo, X_ERROR,
891                     "Synaptics driver unable to detect protocol\n");
892         goto SetupProc_fail;
893     }
894 
895     priv->device = xf86FindOptionValue(pInfo->options, "Device");
896 
897     /* open the touchpad device */
898     pInfo->fd = xf86OpenSerial(pInfo->options);
899     if (pInfo->fd == -1) {
900         xf86IDrvMsg(pInfo, X_ERROR, "Synaptics driver unable to open device\n");
901         goto SetupProc_fail;
902     }
903     xf86ErrorFVerb(6, "port opened successfully\n");
904 
905     /* initialize variables */
906     priv->repeatButtons = 0;
907     priv->nextRepeat = 0;
908     priv->count_packet_finger = 0;
909     priv->tap_state = TS_START;
910     priv->tap_button = 0;
911     priv->tap_button_state = TBS_BUTTON_UP;
912     priv->touch_on.millis = 0;
913     priv->synpara.hyst_x = -1;
914     priv->synpara.hyst_y = -1;
915 
916     /* read hardware dimensions */
917     ReadDevDimensions(pInfo);
918 
919     set_default_parameters(pInfo);
920 
921 #ifndef NO_DRIVER_SCALING
922     CalculateScalingCoeffs(priv);
923 #endif
924 
925 
926     priv->comm.buffer = XisbNew(pInfo->fd, INPUT_BUFFER_SIZE);
927 
928     if (!QueryHardware(pInfo)) {
929         xf86IDrvMsg(pInfo, X_ERROR,
930                     "Unable to query/initialize Synaptics hardware.\n");
931         goto SetupProc_fail;
932     }
933 
934     xf86ProcessCommonOptions(pInfo, pInfo->options);
935 
936     if (priv->comm.buffer) {
937         XisbFree(priv->comm.buffer);
938         priv->comm.buffer = NULL;
939     }
940     SynapticsCloseFd(pInfo);
941 
942     return Success;
943 
944  SetupProc_fail:
945     SynapticsCloseFd(pInfo);
946 
947     if (priv->comm.buffer)
948         XisbFree(priv->comm.buffer);
949     free(priv->proto_data);
950     free(priv->timer);
951     free(priv);
952     pInfo->private = NULL;
953     return BadAlloc;
954 }
955 
956 /*
957  *  Uninitialize the device.
958  */
959 static void
SynapticsUnInit(InputDriverPtr drv,InputInfoPtr pInfo,int flags)960 SynapticsUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
961 {
962     SynapticsPrivate *priv = ((SynapticsPrivate *) pInfo->private);
963 
964     if (priv && priv->timer)
965         free(priv->timer);
966     if (priv && priv->proto_data)
967         free(priv->proto_data);
968     if (priv && priv->scroll_events_mask)
969         valuator_mask_free(&priv->scroll_events_mask);
970     if (priv && priv->open_slots)
971         free(priv->open_slots);
972     free(pInfo->private);
973     pInfo->private = NULL;
974     xf86DeleteInput(pInfo, 0);
975 }
976 
977 /*
978  *  Alter the control parameters for the mouse. Note that all special
979  *  protocol values are handled by dix.
980  */
981 static void
SynapticsCtrl(DeviceIntPtr device,PtrCtrl * ctrl)982 SynapticsCtrl(DeviceIntPtr device, PtrCtrl * ctrl)
983 {
984 }
985 
986 static int
DeviceControl(DeviceIntPtr dev,int mode)987 DeviceControl(DeviceIntPtr dev, int mode)
988 {
989     Bool RetValue;
990 
991     switch (mode) {
992     case DEVICE_INIT:
993         RetValue = DeviceInit(dev);
994         break;
995     case DEVICE_ON:
996         RetValue = DeviceOn(dev);
997         break;
998     case DEVICE_OFF:
999         RetValue = DeviceOff(dev);
1000         break;
1001     case DEVICE_CLOSE:
1002         RetValue = DeviceClose(dev);
1003         break;
1004     default:
1005         RetValue = BadValue;
1006     }
1007 
1008     return RetValue;
1009 }
1010 
1011 static int
DeviceOn(DeviceIntPtr dev)1012 DeviceOn(DeviceIntPtr dev)
1013 {
1014     InputInfoPtr pInfo = dev->public.devicePrivate;
1015     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
1016 
1017     DBG(3, "Synaptics DeviceOn called\n");
1018 
1019     pInfo->fd = xf86OpenSerial(pInfo->options);
1020     if (pInfo->fd == -1) {
1021         xf86IDrvMsg(pInfo, X_WARNING, "cannot open input device\n");
1022         return !Success;
1023     }
1024 
1025     if (priv->proto_ops->DeviceOnHook &&
1026         !priv->proto_ops->DeviceOnHook(pInfo, &priv->synpara))
1027          goto error;
1028 
1029     priv->comm.buffer = XisbNew(pInfo->fd, INPUT_BUFFER_SIZE);
1030     if (!priv->comm.buffer)
1031         goto error;
1032 
1033     xf86FlushInput(pInfo->fd);
1034 
1035     /* reinit the pad */
1036     if (!QueryHardware(pInfo))
1037         goto error;
1038 
1039     xf86AddEnabledDevice(pInfo);
1040     dev->public.on = TRUE;
1041 
1042     return Success;
1043 
1044 error:
1045     if (priv->comm.buffer) {
1046         XisbFree(priv->comm.buffer);
1047         priv->comm.buffer = NULL;
1048     }
1049     SynapticsCloseFd(pInfo);
1050     return !Success;
1051 }
1052 
1053 static void
SynapticsReset(SynapticsPrivate * priv)1054 SynapticsReset(SynapticsPrivate * priv)
1055 {
1056     int i;
1057 
1058     SynapticsResetHwState(priv->hwState);
1059     SynapticsResetHwState(priv->local_hw_state);
1060     SynapticsResetHwState(priv->comm.hwState);
1061 
1062     memset(priv->move_hist, 0, sizeof(priv->move_hist));
1063     priv->hyst_center_x = 0;
1064     priv->hyst_center_y = 0;
1065     memset(&priv->scroll, 0, sizeof(priv->scroll));
1066     priv->count_packet_finger = 0;
1067     priv->finger_state = FS_UNTOUCHED;
1068     priv->last_motion_millis = 0;
1069     priv->clickpad_click_millis = 0;
1070     priv->last_button_area = NO_BUTTON_AREA;
1071     priv->tap_state = TS_START;
1072     priv->tap_button = 0;
1073     priv->tap_button_state = TBS_BUTTON_UP;
1074     priv->moving_state = MS_FALSE;
1075     priv->vert_scroll_edge_on = FALSE;
1076     priv->horiz_scroll_edge_on = FALSE;
1077     priv->vert_scroll_twofinger_on = FALSE;
1078     priv->horiz_scroll_twofinger_on = FALSE;
1079     priv->circ_scroll_on = FALSE;
1080     priv->circ_scroll_vert = FALSE;
1081     priv->mid_emu_state = MBE_OFF;
1082     priv->nextRepeat = 0;
1083     priv->lastButtons = 0;
1084     priv->prev_z = 0;
1085     priv->prevFingers = 0;
1086     priv->num_active_touches = 0;
1087 
1088     for (i = 0; i < priv->num_slots; i++)
1089         priv->open_slots[i] = -1;
1090 }
1091 
1092 static int
DeviceOff(DeviceIntPtr dev)1093 DeviceOff(DeviceIntPtr dev)
1094 {
1095     InputInfoPtr pInfo = dev->public.devicePrivate;
1096     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
1097     Bool rc = Success;
1098 
1099     DBG(3, "Synaptics DeviceOff called\n");
1100 
1101     if (pInfo->fd != -1) {
1102         TimerCancel(priv->timer);
1103         xf86RemoveEnabledDevice(pInfo);
1104         SynapticsReset(priv);
1105 
1106         if (priv->proto_ops->DeviceOffHook &&
1107             !priv->proto_ops->DeviceOffHook(pInfo))
1108             rc = !Success;
1109         if (priv->comm.buffer) {
1110             XisbFree(priv->comm.buffer);
1111             priv->comm.buffer = NULL;
1112         }
1113         SynapticsCloseFd(pInfo);
1114     }
1115     dev->public.on = FALSE;
1116     return rc;
1117 }
1118 
1119 static int
DeviceClose(DeviceIntPtr dev)1120 DeviceClose(DeviceIntPtr dev)
1121 {
1122     Bool RetValue;
1123     InputInfoPtr pInfo = dev->public.devicePrivate;
1124     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
1125 
1126     RetValue = DeviceOff(dev);
1127     TimerFree(priv->timer);
1128     priv->timer = NULL;
1129     free(priv->touch_axes);
1130     priv->touch_axes = NULL;
1131     SynapticsHwStateFree(&priv->hwState);
1132     SynapticsHwStateFree(&priv->local_hw_state);
1133     SynapticsHwStateFree(&priv->comm.hwState);
1134     return RetValue;
1135 }
1136 
1137 static void
InitAxesLabels(Atom * labels,int nlabels,const SynapticsPrivate * priv)1138 InitAxesLabels(Atom *labels, int nlabels, const SynapticsPrivate * priv)
1139 {
1140     int i;
1141 
1142     memset(labels, 0, nlabels * sizeof(Atom));
1143     switch (nlabels) {
1144     default:
1145     case 4:
1146         labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
1147     case 3:
1148         labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
1149     case 2:
1150         labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
1151     case 1:
1152         labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
1153         break;
1154     }
1155 
1156     for (i = 0; i < priv->num_mt_axes; i++) {
1157         SynapticsTouchAxisRec *axis = &priv->touch_axes[i];
1158         int axnum = nlabels - priv->num_mt_axes + i;
1159 
1160         labels[axnum] = XIGetKnownProperty(axis->label);
1161     }
1162 }
1163 
1164 static void
InitButtonLabels(Atom * labels,int nlabels)1165 InitButtonLabels(Atom *labels, int nlabels)
1166 {
1167     memset(labels, 0, nlabels * sizeof(Atom));
1168     switch (nlabels) {
1169     default:
1170     case 7:
1171         labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
1172     case 6:
1173         labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
1174     case 5:
1175         labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
1176     case 4:
1177         labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
1178     case 3:
1179         labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
1180     case 2:
1181         labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
1182     case 1:
1183         labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
1184         break;
1185     }
1186 }
1187 
1188 static void
DeviceInitTouch(DeviceIntPtr dev,Atom * axes_labels)1189 DeviceInitTouch(DeviceIntPtr dev, Atom *axes_labels)
1190 {
1191     InputInfoPtr pInfo = dev->public.devicePrivate;
1192     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
1193 
1194     if (!priv->has_touch)
1195         return;
1196 
1197     priv->num_slots =
1198         priv->max_touches ? priv->max_touches : SYNAPTICS_MAX_TOUCHES;
1199 
1200     priv->open_slots = malloc(priv->num_slots * sizeof(int));
1201     if (!priv->open_slots) {
1202         xf86IDrvMsg(pInfo, X_ERROR,
1203                     "failed to allocate open touch slots array\n");
1204         priv->has_touch = 0;
1205         priv->num_slots = 0;
1206     }
1207 }
1208 
1209 static int
DeviceInit(DeviceIntPtr dev)1210 DeviceInit(DeviceIntPtr dev)
1211 {
1212     InputInfoPtr pInfo = dev->public.devicePrivate;
1213     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
1214     Atom float_type, prop;
1215     float tmpf;
1216     unsigned char map[SYN_MAX_BUTTONS + 1];
1217     int i;
1218     int min, max;
1219     int num_axes = 2;
1220     Atom btn_labels[SYN_MAX_BUTTONS] = { 0 };
1221     Atom *axes_labels;
1222     DeviceVelocityPtr pVel;
1223 
1224     num_axes += 2;
1225 
1226     num_axes += priv->num_mt_axes;
1227 
1228     axes_labels = calloc(num_axes, sizeof(Atom));
1229     if (!axes_labels) {
1230         xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate axis labels\n");
1231         return !Success;
1232     }
1233 
1234     InitAxesLabels(axes_labels, num_axes, priv);
1235     InitButtonLabels(btn_labels, SYN_MAX_BUTTONS);
1236 
1237     DBG(3, "Synaptics DeviceInit called\n");
1238 
1239     for (i = 0; i <= SYN_MAX_BUTTONS; i++)
1240         map[i] = i;
1241 
1242     dev->public.on = FALSE;
1243 
1244     InitPointerDeviceStruct((DevicePtr) dev, map,
1245                             SYN_MAX_BUTTONS,
1246                             btn_labels,
1247                             SynapticsCtrl,
1248                             GetMotionHistorySize(), num_axes, axes_labels);
1249 
1250     /*
1251      * setup dix acceleration to match legacy synaptics settings, and
1252      * etablish a device-specific profile to do stuff like pressure-related
1253      * acceleration.
1254      */
1255     if (NULL != (pVel = GetDevicePredictableAccelData(dev))) {
1256         SetDeviceSpecificAccelerationProfile(pVel,
1257                                              SynapticsAccelerationProfile);
1258 
1259         /* float property type */
1260         float_type = XIGetKnownProperty(XATOM_FLOAT);
1261 
1262         /* translate MinAcc to constant deceleration.
1263          * May be overridden in xf86InitValuatorDefaults */
1264         tmpf = 1.0 / priv->synpara.min_speed;
1265 
1266         xf86IDrvMsg(pInfo, X_CONFIG,
1267                     "(accel) MinSpeed is now constant deceleration " "%.1f\n",
1268                     tmpf);
1269         prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
1270         XIChangeDeviceProperty(dev, prop, float_type, 32,
1271                                PropModeReplace, 1, &tmpf, FALSE);
1272 
1273         /* adjust accordingly */
1274         priv->synpara.max_speed /= priv->synpara.min_speed;
1275         priv->synpara.min_speed = 1.0;
1276 
1277         /* synaptics seems to report 80 packet/s, but dix scales for
1278          * 100 packet/s by default. */
1279         pVel->corr_mul = 12.5f; /*1000[ms]/80[/s] = 12.5 */
1280 
1281         xf86IDrvMsg(pInfo, X_CONFIG, "(accel) MaxSpeed is now %.2f\n",
1282                     priv->synpara.max_speed);
1283         xf86IDrvMsg(pInfo, X_CONFIG, "(accel) AccelFactor is now %.3f\n",
1284                     priv->synpara.accl);
1285 
1286         prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
1287         i = AccelProfileDeviceSpecific;
1288         XIChangeDeviceProperty(dev, prop, XA_INTEGER, 32,
1289                                PropModeReplace, 1, &i, FALSE);
1290     }
1291 
1292     /* X valuator */
1293     if (priv->minx < priv->maxx) {
1294         min = priv->minx;
1295         max = priv->maxx;
1296     }
1297     else {
1298         min = 0;
1299         max = -1;
1300     }
1301 
1302     xf86InitValuatorAxisStruct(dev, 0, axes_labels[0], min, max,
1303 			       priv->resx * 1000, 0, priv->resx * 1000,
1304 			       Relative);
1305     xf86InitValuatorDefaults(dev, 0);
1306 
1307     /* Y valuator */
1308     if (priv->miny < priv->maxy) {
1309         min = priv->miny;
1310         max = priv->maxy;
1311     }
1312     else {
1313         min = 0;
1314         max = -1;
1315     }
1316 
1317     xf86InitValuatorAxisStruct(dev, 1, axes_labels[1], min, max,
1318 			       priv->resy * 1000, 0, priv->resy * 1000,
1319 			       Relative);
1320     xf86InitValuatorDefaults(dev, 1);
1321 
1322     xf86InitValuatorAxisStruct(dev, 2, axes_labels[2], 0, -1, 0, 0, 0,
1323                                Relative);
1324     priv->scroll_axis_horiz = 2;
1325     xf86InitValuatorAxisStruct(dev, 3, axes_labels[3], 0, -1, 0, 0, 0,
1326                                Relative);
1327     priv->scroll_axis_vert = 3;
1328     priv->scroll_events_mask = valuator_mask_new(MAX_VALUATORS);
1329     if (!priv->scroll_events_mask) {
1330         free(axes_labels);
1331         return !Success;
1332     }
1333 
1334     SetScrollValuator(dev, priv->scroll_axis_horiz, SCROLL_TYPE_HORIZONTAL,
1335                       priv->synpara.scroll_dist_horiz, 0);
1336     SetScrollValuator(dev, priv->scroll_axis_vert, SCROLL_TYPE_VERTICAL,
1337                       priv->synpara.scroll_dist_vert, 0);
1338 
1339     DeviceInitTouch(dev, axes_labels);
1340 
1341     free(axes_labels);
1342 
1343     priv->hwState = SynapticsHwStateAlloc(priv);
1344     if (!priv->hwState)
1345         goto fail;
1346 
1347     priv->local_hw_state = SynapticsHwStateAlloc(priv);
1348     if (!priv->local_hw_state)
1349         goto fail;
1350 
1351     priv->comm.hwState = SynapticsHwStateAlloc(priv);
1352 
1353     InitDeviceProperties(pInfo);
1354     XIRegisterPropertyHandler(pInfo->dev, SetProperty, NULL, NULL);
1355 
1356     SynapticsReset(priv);
1357 
1358     return Success;
1359 
1360  fail:
1361     free(priv->local_hw_state);
1362     free(priv->hwState);
1363     free(priv->open_slots);
1364     return !Success;
1365 }
1366 
1367 /*
1368  * Convert from absolute X/Y coordinates to a coordinate system where
1369  * -1 corresponds to the left/upper edge and +1 corresponds to the
1370  * right/lower edge.
1371  */
1372 static void
relative_coords(SynapticsPrivate * priv,int x,int y,double * relX,double * relY)1373 relative_coords(SynapticsPrivate * priv, int x, int y,
1374                 double *relX, double *relY)
1375 {
1376     int minX = priv->synpara.left_edge;
1377     int maxX = priv->synpara.right_edge;
1378     int minY = priv->synpara.top_edge;
1379     int maxY = priv->synpara.bottom_edge;
1380     double xCenter = (minX + maxX) / 2.0;
1381     double yCenter = (minY + maxY) / 2.0;
1382 
1383     if ((maxX - xCenter > 0) && (maxY - yCenter > 0)) {
1384         *relX = (x - xCenter) / (maxX - xCenter);
1385         *relY = (y - yCenter) / (maxY - yCenter);
1386     }
1387     else {
1388         *relX = 0;
1389         *relY = 0;
1390     }
1391 }
1392 
1393 /* return angle of point relative to center */
1394 static double
angle(SynapticsPrivate * priv,int x,int y)1395 angle(SynapticsPrivate * priv, int x, int y)
1396 {
1397     double xCenter = (priv->synpara.left_edge + priv->synpara.right_edge) / 2.0;
1398     double yCenter = (priv->synpara.top_edge + priv->synpara.bottom_edge) / 2.0;
1399 
1400     return atan2(-(y - yCenter), x - xCenter);
1401 }
1402 
1403 /* return angle difference */
1404 static double
diffa(double a1,double a2)1405 diffa(double a1, double a2)
1406 {
1407     double da = fmod(a2 - a1, 2 * M_PI);
1408 
1409     if (da < 0)
1410         da += 2 * M_PI;
1411     if (da > M_PI)
1412         da -= 2 * M_PI;
1413     return da;
1414 }
1415 
1416 static enum EdgeType
circular_edge_detection(SynapticsPrivate * priv,int x,int y)1417 circular_edge_detection(SynapticsPrivate * priv, int x, int y)
1418 {
1419     enum EdgeType edge = 0;
1420     double relX, relY, relR;
1421 
1422     relative_coords(priv, x, y, &relX, &relY);
1423     relR = SQR(relX) + SQR(relY);
1424 
1425     if (relR > 1) {
1426         /* we are outside the ellipse enclosed by the edge parameters */
1427         if (relX > M_SQRT1_2)
1428             edge |= RIGHT_EDGE;
1429         else if (relX < -M_SQRT1_2)
1430             edge |= LEFT_EDGE;
1431 
1432         if (relY < -M_SQRT1_2)
1433             edge |= TOP_EDGE;
1434         else if (relY > M_SQRT1_2)
1435             edge |= BOTTOM_EDGE;
1436     }
1437 
1438     return edge;
1439 }
1440 
1441 static enum EdgeType
edge_detection(SynapticsPrivate * priv,int x,int y)1442 edge_detection(SynapticsPrivate * priv, int x, int y)
1443 {
1444     enum EdgeType edge = NO_EDGE;
1445 
1446     if (priv->synpara.circular_pad)
1447         return circular_edge_detection(priv, x, y);
1448 
1449     if (x > priv->synpara.right_edge)
1450         edge |= RIGHT_EDGE;
1451     else if (x < priv->synpara.left_edge)
1452         edge |= LEFT_EDGE;
1453 
1454     if (y < priv->synpara.top_edge)
1455         edge |= TOP_EDGE;
1456     else if (y > priv->synpara.bottom_edge)
1457         edge |= BOTTOM_EDGE;
1458 
1459     return edge;
1460 }
1461 
1462 /* Checks whether coordinates are in the Synaptics Area
1463  * or not. If no Synaptics Area is defined (i.e. if
1464  * priv->synpara.area_{left|right|top|bottom}_edge are
1465  * all set to zero), the function returns TRUE.
1466  */
1467 static Bool
is_inside_active_area(SynapticsPrivate * priv,int x,int y)1468 is_inside_active_area(SynapticsPrivate * priv, int x, int y)
1469 {
1470     Bool inside_area = TRUE;
1471 
1472     /* If a finger is down, then it must have started inside the active_area,
1473        allow the motion to complete using the entire area */
1474     if (priv->finger_state >= FS_TOUCHED)
1475         return TRUE;
1476 
1477     if ((priv->synpara.area_left_edge != 0) &&
1478         (x < priv->synpara.area_left_edge))
1479         inside_area = FALSE;
1480     else if ((priv->synpara.area_right_edge != 0) &&
1481              (x > priv->synpara.area_right_edge))
1482         inside_area = FALSE;
1483 
1484     if ((priv->synpara.area_top_edge != 0) && (y < priv->synpara.area_top_edge))
1485         inside_area = FALSE;
1486     else if ((priv->synpara.area_bottom_edge != 0) &&
1487              (y > priv->synpara.area_bottom_edge))
1488         inside_area = FALSE;
1489 
1490     return inside_area;
1491 }
1492 
1493 static Bool
is_inside_button_area(SynapticsParameters * para,int which,int x,int y)1494 is_inside_button_area(SynapticsParameters * para, int which, int x, int y)
1495 {
1496     Bool inside_area = TRUE;
1497 
1498     if (para->softbutton_areas[which][LEFT] == 0 &&
1499         para->softbutton_areas[which][RIGHT] == 0 &&
1500         para->softbutton_areas[which][TOP] == 0 &&
1501         para->softbutton_areas[which][BOTTOM] == 0)
1502         return FALSE;
1503 
1504     if (para->softbutton_areas[which][LEFT] &&
1505         x < para->softbutton_areas[which][LEFT])
1506         inside_area = FALSE;
1507     else if (para->softbutton_areas[which][RIGHT] &&
1508              x > para->softbutton_areas[which][RIGHT])
1509         inside_area = FALSE;
1510     else if (para->softbutton_areas[which][TOP] &&
1511              y < para->softbutton_areas[which][TOP])
1512         inside_area = FALSE;
1513     else if (para->softbutton_areas[which][BOTTOM] &&
1514              y > para->softbutton_areas[which][BOTTOM])
1515         inside_area = FALSE;
1516 
1517     return inside_area;
1518 }
1519 
1520 static Bool
is_inside_rightbutton_area(SynapticsParameters * para,int x,int y)1521 is_inside_rightbutton_area(SynapticsParameters * para, int x, int y)
1522 {
1523     return is_inside_button_area(para, BOTTOM_RIGHT_BUTTON_AREA, x, y);
1524 }
1525 
1526 static Bool
is_inside_middlebutton_area(SynapticsParameters * para,int x,int y)1527 is_inside_middlebutton_area(SynapticsParameters * para, int x, int y)
1528 {
1529     return is_inside_button_area(para, BOTTOM_MIDDLE_BUTTON_AREA, x, y);
1530 }
1531 
1532 static Bool
is_inside_sec_rightbutton_area(SynapticsParameters * para,int x,int y)1533 is_inside_sec_rightbutton_area(SynapticsParameters * para, int x, int y)
1534 {
1535     return is_inside_button_area(para, TOP_RIGHT_BUTTON_AREA, x, y);
1536 }
1537 
1538 static Bool
is_inside_sec_middlebutton_area(SynapticsParameters * para,int x,int y)1539 is_inside_sec_middlebutton_area(SynapticsParameters * para, int x, int y)
1540 {
1541     return is_inside_button_area(para, TOP_MIDDLE_BUTTON_AREA, x, y);
1542 }
1543 
1544 static Bool
is_inside_top_or_bottom_button_area(SynapticsParameters * para,int offset,int x,int y)1545 is_inside_top_or_bottom_button_area(SynapticsParameters * para, int offset,
1546                                     int x, int y)
1547 {
1548     Bool inside_area = TRUE;
1549     Bool right_valid, middle_valid;
1550     int top, bottom;
1551 
1552     /* We don't have a left button area, so we only check the y axis */
1553     right_valid = para->softbutton_areas[offset][TOP] ||
1554                   para->softbutton_areas[offset][BOTTOM];
1555     middle_valid = para->softbutton_areas[offset + 1][TOP] ||
1556                    para->softbutton_areas[offset + 1][BOTTOM];
1557 
1558     if (!right_valid && !middle_valid)
1559         return FALSE;
1560 
1561     /* Check both buttons are horizontally aligned */
1562     if (right_valid && middle_valid && (
1563             para->softbutton_areas[offset][TOP] !=
1564                 para->softbutton_areas[offset + 1][TOP] ||
1565             para->softbutton_areas[offset][BOTTOM] !=
1566                 para->softbutton_areas[offset + 1][BOTTOM]))
1567         return FALSE;
1568 
1569     if (right_valid) {
1570         top    = para->softbutton_areas[offset][TOP];
1571         bottom = para->softbutton_areas[offset][BOTTOM];
1572     }
1573     else {
1574         top    = para->softbutton_areas[offset + 1][TOP];
1575         bottom = para->softbutton_areas[offset + 1][BOTTOM];
1576     }
1577 
1578     if (top && y < top)
1579         inside_area = FALSE;
1580     else if (bottom && y > bottom)
1581         inside_area = FALSE;
1582 
1583     return inside_area;
1584 }
1585 
1586 static enum SoftButtonAreas
current_button_area(SynapticsParameters * para,int x,int y)1587 current_button_area(SynapticsParameters * para, int x, int y)
1588 {
1589     if (is_inside_top_or_bottom_button_area(para, BOTTOM_BUTTON_AREA, x, y))
1590         return BOTTOM_BUTTON_AREA;
1591     else if (is_inside_top_or_bottom_button_area(para, TOP_BUTTON_AREA, x, y))
1592         return TOP_BUTTON_AREA;
1593     else
1594         return NO_BUTTON_AREA;
1595 }
1596 
1597 static CARD32
timerFunc(OsTimerPtr timer,CARD32 now,pointer arg)1598 timerFunc(OsTimerPtr timer, CARD32 now, pointer arg)
1599 {
1600     InputInfoPtr pInfo = arg;
1601     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
1602     struct SynapticsHwState *hw = priv->local_hw_state;
1603     int delay;
1604 #if !HAVE_THREADED_INPUT
1605     int sigstate = xf86BlockSIGIO();
1606 #else
1607     input_lock();
1608 #endif
1609 
1610     priv->hwState->millis += now - priv->timer_time;
1611     SynapticsCopyHwState(hw, priv->hwState);
1612     SynapticsResetTouchHwState(hw, FALSE);
1613     delay = HandleState(pInfo, hw, hw->millis, TRUE);
1614 
1615     priv->timer_time = now;
1616     priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo);
1617 
1618 #if !HAVE_THREADED_INPUT
1619     xf86UnblockSIGIO(sigstate);
1620 #else
1621     input_unlock();
1622 #endif
1623 
1624     return 0;
1625 }
1626 
1627 static int
clamp(int val,int min,int max)1628 clamp(int val, int min, int max)
1629 {
1630     if (val < min)
1631         return min;
1632     else if (val < max)
1633         return val;
1634     else
1635         return max;
1636 }
1637 
1638 static Bool
SynapticsGetHwState(InputInfoPtr pInfo,SynapticsPrivate * priv,struct SynapticsHwState * hw)1639 SynapticsGetHwState(InputInfoPtr pInfo, SynapticsPrivate * priv,
1640                     struct SynapticsHwState *hw)
1641 {
1642     return priv->proto_ops->ReadHwState(pInfo, &priv->comm, hw);
1643 }
1644 
1645 /*
1646  *  called for each full received packet from the touchpad
1647  */
1648 static void
ReadInput(InputInfoPtr pInfo)1649 ReadInput(InputInfoPtr pInfo)
1650 {
1651     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
1652     struct SynapticsHwState *hw = priv->local_hw_state;
1653     int delay = 0;
1654     Bool newDelay = FALSE;
1655 
1656     SynapticsResetTouchHwState(hw, FALSE);
1657 
1658     while (SynapticsGetHwState(pInfo, priv, hw)) {
1659         /* Semi-mt device touch slots do not track touches. When there is a
1660          * change in the number of touches, we must disregard the temporary
1661          * motion changes. */
1662         if (priv->has_semi_mt && hw->numFingers != priv->hwState->numFingers) {
1663             hw->cumulative_dx = priv->hwState->cumulative_dx;
1664             hw->cumulative_dy = priv->hwState->cumulative_dy;
1665         }
1666 
1667         /* timer may cause actual events to lag behind (#48777) */
1668         if (priv->hwState->millis > hw->millis)
1669             hw->millis = priv->hwState->millis;
1670 
1671         SynapticsCopyHwState(priv->hwState, hw);
1672         delay = HandleState(pInfo, hw, hw->millis, FALSE);
1673         newDelay = TRUE;
1674     }
1675 
1676     if (newDelay) {
1677         priv->timer_time = GetTimeInMillis();
1678         priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo);
1679     }
1680 }
1681 
1682 static int
HandleMidButtonEmulation(SynapticsPrivate * priv,struct SynapticsHwState * hw,CARD32 now,int * delay)1683 HandleMidButtonEmulation(SynapticsPrivate * priv, struct SynapticsHwState *hw,
1684                          CARD32 now, int *delay)
1685 {
1686     SynapticsParameters *para = &priv->synpara;
1687     Bool done = FALSE;
1688     int timeleft;
1689     int mid = 0;
1690 
1691     if (para->emulate_mid_button_time <= 0)
1692         return mid;
1693 
1694     while (!done) {
1695         switch (priv->mid_emu_state) {
1696         case MBE_LEFT_CLICK:
1697         case MBE_RIGHT_CLICK:
1698         case MBE_OFF:
1699             priv->button_delay_millis = now;
1700             if (hw->left) {
1701                 priv->mid_emu_state = MBE_LEFT;
1702             }
1703             else if (hw->right) {
1704                 priv->mid_emu_state = MBE_RIGHT;
1705             }
1706             else {
1707                 done = TRUE;
1708             }
1709             break;
1710         case MBE_LEFT:
1711             timeleft =
1712                 TIME_DIFF(priv->button_delay_millis +
1713                           para->emulate_mid_button_time, now);
1714             if (timeleft > 0)
1715                 *delay = MIN(*delay, timeleft);
1716 
1717             /* timeout, but within the same ReadInput cycle! */
1718             if ((timeleft <= 0) && !hw->left) {
1719                 priv->mid_emu_state = MBE_LEFT_CLICK;
1720                 done = TRUE;
1721             }
1722             else if ((!hw->left) || (timeleft <= 0)) {
1723                 hw->left = TRUE;
1724                 priv->mid_emu_state = MBE_TIMEOUT;
1725                 done = TRUE;
1726             }
1727             else if (hw->right) {
1728                 priv->mid_emu_state = MBE_MID;
1729             }
1730             else {
1731                 hw->left = FALSE;
1732                 done = TRUE;
1733             }
1734             break;
1735         case MBE_RIGHT:
1736             timeleft =
1737                 TIME_DIFF(priv->button_delay_millis +
1738                           para->emulate_mid_button_time, now);
1739             if (timeleft > 0)
1740                 *delay = MIN(*delay, timeleft);
1741 
1742             /* timeout, but within the same ReadInput cycle! */
1743             if ((timeleft <= 0) && !hw->right) {
1744                 priv->mid_emu_state = MBE_RIGHT_CLICK;
1745                 done = TRUE;
1746             }
1747             else if (!hw->right || (timeleft <= 0)) {
1748                 hw->right = TRUE;
1749                 priv->mid_emu_state = MBE_TIMEOUT;
1750                 done = TRUE;
1751             }
1752             else if (hw->left) {
1753                 priv->mid_emu_state = MBE_MID;
1754             }
1755             else {
1756                 hw->right = FALSE;
1757                 done = TRUE;
1758             }
1759             break;
1760         case MBE_MID:
1761             if (!hw->left && !hw->right) {
1762                 priv->mid_emu_state = MBE_OFF;
1763             }
1764             else {
1765                 mid = TRUE;
1766                 hw->left = hw->right = FALSE;
1767                 done = TRUE;
1768             }
1769             break;
1770         case MBE_TIMEOUT:
1771             if (!hw->left && !hw->right) {
1772                 priv->mid_emu_state = MBE_OFF;
1773             }
1774             else {
1775                 done = TRUE;
1776             }
1777         }
1778     }
1779     return mid;
1780 }
1781 
1782 static enum FingerState
SynapticsDetectFinger(SynapticsPrivate * priv,struct SynapticsHwState * hw)1783 SynapticsDetectFinger(SynapticsPrivate * priv, struct SynapticsHwState *hw)
1784 {
1785     SynapticsParameters *para = &priv->synpara;
1786     enum FingerState finger;
1787 
1788     /* finger detection thru pressure and threshold */
1789     if (hw->z < para->finger_low)
1790         return FS_UNTOUCHED;
1791 
1792     if (priv->finger_state == FS_BLOCKED)
1793         return FS_BLOCKED;
1794 
1795     if (hw->z > para->finger_high && priv->finger_state == FS_UNTOUCHED)
1796         finger = FS_TOUCHED;
1797     else
1798         finger = priv->finger_state;
1799 
1800     if (!para->palm_detect)
1801         return finger;
1802 
1803     /* palm detection */
1804 
1805     if ((hw->z > para->palm_min_z) && (hw->fingerWidth > para->palm_min_width))
1806         return FS_BLOCKED;
1807 
1808     if (priv->has_mt_palm_detect)
1809         return finger;
1810 
1811     if (hw->x == 0 || priv->finger_state == FS_UNTOUCHED)
1812         priv->avg_width = 0;
1813     else
1814         priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2;
1815 
1816     if (finger != FS_UNTOUCHED && priv->finger_state == FS_UNTOUCHED) {
1817         int safe_width = MAX(hw->fingerWidth, priv->avg_width);
1818 
1819         if (hw->numFingers > 1 ||       /* more than one finger -> not a palm */
1820             ((safe_width < 6) && (priv->prev_z < para->finger_high)) || /* thin finger, distinct touch -> not a palm */
1821             ((safe_width < 7) && (priv->prev_z < para->finger_high / 2))) {     /* thin finger, distinct touch -> not a palm */
1822             /* leave finger value as is */
1823         }
1824         else if (hw->z > priv->prev_z + 1)      /* z not stable, may be a palm */
1825             finger = FS_UNTOUCHED;
1826         else if (hw->z < priv->prev_z - 5)      /* z not stable, may be a palm */
1827             finger = FS_UNTOUCHED;
1828         else if (hw->fingerWidth > para->palm_min_width)        /* finger width too large -> probably palm */
1829             finger = FS_UNTOUCHED;
1830     }
1831     priv->prev_z = hw->z;
1832 
1833     return finger;
1834 }
1835 
1836 static void
SelectTapButton(SynapticsPrivate * priv,enum EdgeType edge)1837 SelectTapButton(SynapticsPrivate * priv, enum EdgeType edge)
1838 {
1839     enum TapEvent tap;
1840 
1841     if (priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF) {
1842         priv->tap_button = 0;
1843         return;
1844     }
1845 
1846     switch (priv->tap_max_fingers) {
1847     case 1:
1848         switch (edge) {
1849         case RIGHT_TOP_EDGE:
1850             DBG(7, "right top edge\n");
1851             tap = RT_TAP;
1852             break;
1853         case RIGHT_BOTTOM_EDGE:
1854             DBG(7, "right bottom edge\n");
1855             tap = RB_TAP;
1856             break;
1857         case LEFT_TOP_EDGE:
1858             DBG(7, "left top edge\n");
1859             tap = LT_TAP;
1860             break;
1861         case LEFT_BOTTOM_EDGE:
1862             DBG(7, "left bottom edge\n");
1863             tap = LB_TAP;
1864             break;
1865         default:
1866             DBG(7, "no edge\n");
1867             tap = F1_TAP;
1868             break;
1869         }
1870         break;
1871     case 2:
1872         DBG(7, "two finger tap\n");
1873         tap = F2_TAP;
1874         break;
1875     case 3:
1876         DBG(7, "three finger tap\n");
1877         tap = F3_TAP;
1878         break;
1879     default:
1880         priv->tap_button = 0;
1881         return;
1882     }
1883 
1884     priv->tap_button = priv->synpara.tap_action[tap];
1885     priv->tap_button = clamp(priv->tap_button, 0, SYN_MAX_BUTTONS);
1886 }
1887 
1888 static void
SetTapState(SynapticsPrivate * priv,enum TapState tap_state,CARD32 millis)1889 SetTapState(SynapticsPrivate * priv, enum TapState tap_state, CARD32 millis)
1890 {
1891     DBG(3, "SetTapState - %d -> %d (millis:%u)\n", priv->tap_state, tap_state,
1892         millis);
1893     switch (tap_state) {
1894     case TS_START:
1895         priv->tap_button_state = TBS_BUTTON_UP;
1896         priv->tap_max_fingers = 0;
1897         break;
1898     case TS_1:
1899         priv->tap_button_state = TBS_BUTTON_UP;
1900         break;
1901     case TS_2A:
1902 	priv->tap_button_state = TBS_BUTTON_UP;
1903         break;
1904     case TS_2B:
1905         priv->tap_button_state = TBS_BUTTON_UP;
1906         break;
1907     case TS_3:
1908         priv->tap_button_state = TBS_BUTTON_DOWN;
1909         break;
1910     case TS_SINGLETAP:
1911 	priv->tap_button_state = TBS_BUTTON_DOWN;
1912         priv->touch_on.millis = millis;
1913         break;
1914     default:
1915         break;
1916     }
1917     priv->tap_state = tap_state;
1918 }
1919 
1920 static void
SetMovingState(SynapticsPrivate * priv,enum MovingState moving_state,CARD32 millis)1921 SetMovingState(SynapticsPrivate * priv, enum MovingState moving_state,
1922                CARD32 millis)
1923 {
1924     DBG(7, "SetMovingState - %d -> %d center at %d/%d (millis:%u)\n",
1925         priv->moving_state, moving_state, priv->hwState->x, priv->hwState->y,
1926         millis);
1927 
1928     priv->moving_state = moving_state;
1929 }
1930 
1931 static int
GetTimeOut(SynapticsPrivate * priv)1932 GetTimeOut(SynapticsPrivate * priv)
1933 {
1934     SynapticsParameters *para = &priv->synpara;
1935 
1936     switch (priv->tap_state) {
1937     case TS_1:
1938     case TS_3:
1939     case TS_5:
1940         return para->tap_time;
1941     case TS_SINGLETAP:
1942         return para->click_time;
1943     case TS_2A:
1944         return para->single_tap_timeout;
1945     case TS_2B:
1946         return para->tap_time_2;
1947     case TS_4:
1948         return para->locked_drag_time;
1949     default:
1950         return -1;              /* No timeout */
1951     }
1952 }
1953 
1954 static int
HandleTapProcessing(SynapticsPrivate * priv,struct SynapticsHwState * hw,CARD32 now,enum FingerState finger,Bool inside_active_area)1955 HandleTapProcessing(SynapticsPrivate * priv, struct SynapticsHwState *hw,
1956                     CARD32 now, enum FingerState finger,
1957                     Bool inside_active_area)
1958 {
1959     SynapticsParameters *para = &priv->synpara;
1960     Bool touch, release, is_timeout, move, press;
1961     int timeleft, timeout;
1962     enum EdgeType edge;
1963     int delay = 1000000000;
1964 
1965     if (para->touchpad_off == TOUCHPAD_OFF ||
1966         priv->finger_state == FS_BLOCKED)
1967         return delay;
1968 
1969     touch = finger >= FS_TOUCHED && priv->finger_state == FS_UNTOUCHED;
1970     release = finger == FS_UNTOUCHED && priv->finger_state >= FS_TOUCHED;
1971     move = (finger >= FS_TOUCHED &&
1972             (priv->tap_max_fingers <=
1973              ((priv->horiz_scroll_twofinger_on ||
1974                priv->vert_scroll_twofinger_on) ? 2 : 1)) &&
1975             (priv->prevFingers == hw->numFingers &&
1976              ((abs(hw->x - priv->touch_on.x) >= para->tap_move) ||
1977               (abs(hw->y - priv->touch_on.y) >= para->tap_move))));
1978     press = (hw->left || hw->right || hw->middle);
1979 
1980     if (touch) {
1981         priv->touch_on.x = hw->x;
1982         priv->touch_on.y = hw->y;
1983         priv->touch_on.millis = now;
1984     }
1985     else if (release) {
1986         priv->touch_on.millis = now;
1987     }
1988     if (hw->z > para->finger_high)
1989         if (priv->tap_max_fingers < hw->numFingers)
1990             priv->tap_max_fingers = hw->numFingers;
1991     timeout = GetTimeOut(priv);
1992     timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now);
1993     is_timeout = timeleft <= 0;
1994 
1995  restart:
1996     switch (priv->tap_state) {
1997     case TS_START:
1998         if (touch)
1999             SetTapState(priv, TS_1, now);
2000         break;
2001     case TS_1:
2002         if (para->clickpad && press) {
2003             SetTapState(priv, TS_CLICKPAD_MOVE, now);
2004             goto restart;
2005         }
2006         if (move) {
2007             SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2008             SetTapState(priv, TS_MOVE, now);
2009             goto restart;
2010         }
2011         else if (is_timeout) {
2012             if (finger == FS_TOUCHED) {
2013                 SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2014             }
2015             SetTapState(priv, TS_MOVE, now);
2016             goto restart;
2017         }
2018         else if (release) {
2019             edge = edge_detection(priv, priv->touch_on.x, priv->touch_on.y);
2020             SelectTapButton(priv, edge);
2021             /* Disable taps outside of the active area */
2022             if (!inside_active_area) {
2023                 priv->tap_button = 0;
2024             }
2025             SetTapState(priv, TS_2A, now);
2026         }
2027         break;
2028     case TS_MOVE:
2029         if (para->clickpad && press) {
2030             SetTapState(priv, TS_CLICKPAD_MOVE, now);
2031             goto restart;
2032         }
2033         if (release) {
2034             SetMovingState(priv, MS_FALSE, now);
2035             SetTapState(priv, TS_START, now);
2036         }
2037         break;
2038     case TS_2A:
2039         if (touch)
2040             SetTapState(priv, TS_3, now);
2041         else if (is_timeout)
2042             SetTapState(priv, TS_SINGLETAP, now);
2043         break;
2044     case TS_2B:
2045         if (touch)
2046             SetTapState(priv, TS_3, now);
2047         else if (is_timeout)
2048             SetTapState(priv, TS_SINGLETAP, now);
2049         break;
2050     case TS_SINGLETAP:
2051         if (touch)
2052             SetTapState(priv, TS_1, now);
2053         else if (is_timeout)
2054             SetTapState(priv, TS_START, now);
2055         break;
2056     case TS_3:
2057         if (move) {
2058             if (para->tap_and_drag_gesture) {
2059                 SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2060                 SetTapState(priv, TS_DRAG, now);
2061             }
2062             else {
2063                 SetTapState(priv, TS_1, now);
2064             }
2065             goto restart;
2066         }
2067         else if (is_timeout) {
2068             if (para->tap_and_drag_gesture) {
2069                 if (finger == FS_TOUCHED) {
2070                     SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2071                 }
2072                 SetTapState(priv, TS_DRAG, now);
2073             }
2074             else {
2075                 SetTapState(priv, TS_1, now);
2076             }
2077             goto restart;
2078         }
2079         else if (release) {
2080             SetTapState(priv, TS_2B, now);
2081         }
2082         break;
2083     case TS_DRAG:
2084         if (para->clickpad && press) {
2085             SetTapState(priv, TS_CLICKPAD_MOVE, now);
2086             goto restart;
2087         }
2088         if (move)
2089             SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2090         if (release) {
2091             SetMovingState(priv, MS_FALSE, now);
2092             if (para->locked_drags) {
2093                 SetTapState(priv, TS_4, now);
2094             }
2095             else {
2096                 SetTapState(priv, TS_START, now);
2097             }
2098         }
2099         break;
2100     case TS_4:
2101         if (is_timeout) {
2102             SetTapState(priv, TS_START, now);
2103             goto restart;
2104         }
2105         if (touch)
2106             SetTapState(priv, TS_5, now);
2107         break;
2108     case TS_5:
2109         if (is_timeout || move) {
2110             SetTapState(priv, TS_DRAG, now);
2111             goto restart;
2112         }
2113         else if (release) {
2114             SetMovingState(priv, MS_FALSE, now);
2115             SetTapState(priv, TS_START, now);
2116         }
2117         break;
2118     case TS_CLICKPAD_MOVE:
2119         /* Disable scrolling once a button is pressed on a clickpad */
2120         priv->vert_scroll_edge_on = FALSE;
2121         priv->horiz_scroll_edge_on = FALSE;
2122         priv->vert_scroll_twofinger_on = FALSE;
2123         priv->horiz_scroll_twofinger_on = FALSE;
2124 
2125         /* Assume one touch is only for holding the clickpad button down */
2126         if (hw->numFingers > 1)
2127             hw->numFingers--;
2128         SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2129         if (!press) {
2130             SetMovingState(priv, MS_FALSE, now);
2131             SetTapState(priv, TS_MOVE, now);
2132             priv->count_packet_finger = 0;
2133         }
2134         break;
2135     }
2136 
2137     timeout = GetTimeOut(priv);
2138     if (timeout >= 0) {
2139         timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now);
2140         delay = clamp(timeleft, 1, delay);
2141     }
2142     return delay;
2143 }
2144 
2145 #define HIST(a) (priv->move_hist[((priv->hist_index - (a) + SYNAPTICS_MOVE_HISTORY) % SYNAPTICS_MOVE_HISTORY)])
2146 #define HIST_DELTA(a, b, e) ((HIST((a)).e) - (HIST((b)).e))
2147 
2148 static void
store_history(SynapticsPrivate * priv,int x,int y,CARD32 millis)2149 store_history(SynapticsPrivate * priv, int x, int y, CARD32 millis)
2150 {
2151     int idx = (priv->hist_index + 1) % SYNAPTICS_MOVE_HISTORY;
2152 
2153     priv->move_hist[idx].x = x;
2154     priv->move_hist[idx].y = y;
2155     priv->move_hist[idx].millis = millis;
2156     priv->hist_index = idx;
2157     if (priv->count_packet_finger < SYNAPTICS_MOVE_HISTORY)
2158         priv->count_packet_finger++;
2159 }
2160 
2161 /*
2162  * Estimate the slope for the data sequence [x3, x2, x1, x0] by using
2163  * linear regression to fit a line to the data and use the slope of the
2164  * line.
2165  */
2166 static double
estimate_delta(double x0,double x1,double x2,double x3)2167 estimate_delta(double x0, double x1, double x2, double x3)
2168 {
2169     return x0 * 0.3 + x1 * 0.1 - x2 * 0.1 - x3 * 0.3;
2170 }
2171 
2172 /**
2173  * Applies hysteresis. center is shifted such that it is in range with
2174  * in by the margin again. The new center is returned.
2175  * @param in the current value
2176  * @param center the current center
2177  * @param margin the margin to center in which no change is applied
2178  * @return the new center (which might coincide with the previous)
2179  */
2180 static int
hysteresis(int in,int center,int margin)2181 hysteresis(int in, int center, int margin)
2182 {
2183     int diff = in - center;
2184 
2185     if (abs(diff) <= margin) {
2186         diff = 0;
2187     }
2188     else if (diff > margin) {
2189         diff -= margin;
2190     }
2191     else if (diff < -margin) {
2192         diff += margin;
2193     }
2194     return center + diff;
2195 }
2196 
2197 static void
get_delta(SynapticsPrivate * priv,const struct SynapticsHwState * hw,enum EdgeType edge,double * dx,double * dy)2198 get_delta(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
2199           enum EdgeType edge, double *dx, double *dy)
2200 {
2201     *dx = hw->x - HIST(0).x;
2202     *dy = hw->y - HIST(0).y;
2203 }
2204 
2205 /* Vector length, but not sqrt'ed, we only need it for comparison */
2206 static inline double
vlenpow2(double x,double y)2207 vlenpow2(double x, double y)
2208 {
2209     return x * x + y * y;
2210 }
2211 
2212 /**
2213  * Compute relative motion ('deltas') including edge motion.
2214  */
2215 static int
ComputeDeltas(SynapticsPrivate * priv,const struct SynapticsHwState * hw,enum EdgeType edge,int * dxP,int * dyP,Bool inside_area)2216 ComputeDeltas(SynapticsPrivate * priv, const struct SynapticsHwState *hw,
2217               enum EdgeType edge, int *dxP, int *dyP, Bool inside_area)
2218 {
2219     enum MovingState moving_state;
2220     double dx, dy;
2221     double vlen;
2222     int delay = 1000000000;
2223 
2224     dx = dy = 0;
2225 
2226     moving_state = priv->moving_state;
2227     if (moving_state == MS_FALSE) {
2228         switch (priv->tap_state) {
2229         case TS_MOVE:
2230         case TS_DRAG:
2231             moving_state = MS_TOUCHPAD_RELATIVE;
2232             break;
2233         case TS_1:
2234         case TS_3:
2235         case TS_5:
2236             moving_state = MS_TOUCHPAD_RELATIVE;
2237             break;
2238         default:
2239             break;
2240         }
2241     }
2242 
2243     if (!inside_area || !moving_state || priv->finger_state == FS_BLOCKED ||
2244         priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
2245         priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
2246         priv->circ_scroll_on || priv->prevFingers != hw->numFingers ||
2247         (moving_state == MS_TOUCHPAD_RELATIVE && hw->numFingers != 1)) {
2248         /* reset packet counter. */
2249         priv->count_packet_finger = 0;
2250         goto out;
2251     }
2252 
2253     /* To create the illusion of fluid motion, call back at roughly the report
2254      * rate, even in the absence of new hardware events; see comment above
2255      * POLL_MS declaration. */
2256     delay = MIN(delay, POLL_MS);
2257 
2258     if (priv->count_packet_finger <= 1)
2259         goto out;               /* skip the lot */
2260 
2261     if (moving_state == MS_TOUCHPAD_RELATIVE)
2262         get_delta(priv, hw, edge, &dx, &dy);
2263 
2264  out:
2265     priv->prevFingers = hw->numFingers;
2266 
2267     vlen = vlenpow2(dx/priv->synpara.resolution_horiz,
2268                     dy/priv->synpara.resolution_vert);
2269 
2270     if (vlen > priv->synpara.maxDeltaMM * priv->synpara.maxDeltaMM) {
2271         dx = 0;
2272         dy = 0;
2273     }
2274 
2275     *dxP = dx;
2276     *dyP = dy;
2277 
2278     return delay;
2279 }
2280 
2281 static double
estimate_delta_circ(SynapticsPrivate * priv)2282 estimate_delta_circ(SynapticsPrivate * priv)
2283 {
2284     double a1 = angle(priv, HIST(3).x, HIST(3).y);
2285     double a2 = angle(priv, HIST(2).x, HIST(2).y);
2286     double a3 = angle(priv, HIST(1).x, HIST(1).y);
2287     double a4 = angle(priv, HIST(0).x, HIST(0).y);
2288     double d1 = diffa(a2, a1);
2289     double d2 = d1 + diffa(a3, a2);
2290     double d3 = d2 + diffa(a4, a3);
2291 
2292     return estimate_delta(d3, d2, d1, 0);
2293 }
2294 
2295 /* vert and horiz are to know which direction to start coasting
2296  * circ is true if the user had been circular scrolling.
2297  */
2298 static void
start_coasting(SynapticsPrivate * priv,struct SynapticsHwState * hw,Bool vert,Bool horiz,Bool circ)2299 start_coasting(SynapticsPrivate * priv, struct SynapticsHwState *hw,
2300                Bool vert, Bool horiz, Bool circ)
2301 {
2302     SynapticsParameters *para = &priv->synpara;
2303 
2304     priv->scroll.coast_delta_y = 0.0;
2305     priv->scroll.coast_delta_x = 0.0;
2306 
2307     if ((priv->scroll.packets_this_scroll > 3) && (para->coasting_speed > 0.0)) {
2308         double pkt_time = HIST_DELTA(0, 3, millis) / 1000.0;
2309 
2310         if (vert && !circ) {
2311             double dy =
2312                 estimate_delta(HIST(0).y, HIST(1).y, HIST(2).y, HIST(3).y);
2313             if (pkt_time > 0) {
2314                 double scrolls_per_sec = (dy / abs(para->scroll_dist_vert)) / pkt_time;
2315 
2316                 if (fabs(scrolls_per_sec) >= para->coasting_speed) {
2317                     priv->scroll.coast_speed_y = scrolls_per_sec;
2318                     priv->scroll.coast_delta_y = (hw->y - priv->scroll.last_y);
2319                 }
2320             }
2321         }
2322         if (horiz && !circ) {
2323             double dx =
2324                 estimate_delta(HIST(0).x, HIST(1).x, HIST(2).x, HIST(3).x);
2325             if (pkt_time > 0) {
2326                 double scrolls_per_sec = (dx / abs(para->scroll_dist_vert)) / pkt_time;
2327 
2328                 if (fabs(scrolls_per_sec) >= para->coasting_speed) {
2329                     priv->scroll.coast_speed_x = scrolls_per_sec;
2330                     priv->scroll.coast_delta_x = (hw->x - priv->scroll.last_x);
2331                 }
2332             }
2333         }
2334         if (circ) {
2335             double da = estimate_delta_circ(priv);
2336 
2337             if (pkt_time > 0) {
2338                 double scrolls_per_sec = (da / para->scroll_dist_circ) / pkt_time;
2339 
2340                 if (fabs(scrolls_per_sec) >= para->coasting_speed) {
2341                     if (vert) {
2342                         priv->scroll.coast_speed_y = scrolls_per_sec;
2343                         priv->scroll.coast_delta_y =
2344                             diffa(priv->scroll.last_a,
2345                                   angle(priv, hw->x, hw->y));
2346                     }
2347                     else if (horiz) {
2348                         priv->scroll.coast_speed_x = scrolls_per_sec;
2349                         priv->scroll.coast_delta_x =
2350                             diffa(priv->scroll.last_a,
2351                                   angle(priv, hw->x, hw->y));
2352                     }
2353                 }
2354             }
2355         }
2356     }
2357     priv->scroll.packets_this_scroll = 0;
2358 }
2359 
2360 static void
stop_coasting(SynapticsPrivate * priv)2361 stop_coasting(SynapticsPrivate * priv)
2362 {
2363     priv->scroll.coast_speed_x = 0;
2364     priv->scroll.coast_speed_y = 0;
2365     priv->scroll.packets_this_scroll = 0;
2366 }
2367 
2368 static int
HandleScrolling(SynapticsPrivate * priv,struct SynapticsHwState * hw,enum EdgeType edge,Bool finger)2369 HandleScrolling(SynapticsPrivate * priv, struct SynapticsHwState *hw,
2370                 enum EdgeType edge, Bool finger)
2371 {
2372     SynapticsParameters *para = &priv->synpara;
2373     int delay = 1000000000;
2374 
2375     if (priv->synpara.touchpad_off == TOUCHPAD_TAP_OFF ||
2376         priv->synpara.touchpad_off == TOUCHPAD_OFF ||
2377         priv->finger_state == FS_BLOCKED) {
2378         stop_coasting(priv);
2379         priv->circ_scroll_on = FALSE;
2380         priv->vert_scroll_edge_on = FALSE;
2381         priv->horiz_scroll_edge_on = FALSE;
2382         priv->vert_scroll_twofinger_on = FALSE;
2383         priv->horiz_scroll_twofinger_on = FALSE;
2384         return delay;
2385     }
2386 
2387     /* scroll detection */
2388     if (finger && priv->finger_state == FS_UNTOUCHED) {
2389         stop_coasting(priv);
2390         priv->scroll.delta_y = 0;
2391         priv->scroll.delta_x = 0;
2392         if (para->circular_scrolling) {
2393             if ((para->circular_trigger == 0 && edge) ||
2394                 (para->circular_trigger == 1 && edge & TOP_EDGE) ||
2395                 (para->circular_trigger == 2 && edge & TOP_EDGE &&
2396                  edge & RIGHT_EDGE) || (para->circular_trigger == 3 &&
2397                                         edge & RIGHT_EDGE) ||
2398                 (para->circular_trigger == 4 && edge & RIGHT_EDGE &&
2399                  edge & BOTTOM_EDGE) || (para->circular_trigger == 5 &&
2400                                          edge & BOTTOM_EDGE) ||
2401                 (para->circular_trigger == 6 && edge & BOTTOM_EDGE &&
2402                  edge & LEFT_EDGE) || (para->circular_trigger == 7 &&
2403                                        edge & LEFT_EDGE) ||
2404                 (para->circular_trigger == 8 && edge & LEFT_EDGE &&
2405                  edge & TOP_EDGE)) {
2406                 priv->circ_scroll_on = TRUE;
2407                 priv->circ_scroll_vert = TRUE;
2408                 priv->scroll.last_a = angle(priv, hw->x, hw->y);
2409                 DBG(7, "circular scroll detected on edge\n");
2410             }
2411         }
2412     }
2413     if (!priv->circ_scroll_on) {
2414         if (finger) {
2415             if (hw->numFingers == 2) {
2416                 if (!priv->vert_scroll_twofinger_on &&
2417                     (para->scroll_twofinger_vert) &&
2418                     (para->scroll_dist_vert != 0)) {
2419                     stop_coasting(priv);
2420                     priv->vert_scroll_twofinger_on = TRUE;
2421                     priv->vert_scroll_edge_on = FALSE;
2422                     priv->scroll.last_y = hw->y;
2423                     DBG(7, "vert two-finger scroll detected\n");
2424                 }
2425                 if (!priv->horiz_scroll_twofinger_on &&
2426                     (para->scroll_twofinger_horiz) &&
2427                     (para->scroll_dist_horiz != 0)) {
2428                     stop_coasting(priv);
2429                     priv->horiz_scroll_twofinger_on = TRUE;
2430                     priv->horiz_scroll_edge_on = FALSE;
2431                     priv->scroll.last_x = hw->x;
2432                     DBG(7, "horiz two-finger scroll detected\n");
2433                 }
2434             }
2435         }
2436         if (finger && priv->finger_state == FS_UNTOUCHED) {
2437             if (!priv->vert_scroll_twofinger_on &&
2438                 !priv->horiz_scroll_twofinger_on) {
2439                 if ((para->scroll_edge_vert) && (para->scroll_dist_vert != 0) &&
2440                     (edge & RIGHT_EDGE)) {
2441                     priv->vert_scroll_edge_on = TRUE;
2442                     priv->scroll.last_y = hw->y;
2443                     DBG(7, "vert edge scroll detected on right edge\n");
2444                 }
2445                 if ((para->scroll_edge_horiz) && (para->scroll_dist_horiz != 0)
2446                     && (edge & BOTTOM_EDGE)) {
2447                     priv->horiz_scroll_edge_on = TRUE;
2448                     priv->scroll.last_x = hw->x;
2449                     DBG(7, "horiz edge scroll detected on bottom edge\n");
2450                 }
2451             }
2452         }
2453     }
2454     {
2455         Bool oldv = priv->vert_scroll_twofinger_on || priv->vert_scroll_edge_on
2456             || (priv->circ_scroll_on && priv->circ_scroll_vert);
2457 
2458         Bool oldh = priv->horiz_scroll_twofinger_on ||
2459             priv->horiz_scroll_edge_on || (priv->circ_scroll_on &&
2460                                            !priv->circ_scroll_vert);
2461 
2462         Bool oldc = priv->circ_scroll_on;
2463 
2464         if (priv->circ_scroll_on && !finger) {
2465             /* circular scroll locks in until finger is raised */
2466             DBG(7, "cicular scroll off\n");
2467             priv->circ_scroll_on = FALSE;
2468         }
2469 
2470         if (!finger || hw->numFingers != 2) {
2471             if (priv->vert_scroll_twofinger_on) {
2472                 DBG(7, "vert two-finger scroll off\n");
2473                 priv->vert_scroll_twofinger_on = FALSE;
2474             }
2475             if (priv->horiz_scroll_twofinger_on) {
2476                 DBG(7, "horiz two-finger scroll off\n");
2477                 priv->horiz_scroll_twofinger_on = FALSE;
2478             }
2479         }
2480 
2481         if (priv->vert_scroll_edge_on && (!(edge & RIGHT_EDGE) || !finger)) {
2482             DBG(7, "vert edge scroll off\n");
2483             priv->vert_scroll_edge_on = FALSE;
2484         }
2485         if (priv->horiz_scroll_edge_on && (!(edge & BOTTOM_EDGE) || !finger)) {
2486             DBG(7, "horiz edge scroll off\n");
2487             priv->horiz_scroll_edge_on = FALSE;
2488         }
2489         /* If we were corner edge scrolling (coasting),
2490          * but no longer in corner or raised a finger, then stop coasting. */
2491         if (para->scroll_edge_corner &&
2492             (priv->scroll.coast_speed_x || priv->scroll.coast_speed_y)) {
2493             Bool is_in_corner = ((edge & RIGHT_EDGE) &&
2494                                  (edge & (TOP_EDGE | BOTTOM_EDGE))) ||
2495                 ((edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE)));
2496             if (!is_in_corner || !finger) {
2497                 DBG(7, "corner edge scroll off\n");
2498                 stop_coasting(priv);
2499             }
2500         }
2501         /* if we were scrolling, but couldn't corner edge scroll,
2502          * and are no longer scrolling, then start coasting */
2503         oldv = oldv && !(priv->vert_scroll_twofinger_on ||
2504                          priv->vert_scroll_edge_on || (priv->circ_scroll_on &&
2505                                                        priv->circ_scroll_vert));
2506 
2507         oldh = oldh && !(priv->horiz_scroll_twofinger_on ||
2508                          priv->horiz_scroll_edge_on || (priv->circ_scroll_on &&
2509                                                         !priv->
2510                                                         circ_scroll_vert));
2511 
2512         oldc = oldc && !priv->circ_scroll_on;
2513 
2514         if ((oldv || oldh) && !para->scroll_edge_corner) {
2515             start_coasting(priv, hw, oldv, oldh, oldc);
2516         }
2517     }
2518 
2519     /* if hitting a corner (top right or bottom right) while vertical
2520      * scrolling is active, consider starting corner edge scrolling or
2521      * switching over to circular scrolling smoothly */
2522     if (priv->vert_scroll_edge_on && !priv->horiz_scroll_edge_on &&
2523         (edge & RIGHT_EDGE) && (edge & (TOP_EDGE | BOTTOM_EDGE))) {
2524         if (para->scroll_edge_corner) {
2525             if (priv->scroll.coast_speed_y == 0) {
2526                 /* FYI: We can generate multiple start_coasting requests if
2527                  * we're in the corner, but we were moving so slowly when we
2528                  * got here that we didn't actually start coasting. */
2529                 DBG(7, "corner edge scroll on\n");
2530                 start_coasting(priv, hw, TRUE, FALSE, FALSE);
2531             }
2532         }
2533         else if (para->circular_scrolling) {
2534             priv->vert_scroll_edge_on = FALSE;
2535             priv->circ_scroll_on = TRUE;
2536             priv->circ_scroll_vert = TRUE;
2537             priv->scroll.last_a = angle(priv, hw->x, hw->y);
2538             DBG(7, "switching to circular scrolling\n");
2539         }
2540     }
2541     /* Same treatment for horizontal scrolling */
2542     if (priv->horiz_scroll_edge_on && !priv->vert_scroll_edge_on &&
2543         (edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) {
2544         if (para->scroll_edge_corner) {
2545             if (priv->scroll.coast_speed_x == 0) {
2546                 /* FYI: We can generate multiple start_coasting requests if
2547                  * we're in the corner, but we were moving so slowly when we
2548                  * got here that we didn't actually start coasting. */
2549                 DBG(7, "corner edge scroll on\n");
2550                 start_coasting(priv, hw, FALSE, TRUE, FALSE);
2551             }
2552         }
2553         else if (para->circular_scrolling) {
2554             priv->horiz_scroll_edge_on = FALSE;
2555             priv->circ_scroll_on = TRUE;
2556             priv->circ_scroll_vert = FALSE;
2557             priv->scroll.last_a = angle(priv, hw->x, hw->y);
2558             DBG(7, "switching to circular scrolling\n");
2559         }
2560     }
2561 
2562     if (priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
2563         priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
2564         priv->circ_scroll_on) {
2565         priv->scroll.packets_this_scroll++;
2566     }
2567 
2568     if (priv->vert_scroll_edge_on || priv->vert_scroll_twofinger_on) {
2569         /* + = down, - = up */
2570         if (para->scroll_dist_vert != 0 && hw->y != priv->scroll.last_y) {
2571             priv->scroll.delta_y += (hw->y - priv->scroll.last_y);
2572             priv->scroll.last_y = hw->y;
2573         }
2574     }
2575     if (priv->horiz_scroll_edge_on || priv->horiz_scroll_twofinger_on) {
2576         /* + = right, - = left */
2577         if (para->scroll_dist_horiz != 0 && hw->x != priv->scroll.last_x) {
2578             priv->scroll.delta_x += (hw->x - priv->scroll.last_x);
2579             priv->scroll.last_x = hw->x;
2580         }
2581     }
2582     if (priv->circ_scroll_on) {
2583         /* + = counter clockwise, - = clockwise */
2584         double delta = para->scroll_dist_circ;
2585         double diff = diffa(priv->scroll.last_a, angle(priv, hw->x, hw->y));
2586 
2587         if (delta >= 0.005 && diff != 0.0) {
2588             if (priv->circ_scroll_vert)
2589                 priv->scroll.delta_y -= diff / delta * para->scroll_dist_vert;
2590             else
2591                 priv->scroll.delta_x -= diff / delta * para->scroll_dist_horiz;
2592             priv->scroll.last_a = angle(priv, hw->x, hw->y);
2593         }
2594     }
2595 
2596     if (priv->scroll.coast_speed_y) {
2597         double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0;
2598         double ddy = para->coasting_friction * dtime;
2599 
2600         priv->scroll.delta_y += priv->scroll.coast_speed_y * dtime * abs(para->scroll_dist_vert);
2601         delay = MIN(delay, POLL_MS);
2602         if (fabs(priv->scroll.coast_speed_y) < ddy) {
2603             priv->scroll.coast_speed_y = 0;
2604             priv->scroll.packets_this_scroll = 0;
2605         }
2606         else {
2607             priv->scroll.coast_speed_y +=
2608                 (priv->scroll.coast_speed_y < 0 ? ddy : -ddy);
2609         }
2610     }
2611 
2612     if (priv->scroll.coast_speed_x) {
2613         double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0;
2614         double ddx = para->coasting_friction * dtime;
2615         priv->scroll.delta_x += priv->scroll.coast_speed_x * dtime * abs(para->scroll_dist_horiz);
2616         delay = MIN(delay, POLL_MS);
2617         if (fabs(priv->scroll.coast_speed_x) < ddx) {
2618             priv->scroll.coast_speed_x = 0;
2619             priv->scroll.packets_this_scroll = 0;
2620         }
2621         else {
2622             priv->scroll.coast_speed_x +=
2623                 (priv->scroll.coast_speed_x < 0 ? ddx : -ddx);
2624         }
2625     }
2626 
2627     return delay;
2628 }
2629 
2630 /**
2631  * Check if any 2+ fingers are close enough together to assume this is a
2632  * ClickFinger action.
2633  */
2634 static int
clickpad_guess_clickfingers(SynapticsPrivate * priv,struct SynapticsHwState * hw)2635 clickpad_guess_clickfingers(SynapticsPrivate * priv,
2636                             struct SynapticsHwState *hw)
2637 {
2638     int nfingers = 0;
2639     uint32_t close_point = 0; /* 1 bit for each point close to another one */
2640     int i, j;
2641 
2642     BUG_RETURN_VAL(hw->num_mt_mask > sizeof(close_point) * 8, 0);
2643 
2644     for (i = 0; i < hw->num_mt_mask - 1; i++) {
2645         ValuatorMask *f1;
2646 
2647         if (hw->slot_state[i] == SLOTSTATE_EMPTY ||
2648             hw->slot_state[i] == SLOTSTATE_CLOSE)
2649             continue;
2650 
2651         f1 = hw->mt_mask[i];
2652 
2653         for (j = i + 1; j < hw->num_mt_mask; j++) {
2654             ValuatorMask *f2;
2655             double x1, x2, y1, y2;
2656 
2657             if (hw->slot_state[j] == SLOTSTATE_EMPTY ||
2658                 hw->slot_state[j] == SLOTSTATE_CLOSE)
2659                 continue;
2660 
2661             f2 = hw->mt_mask[j];
2662 
2663             x1 = valuator_mask_get_double(f1, 0);
2664             y1 = valuator_mask_get_double(f1, 1);
2665 
2666             x2 = valuator_mask_get_double(f2, 0);
2667             y2 = valuator_mask_get_double(f2, 1);
2668 
2669             /* FIXME: fingers closer together than 30% of touchpad width, but
2670              * really, this should be dependent on the touchpad size. Also,
2671              * you'll need to find a touchpad that doesn't lie about it's
2672              * size. Good luck. */
2673             if (fabs(x1 - x2) < (priv->maxx - priv->minx) * .3 &&
2674                 fabs(y1 - y2) < (priv->maxy - priv->miny) * .3) {
2675                 close_point |= (1 << j);
2676                 close_point |= (1 << i);
2677             }
2678         }
2679     }
2680 
2681     while (close_point > 0) {
2682         nfingers += close_point & 0x1;
2683         close_point >>= 1;
2684     }
2685 
2686     /* Some trackpads touchpad only track two touchpoints but announce
2687      * BTN_TOOL_TRIPLETAP (which sets hw->numFingers to 3), when this happens
2688      * the user likely intents to do a 3 finger click, so handle it as such.
2689      */
2690     if (hw->numFingers >= 3 && hw->num_mt_mask < 3)
2691         nfingers = 3;
2692 
2693     return nfingers;
2694 }
2695 
2696 static void
handle_clickfinger(SynapticsPrivate * priv,struct SynapticsHwState * hw)2697 handle_clickfinger(SynapticsPrivate * priv, struct SynapticsHwState *hw)
2698 {
2699     SynapticsParameters *para = &priv->synpara;
2700     int action = 0;
2701     int nfingers = hw->numFingers;
2702 
2703     /* if this is a clickpad, clickfinger handling is:
2704      * one finger down: no action, this is a normal click
2705      * two fingers down: F2_CLICK
2706      * three fingers down: F3_CLICK
2707      */
2708 
2709     if (para->clickpad)
2710         nfingers = clickpad_guess_clickfingers(priv, hw);
2711 
2712     switch (nfingers) {
2713     case 1:
2714         action = para->click_action[F1_CLICK1];
2715         break;
2716     case 2:
2717         action = para->click_action[F2_CLICK1];
2718         break;
2719     case 3:
2720         action = para->click_action[F3_CLICK1];
2721         break;
2722     }
2723     switch (action) {
2724     case 1:
2725         hw->left = 1 | BTN_EMULATED_FLAG;
2726         break;
2727     case 2:
2728         hw->left = 0;
2729         hw->middle = 1 | BTN_EMULATED_FLAG;
2730         break;
2731     case 3:
2732         hw->left = 0;
2733         hw->right = 1 | BTN_EMULATED_FLAG;
2734         break;
2735     }
2736 }
2737 
2738 /* Adjust the hardware state according to the extra buttons (if the touchpad
2739  * has any and not many touchpads do these days). These buttons are up/down
2740  * tilt buttons and/or left/right buttons that then map into a specific
2741  * function (or scrolling into).
2742  */
2743 static Bool
adjust_state_from_scrollbuttons(const InputInfoPtr pInfo,struct SynapticsHwState * hw)2744 adjust_state_from_scrollbuttons(const InputInfoPtr pInfo,
2745                                 struct SynapticsHwState *hw)
2746 {
2747     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
2748     SynapticsParameters *para = &priv->synpara;
2749     Bool double_click = FALSE;
2750 
2751     if (!para->updown_button_scrolling) {
2752         if (hw->down) {         /* map down button to middle button */
2753             hw->middle = TRUE;
2754         }
2755 
2756         if (hw->up) {           /* up button generates double click */
2757             if (!priv->prev_up)
2758                 double_click = TRUE;
2759         }
2760         priv->prev_up = hw->up;
2761 
2762         /* reset up/down button events */
2763         hw->up = hw->down = FALSE;
2764     }
2765 
2766     /* Left/right button scrolling, or middle clicks */
2767     if (!para->leftright_button_scrolling) {
2768         if (hw->multi[2] || hw->multi[3])
2769             hw->middle = TRUE;
2770 
2771         /* reset left/right button events */
2772         hw->multi[2] = hw->multi[3] = FALSE;
2773     }
2774 
2775     return double_click;
2776 }
2777 
2778 static void
update_hw_button_state(const InputInfoPtr pInfo,struct SynapticsHwState * hw,CARD32 now,int * delay)2779 update_hw_button_state(const InputInfoPtr pInfo, struct SynapticsHwState *hw,
2780                        CARD32 now, int *delay)
2781 {
2782     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
2783     SynapticsParameters *para = &priv->synpara;
2784 
2785     /* Treat the first two multi buttons as up/down for now. */
2786     hw->up |= hw->multi[0];
2787     hw->down |= hw->multi[1];
2788 
2789     /* 3rd button emulation */
2790     hw->middle |= HandleMidButtonEmulation(priv, hw, now, delay);
2791 
2792     /* If this is a clickpad and the user clicks in a soft button area, press
2793      * the soft button instead. */
2794     if (para->clickpad) {
2795         /* hw->left is down, but no other buttons were already down */
2796         if (!(priv->lastButtons & 7) && hw->left && !hw->right && !hw->middle) {
2797             /* If the finger down event is delayed, the x and y
2798              * coordinates are stale so we delay processing the click */
2799             if (hw->z < para->finger_low) {
2800                 hw->left = 0;
2801                 goto out;
2802             }
2803             if (is_inside_rightbutton_area(para, hw->x, hw->y)) {
2804                 hw->left = 0;
2805                 hw->right = 1;
2806             }
2807             else if (is_inside_sec_rightbutton_area(para, hw->x, hw->y)) {
2808                 hw->left = 0;
2809                 hw->right = 1;
2810             }
2811             else if (is_inside_middlebutton_area(para, hw->x, hw->y)) {
2812                 hw->left = 0;
2813                 hw->middle = 1;
2814             }
2815             else if (is_inside_sec_middlebutton_area(para, hw->x, hw->y)) {
2816                 hw->left = 0;
2817                 hw->middle = 1;
2818             }
2819             priv->clickpad_click_millis = now;
2820         }
2821         else if (hw->left) {
2822             hw->left   = (priv->lastButtons & 1) ? 1 : 0;
2823             hw->middle = (priv->lastButtons & 2) ? 1 : 0;
2824             hw->right  = (priv->lastButtons & 4) ? 1 : 0;
2825         }
2826     }
2827 
2828     /* Fingers emulate other buttons. ClickFinger can only be
2829        triggered on transition, when left is pressed
2830      */
2831     if (hw->left && !(priv->lastButtons & 7) && hw->numFingers >= 1)
2832         handle_clickfinger(priv, hw);
2833 
2834 out:
2835     /* Two finger emulation */
2836     if (hw->numFingers == 1 && hw->z >= para->emulate_twofinger_z &&
2837         hw->fingerWidth >= para->emulate_twofinger_w) {
2838         hw->numFingers = 2;
2839     }
2840 }
2841 
2842 static void
post_button_click(const InputInfoPtr pInfo,const int button)2843 post_button_click(const InputInfoPtr pInfo, const int button)
2844 {
2845     xf86PostButtonEvent(pInfo->dev, FALSE, button, TRUE, 0, 0);
2846     xf86PostButtonEvent(pInfo->dev, FALSE, button, FALSE, 0, 0);
2847 }
2848 
2849 static void
post_scroll_events(const InputInfoPtr pInfo)2850 post_scroll_events(const InputInfoPtr pInfo)
2851 {
2852     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
2853 
2854     valuator_mask_zero(priv->scroll_events_mask);
2855 
2856     if (priv->scroll.delta_y != 0.0) {
2857         valuator_mask_set_double(priv->scroll_events_mask,
2858                                  priv->scroll_axis_vert, priv->scroll.delta_y);
2859         priv->scroll.delta_y = 0;
2860     }
2861     if (priv->scroll.delta_x != 0.0) {
2862         valuator_mask_set_double(priv->scroll_events_mask,
2863                                  priv->scroll_axis_horiz, priv->scroll.delta_x);
2864         priv->scroll.delta_x = 0;
2865     }
2866     if (valuator_mask_num_valuators(priv->scroll_events_mask))
2867         xf86PostMotionEventM(pInfo->dev, FALSE, priv->scroll_events_mask);
2868 }
2869 
2870 static inline int
repeat_scrollbuttons(const InputInfoPtr pInfo,const struct SynapticsHwState * hw,int buttons,CARD32 now,int delay)2871 repeat_scrollbuttons(const InputInfoPtr pInfo,
2872                      const struct SynapticsHwState *hw,
2873                      int buttons, CARD32 now, int delay)
2874 {
2875     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
2876     SynapticsParameters *para = &priv->synpara;
2877     int repeat_delay, timeleft;
2878     int rep_buttons = 0;
2879 
2880     if (para->updown_button_repeat)
2881         rep_buttons |= (1 << (4 - 1)) | (1 << (5 - 1));
2882     if (para->leftright_button_repeat)
2883         rep_buttons |= (1 << (6 - 1)) | (1 << (7 - 1));
2884 
2885     /* Handle auto repeat buttons */
2886     repeat_delay = clamp(para->scroll_button_repeat, SBR_MIN, SBR_MAX);
2887     if (((hw->up || hw->down) && para->updown_button_repeat &&
2888          para->updown_button_scrolling) ||
2889         ((hw->multi[2] || hw->multi[3]) && para->leftright_button_repeat &&
2890          para->leftright_button_scrolling)) {
2891         priv->repeatButtons = buttons & rep_buttons;
2892         if (!priv->nextRepeat) {
2893             priv->nextRepeat = now + repeat_delay * 2;
2894         }
2895     }
2896     else {
2897         priv->repeatButtons = 0;
2898         priv->nextRepeat = 0;
2899     }
2900 
2901     if (priv->repeatButtons) {
2902         timeleft = TIME_DIFF(priv->nextRepeat, now);
2903         if (timeleft > 0)
2904             delay = MIN(delay, timeleft);
2905         if (timeleft <= 0) {
2906             int change, id;
2907 
2908             change = priv->repeatButtons;
2909             while (change) {
2910                 id = ffs(change);
2911                 change &= ~(1 << (id - 1));
2912                 if (id == 4)
2913                     priv->scroll.delta_y -= para->scroll_dist_vert;
2914                 else if (id == 5)
2915                     priv->scroll.delta_y += para->scroll_dist_vert;
2916                 else if (id == 6)
2917                     priv->scroll.delta_x -= para->scroll_dist_horiz;
2918                 else if (id == 7)
2919                     priv->scroll.delta_x += para->scroll_dist_horiz;
2920             }
2921 
2922             priv->nextRepeat = now + repeat_delay;
2923             delay = MIN(delay, repeat_delay);
2924         }
2925     }
2926 
2927     return delay;
2928 }
2929 
2930 /* Update the open slots and number of active touches */
2931 static void
UpdateTouchState(InputInfoPtr pInfo,struct SynapticsHwState * hw)2932 UpdateTouchState(InputInfoPtr pInfo, struct SynapticsHwState *hw)
2933 {
2934     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
2935     int i;
2936 
2937     for (i = 0; i < hw->num_mt_mask; i++) {
2938         if (hw->slot_state[i] == SLOTSTATE_OPEN) {
2939             priv->open_slots[priv->num_active_touches] = i;
2940             priv->num_active_touches++;
2941             BUG_WARN(priv->num_active_touches > priv->num_slots);
2942         }
2943         else if (hw->slot_state[i] == SLOTSTATE_CLOSE) {
2944             Bool found = FALSE;
2945             int j;
2946 
2947             for (j = 0; j < priv->num_active_touches - 1; j++) {
2948                 if (priv->open_slots[j] == i)
2949                     found = TRUE;
2950 
2951                 if (found)
2952                     priv->open_slots[j] = priv->open_slots[j + 1];
2953             }
2954 
2955             BUG_WARN(priv->num_active_touches == 0);
2956             if (priv->num_active_touches > 0)
2957                 priv->num_active_touches--;
2958         }
2959     }
2960 
2961     SynapticsResetTouchHwState(hw, FALSE);
2962 }
2963 
2964 static void
filter_jitter(SynapticsPrivate * priv,int * x,int * y)2965 filter_jitter(SynapticsPrivate * priv, int *x, int *y)
2966 {
2967     SynapticsParameters *para = &priv->synpara;
2968 
2969     priv->hyst_center_x = hysteresis(*x, priv->hyst_center_x, para->hyst_x);
2970     priv->hyst_center_y = hysteresis(*y, priv->hyst_center_y, para->hyst_y);
2971     *x = priv->hyst_center_x;
2972     *y = priv->hyst_center_y;
2973 }
2974 
2975 static void
reset_hw_state(struct SynapticsHwState * hw)2976 reset_hw_state(struct SynapticsHwState *hw)
2977 {
2978     hw->x = 0;
2979     hw->y = 0;
2980     hw->z = 0;
2981     hw->numFingers = 0;
2982     hw->fingerWidth = 0;
2983 }
2984 
2985 /*
2986  * React on changes in the hardware state. This function is called every time
2987  * the hardware state changes. The return value is used to specify how many
2988  * milliseconds to wait before calling the function again if no state change
2989  * occurs.
2990  *
2991  * from_timer denotes if HandleState was triggered from a timer (e.g. to
2992  * generate fake motion events, or for the tap-to-click state machine), rather
2993  * than from having received a motion event.
2994  */
2995 static int
HandleState(InputInfoPtr pInfo,struct SynapticsHwState * hw,CARD32 now,Bool from_timer)2996 HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now,
2997             Bool from_timer)
2998 {
2999     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
3000     SynapticsParameters *para = &priv->synpara;
3001     enum FingerState finger = FS_UNTOUCHED;
3002     int dx = 0, dy = 0, buttons, id;
3003     enum EdgeType edge = NO_EDGE;
3004     int change;
3005     int double_click = FALSE;
3006     int delay = 1000000000;
3007     int timeleft;
3008     Bool inside_active_area;
3009     Bool using_cumulative_coords = FALSE;
3010     Bool ignore_motion;
3011 
3012     /* We need both and x/y, the driver can't handle just one of the two
3013      * yet. But since it's possible to hit a phys button on non-clickpads
3014      * without ever getting motion data first, we must continue with 0/0 for
3015      * that case. */
3016     if (hw->x == INT_MIN || hw->y == INT_MAX) {
3017         if (para->clickpad)
3018             return delay;
3019         else if (hw->left || hw->right || hw->middle) {
3020             hw->x = (hw->x == INT_MIN) ? 0 : hw->x;
3021             hw->y = (hw->y == INT_MIN) ? 0 : hw->y;
3022         }
3023     }
3024 
3025     /* If a physical button is pressed on a clickpad or a two-finger scrolling
3026      * is ongoing, use cumulative relative touch movements for motion */
3027     if (para->clickpad &&
3028         ((priv->lastButtons & 7) ||
3029         (priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on)) &&
3030         priv->last_button_area != TOP_BUTTON_AREA) {
3031         hw->x = hw->cumulative_dx;
3032         hw->y = hw->cumulative_dy;
3033         using_cumulative_coords = TRUE;
3034     }
3035 
3036     /* apply hysteresis before doing anything serious. This cancels
3037      * out a lot of noise which might surface in strange phenomena
3038      * like flicker in scrolling or noise motion. */
3039     filter_jitter(priv, &hw->x, &hw->y);
3040 
3041     inside_active_area = is_inside_active_area(priv, hw->x, hw->y);
3042 
3043     /* Ignore motion *starting* inside softbuttonareas */
3044     if (priv->finger_state < FS_TOUCHED)
3045         priv->last_button_area = current_button_area(para, hw->x, hw->y);
3046     /* If we already have a finger down, clear last_button_area if it goes
3047        outside of the softbuttonareas */
3048     else if (priv->last_button_area != NO_BUTTON_AREA &&
3049              current_button_area(para, hw->x, hw->y) == NO_BUTTON_AREA)
3050         priv->last_button_area = NO_BUTTON_AREA;
3051 
3052     ignore_motion = para->touchpad_off == TOUCHPAD_OFF ||
3053         (!using_cumulative_coords && priv->last_button_area != NO_BUTTON_AREA);
3054 
3055     /* these two just update hw->left, right, etc. */
3056     update_hw_button_state(pInfo, hw, now, &delay);
3057     if (priv->has_scrollbuttons)
3058         double_click = adjust_state_from_scrollbuttons(pInfo, hw);
3059 
3060     /* Ignore motion the first X ms after a clickpad click */
3061     if (priv->clickpad_click_millis) {
3062         if(TIME_DIFF(priv->clickpad_click_millis +
3063                      para->clickpad_ignore_motion_time, now) > 0)
3064             ignore_motion = TRUE;
3065         else
3066             priv->clickpad_click_millis = 0;
3067     }
3068 
3069     /* now we know that these _coordinates_ aren't in the area.
3070        invalid are: x, y, z, numFingers, fingerWidth
3071        valid are: millis, left/right/middle/up/down/etc.
3072      */
3073     if (!inside_active_area)
3074         reset_hw_state(hw);
3075 
3076     /* no edge or finger detection outside of area */
3077     if (inside_active_area) {
3078         edge = edge_detection(priv, hw->x, hw->y);
3079         if (!from_timer)
3080             finger = SynapticsDetectFinger(priv, hw);
3081         else
3082             finger = priv->finger_state;
3083     }
3084 
3085     /* tap and drag detection. Needs to be performed even if the finger is in
3086      * the dead area to reset the state. */
3087     timeleft = HandleTapProcessing(priv, hw, now, finger, inside_active_area);
3088     if (timeleft > 0)
3089         delay = MIN(delay, timeleft);
3090 
3091     if (inside_active_area) {
3092         /* Don't bother about scrolling in the dead area of the touchpad. */
3093         timeleft = HandleScrolling(priv, hw, edge, (finger >= FS_TOUCHED));
3094         if (timeleft > 0)
3095             delay = MIN(delay, timeleft);
3096 
3097         /*
3098          * Compensate for unequal x/y resolution. This needs to be done after
3099          * calculations that require unadjusted coordinates, for example edge
3100          * detection.
3101          */
3102 #ifndef NO_DRIVER_SCALING
3103         ScaleCoordinates(priv, hw);
3104 #endif
3105     }
3106 
3107     dx = dy = 0;
3108 
3109     timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy, inside_active_area);
3110     delay = MIN(delay, timeleft);
3111 
3112     buttons = ((hw->left ? 0x01 : 0) |
3113                (hw->middle ? 0x02 : 0) |
3114                (hw->right ? 0x04 : 0) |
3115                (hw->up ? 0x08 : 0) |
3116                (hw->down ? 0x10 : 0) |
3117                (hw->multi[2] ? 0x20 : 0) | (hw->multi[3] ? 0x40 : 0));
3118 
3119     if (priv->tap_button > 0 && priv->tap_button_state == TBS_BUTTON_DOWN)
3120         buttons |= 1 << (priv->tap_button - 1);
3121 
3122     /* Post events */
3123     if (finger >= FS_TOUCHED && (dx || dy) && !ignore_motion)
3124         xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
3125 
3126     if (priv->mid_emu_state == MBE_LEFT_CLICK) {
3127         post_button_click(pInfo, 1);
3128         priv->mid_emu_state = MBE_OFF;
3129     }
3130     else if (priv->mid_emu_state == MBE_RIGHT_CLICK) {
3131         post_button_click(pInfo, 3);
3132         priv->mid_emu_state = MBE_OFF;
3133     }
3134 
3135     change = buttons ^ priv->lastButtons;
3136     while (change) {
3137         id = ffs(change);       /* number of first set bit 1..32 is returned */
3138         change &= ~(1 << (id - 1));
3139         xf86PostButtonEvent(pInfo->dev, FALSE, id, (buttons & (1 << (id - 1))),
3140                             0, 0);
3141     }
3142 
3143     if (priv->has_scrollbuttons)
3144         delay = repeat_scrollbuttons(pInfo, hw, buttons, now, delay);
3145 
3146     /* Process scroll events only if coordinates are
3147      * in the Synaptics Area
3148      */
3149     if (inside_active_area &&
3150         (priv->scroll.delta_x != 0.0 || priv->scroll.delta_y != 0.0)) {
3151         post_scroll_events(pInfo);
3152         priv->scroll.last_millis = hw->millis;
3153     }
3154 
3155     if (double_click) {
3156         post_button_click(pInfo, 1);
3157         post_button_click(pInfo, 1);
3158     }
3159 
3160     UpdateTouchState(pInfo, hw);
3161 
3162     /* Save old values of some state variables */
3163     priv->finger_state = finger;
3164     priv->lastButtons = buttons;
3165 
3166     /* generate a history of the absolute positions */
3167     if (inside_active_area)
3168         store_history(priv, hw->x, hw->y, hw->millis);
3169 
3170     return delay;
3171 }
3172 
3173 static int
ControlProc(InputInfoPtr pInfo,xDeviceCtl * control)3174 ControlProc(InputInfoPtr pInfo, xDeviceCtl * control)
3175 {
3176     DBG(3, "Control Proc called\n");
3177     return Success;
3178 }
3179 
3180 static int
SwitchMode(ClientPtr client,DeviceIntPtr dev,int mode)3181 SwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
3182 {
3183     DBG(3, "SwitchMode called\n");
3184 
3185     return XI_BadMode;
3186 }
3187 
3188 static void
ReadDevDimensions(InputInfoPtr pInfo)3189 ReadDevDimensions(InputInfoPtr pInfo)
3190 {
3191     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
3192 
3193     if (priv->proto_ops->ReadDevDimensions)
3194         priv->proto_ops->ReadDevDimensions(pInfo);
3195 
3196     SanitizeDimensions(pInfo);
3197 }
3198 
3199 static Bool
QueryHardware(InputInfoPtr pInfo)3200 QueryHardware(InputInfoPtr pInfo)
3201 {
3202     SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
3203 
3204     priv->comm.protoBufTail = 0;
3205 
3206     if (!priv->proto_ops->QueryHardware(pInfo)) {
3207         xf86IDrvMsg(pInfo, X_PROBED, "no supported touchpad found\n");
3208         if (priv->proto_ops->DeviceOffHook)
3209             priv->proto_ops->DeviceOffHook(pInfo);
3210         return FALSE;
3211     }
3212 
3213     return TRUE;
3214 }
3215 
3216 #ifndef NO_DRIVER_SCALING
3217 static void
ScaleCoordinates(SynapticsPrivate * priv,struct SynapticsHwState * hw)3218 ScaleCoordinates(SynapticsPrivate * priv, struct SynapticsHwState *hw)
3219 {
3220     int xCenter = (priv->synpara.left_edge + priv->synpara.right_edge) / 2;
3221     int yCenter = (priv->synpara.top_edge + priv->synpara.bottom_edge) / 2;
3222 
3223     hw->x = (hw->x - xCenter) * priv->horiz_coeff + xCenter;
3224     hw->y = (hw->y - yCenter) * priv->vert_coeff + yCenter;
3225 }
3226 
3227 void
CalculateScalingCoeffs(SynapticsPrivate * priv)3228 CalculateScalingCoeffs(SynapticsPrivate * priv)
3229 {
3230     int vertRes = priv->synpara.resolution_vert;
3231     int horizRes = priv->synpara.resolution_horiz;
3232 
3233     if ((horizRes > vertRes) && (horizRes > 0)) {
3234         priv->horiz_coeff = vertRes / (double) horizRes;
3235         priv->vert_coeff = 1;
3236     }
3237     else if ((horizRes < vertRes) && (vertRes > 0)) {
3238         priv->horiz_coeff = 1;
3239         priv->vert_coeff = horizRes / (double) vertRes;
3240     }
3241     else {
3242         priv->horiz_coeff = 1;
3243         priv->vert_coeff = 1;
3244     }
3245 }
3246 #endif
3247