Guest User

synaptics.c

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