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