The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/input/atp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2014 Rohit Grover
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * Some tables, structures, definitions and constant values for the
   31  * touchpad protocol has been copied from Linux's
   32  * "drivers/input/mouse/bcm5974.c" which has the following copyright
   33  * holders under GPLv2. All device specific code in this driver has
   34  * been written from scratch. The decoding algorithm is based on
   35  * output from FreeBSD's usbdump.
   36  *
   37  * Copyright (C) 2008      Henrik Rydberg (rydberg@euromail.se)
   38  * Copyright (C) 2008      Scott Shawcroft (scott.shawcroft@gmail.com)
   39  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
   40  * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
   41  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
   42  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
   43  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
   44  * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
   45  * Copyright (C) 2006      Nicolas Boichat (nicolas@boichat.ch)
   46  */
   47 
   48 /*
   49  * Author's note: 'atp' supports two distinct families of Apple trackpad
   50  * products: the older Fountain/Geyser and the latest Wellspring trackpads.
   51  * The first version made its appearance with FreeBSD 8 and worked only with
   52  * the Fountain/Geyser hardware. A fork of this driver for Wellspring was
   53  * contributed by Huang Wen Hui. This driver unifies the Wellspring effort
   54  * and also improves upon the original work.
   55  *
   56  * I'm grateful to Stephan Scheunig, Angela Naegele, and Nokia IT-support
   57  * for helping me with access to hardware. Thanks also go to Nokia for
   58  * giving me an opportunity to do this work.
   59  */
   60 
   61 #include <sys/cdefs.h>
   62 __FBSDID("$FreeBSD$");
   63 
   64 #include <sys/stdint.h>
   65 #include <sys/stddef.h>
   66 #include <sys/param.h>
   67 #include <sys/types.h>
   68 #include <sys/systm.h>
   69 #include <sys/kernel.h>
   70 #include <sys/bus.h>
   71 #include <sys/module.h>
   72 #include <sys/lock.h>
   73 #include <sys/mutex.h>
   74 #include <sys/sysctl.h>
   75 #include <sys/malloc.h>
   76 #include <sys/conf.h>
   77 #include <sys/fcntl.h>
   78 #include <sys/file.h>
   79 #include <sys/selinfo.h>
   80 #include <sys/poll.h>
   81 
   82 #include <dev/hid/hid.h>
   83 
   84 #include <dev/usb/usb.h>
   85 #include <dev/usb/usbdi.h>
   86 #include <dev/usb/usbdi_util.h>
   87 #include <dev/usb/usbhid.h>
   88 
   89 #include "usbdevs.h"
   90 
   91 #define USB_DEBUG_VAR atp_debug
   92 #include <dev/usb/usb_debug.h>
   93 
   94 #include <sys/mouse.h>
   95 
   96 #define ATP_DRIVER_NAME "atp"
   97 
   98 /*
   99  * Driver specific options: the following options may be set by
  100  * `options' statements in the kernel configuration file.
  101  */
  102 
  103 /* The divisor used to translate sensor reported positions to mickeys. */
  104 #ifndef ATP_SCALE_FACTOR
  105 #define ATP_SCALE_FACTOR                  16
  106 #endif
  107 
  108 /* Threshold for small movement noise (in mickeys) */
  109 #ifndef ATP_SMALL_MOVEMENT_THRESHOLD
  110 #define ATP_SMALL_MOVEMENT_THRESHOLD      30
  111 #endif
  112 
  113 /* Threshold of instantaneous deltas beyond which movement is considered fast.*/
  114 #ifndef ATP_FAST_MOVEMENT_TRESHOLD
  115 #define ATP_FAST_MOVEMENT_TRESHOLD        150
  116 #endif
  117 
  118 /*
  119  * This is the age in microseconds beyond which a touch is considered
  120  * to be a slide; and therefore a tap event isn't registered.
  121  */
  122 #ifndef ATP_TOUCH_TIMEOUT
  123 #define ATP_TOUCH_TIMEOUT                 125000
  124 #endif
  125 
  126 #ifndef ATP_IDLENESS_THRESHOLD
  127 #define ATP_IDLENESS_THRESHOLD 10
  128 #endif
  129 
  130 #ifndef FG_SENSOR_NOISE_THRESHOLD
  131 #define FG_SENSOR_NOISE_THRESHOLD 2
  132 #endif
  133 
  134 /*
  135  * A double-tap followed by a single-finger slide is treated as a
  136  * special gesture. The driver responds to this gesture by assuming a
  137  * virtual button-press for the lifetime of the slide. The following
  138  * threshold is the maximum time gap (in microseconds) between the two
  139  * tap events preceding the slide for such a gesture.
  140  */
  141 #ifndef ATP_DOUBLE_TAP_N_DRAG_THRESHOLD
  142 #define ATP_DOUBLE_TAP_N_DRAG_THRESHOLD   200000
  143 #endif
  144 
  145 /*
  146  * The wait duration in ticks after losing a touch contact before
  147  * zombied strokes are reaped and turned into button events.
  148  */
  149 #define ATP_ZOMBIE_STROKE_REAP_INTERVAL   (hz / 20)     /* 50 ms */
  150 
  151 /* The multiplier used to translate sensor reported positions to mickeys. */
  152 #define FG_SCALE_FACTOR                   380
  153 
  154 /*
  155  * The movement threshold for a stroke; this is the maximum difference
  156  * in position which will be resolved as a continuation of a stroke
  157  * component.
  158  */
  159 #define FG_MAX_DELTA_MICKEYS             ((3 * (FG_SCALE_FACTOR)) >> 1)
  160 
  161 /* Distance-squared threshold for matching a finger with a known stroke */
  162 #ifndef WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ
  163 #define WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ 1000000
  164 #endif
  165 
  166 /* Ignore pressure spans with cumulative press. below this value. */
  167 #define FG_PSPAN_MIN_CUM_PRESSURE         10
  168 
  169 /* Maximum allowed width for pressure-spans.*/
  170 #define FG_PSPAN_MAX_WIDTH                4
  171 
  172 /* end of driver specific options */
  173 
  174 /* Tunables */
  175 static SYSCTL_NODE(_hw_usb, OID_AUTO, atp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
  176     "USB ATP");
  177 
  178 #ifdef USB_DEBUG
  179 enum atp_log_level {
  180         ATP_LLEVEL_DISABLED = 0,
  181         ATP_LLEVEL_ERROR,
  182         ATP_LLEVEL_DEBUG,       /* for troubleshooting */
  183         ATP_LLEVEL_INFO,        /* for diagnostics */
  184 };
  185 static int atp_debug = ATP_LLEVEL_ERROR; /* the default is to only log errors */
  186 SYSCTL_INT(_hw_usb_atp, OID_AUTO, debug, CTLFLAG_RWTUN,
  187     &atp_debug, ATP_LLEVEL_ERROR, "ATP debug level");
  188 #endif /* USB_DEBUG */
  189 
  190 static u_int atp_touch_timeout = ATP_TOUCH_TIMEOUT;
  191 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, touch_timeout, CTLFLAG_RWTUN,
  192     &atp_touch_timeout, 125000, "age threshold in microseconds for a touch");
  193 
  194 static u_int atp_double_tap_threshold = ATP_DOUBLE_TAP_N_DRAG_THRESHOLD;
  195 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, double_tap_threshold, CTLFLAG_RWTUN,
  196     &atp_double_tap_threshold, ATP_DOUBLE_TAP_N_DRAG_THRESHOLD,
  197     "maximum time in microseconds to allow association between a double-tap and "
  198     "drag gesture");
  199 
  200 static u_int atp_mickeys_scale_factor = ATP_SCALE_FACTOR;
  201 static int atp_sysctl_scale_factor_handler(SYSCTL_HANDLER_ARGS);
  202 SYSCTL_PROC(_hw_usb_atp, OID_AUTO, scale_factor,
  203     CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
  204     &atp_mickeys_scale_factor, sizeof(atp_mickeys_scale_factor),
  205     atp_sysctl_scale_factor_handler, "IU",
  206     "movement scale factor");
  207 
  208 static u_int atp_small_movement_threshold = ATP_SMALL_MOVEMENT_THRESHOLD;
  209 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, small_movement, CTLFLAG_RWTUN,
  210     &atp_small_movement_threshold, ATP_SMALL_MOVEMENT_THRESHOLD,
  211     "the small movement black-hole for filtering noise");
  212 
  213 static u_int atp_tap_minimum = 1;
  214 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, tap_minimum, CTLFLAG_RWTUN,
  215     &atp_tap_minimum, 1, "Minimum number of taps before detection");
  216 
  217 /*
  218  * Strokes which accumulate at least this amount of absolute movement
  219  * from the aggregate of their components are considered as
  220  * slides. Unit: mickeys.
  221  */
  222 static u_int atp_slide_min_movement = 2 * ATP_SMALL_MOVEMENT_THRESHOLD;
  223 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, slide_min_movement, CTLFLAG_RWTUN,
  224     &atp_slide_min_movement, 2 * ATP_SMALL_MOVEMENT_THRESHOLD,
  225     "strokes with at least this amt. of movement are considered slides");
  226 
  227 /*
  228  * The minimum age of a stroke for it to be considered mature; this
  229  * helps filter movements (noise) from immature strokes. Units: interrupts.
  230  */
  231 static u_int atp_stroke_maturity_threshold = 4;
  232 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, stroke_maturity_threshold, CTLFLAG_RWTUN,
  233     &atp_stroke_maturity_threshold, 4,
  234     "the minimum age of a stroke for it to be considered mature");
  235 
  236 typedef enum atp_trackpad_family {
  237         TRACKPAD_FAMILY_FOUNTAIN_GEYSER,
  238         TRACKPAD_FAMILY_WELLSPRING,
  239         TRACKPAD_FAMILY_MAX /* keep this at the tail end of the enumeration */
  240 } trackpad_family_t;
  241 
  242 enum fountain_geyser_product {
  243         FOUNTAIN,
  244         GEYSER1,
  245         GEYSER1_17inch,
  246         GEYSER2,
  247         GEYSER3,
  248         GEYSER4,
  249         FOUNTAIN_GEYSER_PRODUCT_MAX /* keep this at the end */
  250 };
  251 
  252 enum wellspring_product {
  253         WELLSPRING1,
  254         WELLSPRING2,
  255         WELLSPRING3,
  256         WELLSPRING4,
  257         WELLSPRING4A,
  258         WELLSPRING5,
  259         WELLSPRING6A,
  260         WELLSPRING6,
  261         WELLSPRING5A,
  262         WELLSPRING7,
  263         WELLSPRING7A,
  264         WELLSPRING8,
  265         WELLSPRING_PRODUCT_MAX /* keep this at the end of the enumeration */
  266 };
  267 
  268 /* trackpad header types */
  269 enum fountain_geyser_trackpad_type {
  270         FG_TRACKPAD_TYPE_GEYSER1,
  271         FG_TRACKPAD_TYPE_GEYSER2,
  272         FG_TRACKPAD_TYPE_GEYSER3,
  273         FG_TRACKPAD_TYPE_GEYSER4,
  274 };
  275 enum wellspring_trackpad_type {
  276         WSP_TRACKPAD_TYPE1,      /* plain trackpad */
  277         WSP_TRACKPAD_TYPE2,      /* button integrated in trackpad */
  278         WSP_TRACKPAD_TYPE3       /* additional header fields since June 2013 */
  279 };
  280 
  281 /*
  282  * Trackpad family and product and family are encoded together in the
  283  * driver_info value associated with a trackpad product.
  284  */
  285 #define N_PROD_BITS 8  /* Number of bits used to encode product */
  286 #define ENCODE_DRIVER_INFO(FAMILY, PROD)      \
  287     (((FAMILY) << N_PROD_BITS) | (PROD))
  288 #define DECODE_FAMILY_FROM_DRIVER_INFO(INFO)  ((INFO) >> N_PROD_BITS)
  289 #define DECODE_PRODUCT_FROM_DRIVER_INFO(INFO) \
  290     ((INFO) & ((1 << N_PROD_BITS) - 1))
  291 
  292 #define FG_DRIVER_INFO(PRODUCT)               \
  293     ENCODE_DRIVER_INFO(TRACKPAD_FAMILY_FOUNTAIN_GEYSER, PRODUCT)
  294 #define WELLSPRING_DRIVER_INFO(PRODUCT)       \
  295     ENCODE_DRIVER_INFO(TRACKPAD_FAMILY_WELLSPRING, PRODUCT)
  296 
  297 /*
  298  * The following structure captures the state of a pressure span along
  299  * an axis. Each contact with the touchpad results in separate
  300  * pressure spans along the two axes.
  301  */
  302 typedef struct fg_pspan {
  303         u_int width;       /* in units of sensors */
  304         u_int cum;         /* cumulative compression (from all sensors) */
  305         u_int cog;         /* center of gravity */
  306         u_int loc;         /* location (scaled using the mickeys factor) */
  307         boolean_t matched; /* to track pspans as they match against strokes. */
  308 } fg_pspan;
  309 
  310 #define FG_MAX_PSPANS_PER_AXIS 3
  311 #define FG_MAX_STROKES         (2 * FG_MAX_PSPANS_PER_AXIS)
  312 
  313 #define WELLSPRING_INTERFACE_INDEX 1
  314 
  315 /* trackpad finger data offsets, le16-aligned */
  316 #define WSP_TYPE1_FINGER_DATA_OFFSET  (13 * 2)
  317 #define WSP_TYPE2_FINGER_DATA_OFFSET  (15 * 2)
  318 #define WSP_TYPE3_FINGER_DATA_OFFSET  (19 * 2)
  319 
  320 /* trackpad button data offsets */
  321 #define WSP_TYPE2_BUTTON_DATA_OFFSET   15
  322 #define WSP_TYPE3_BUTTON_DATA_OFFSET   23
  323 
  324 /* list of device capability bits */
  325 #define HAS_INTEGRATED_BUTTON   1
  326 
  327 /* trackpad finger structure - little endian */
  328 struct wsp_finger_sensor_data {
  329         int16_t origin;       /* zero when switching track finger */
  330         int16_t abs_x;        /* absolute x coordinate */
  331         int16_t abs_y;        /* absolute y coordinate */
  332         int16_t rel_x;        /* relative x coordinate */
  333         int16_t rel_y;        /* relative y coordinate */
  334         int16_t tool_major;   /* tool area, major axis */
  335         int16_t tool_minor;   /* tool area, minor axis */
  336         int16_t orientation;  /* 16384 when point, else 15 bit angle */
  337         int16_t touch_major;  /* touch area, major axis */
  338         int16_t touch_minor;  /* touch area, minor axis */
  339         int16_t unused[3];    /* zeros */
  340         int16_t multi;        /* one finger: varies, more fingers: constant */
  341 } __packed;
  342 
  343 typedef struct wsp_finger {
  344         /* to track fingers as they match against strokes. */
  345         boolean_t matched;
  346 
  347         /* location (scaled using the mickeys factor) */
  348         int x;
  349         int y;
  350 } wsp_finger_t;
  351 
  352 #define WSP_MAX_FINGERS               16
  353 #define WSP_SIZEOF_FINGER_SENSOR_DATA sizeof(struct wsp_finger_sensor_data)
  354 #define WSP_SIZEOF_ALL_FINGER_DATA    (WSP_MAX_FINGERS * \
  355                                        WSP_SIZEOF_FINGER_SENSOR_DATA)
  356 #define WSP_MAX_FINGER_ORIENTATION    16384
  357 
  358 #define ATP_SENSOR_DATA_BUF_MAX       1024
  359 #if (ATP_SENSOR_DATA_BUF_MAX < ((WSP_MAX_FINGERS * 14 * 2) + \
  360                                 WSP_TYPE3_FINGER_DATA_OFFSET))
  361 /* note: 14 * 2 in the above is based on sizeof(struct wsp_finger_sensor_data)*/
  362 #error "ATP_SENSOR_DATA_BUF_MAX is too small"
  363 #endif
  364 
  365 #define ATP_MAX_STROKES               MAX(WSP_MAX_FINGERS, FG_MAX_STROKES)
  366 
  367 #define FG_MAX_XSENSORS 26
  368 #define FG_MAX_YSENSORS 16
  369 
  370 /* device-specific configuration */
  371 struct fg_dev_params {
  372         u_int                              data_len;   /* for sensor data */
  373         u_int                              n_xsensors;
  374         u_int                              n_ysensors;
  375         enum fountain_geyser_trackpad_type prot;
  376 };
  377 struct wsp_dev_params {
  378         uint8_t  caps;               /* device capability bitmask */
  379         uint8_t  tp_type;            /* type of trackpad interface */
  380         uint8_t  finger_data_offset; /* offset to trackpad finger data */
  381 };
  382 
  383 static const struct fg_dev_params fg_dev_params[FOUNTAIN_GEYSER_PRODUCT_MAX] = {
  384         [FOUNTAIN] = {
  385                 .data_len   = 81,
  386                 .n_xsensors = 16,
  387                 .n_ysensors = 16,
  388                 .prot       = FG_TRACKPAD_TYPE_GEYSER1
  389         },
  390         [GEYSER1] = {
  391                 .data_len   = 81,
  392                 .n_xsensors = 16,
  393                 .n_ysensors = 16,
  394                 .prot       = FG_TRACKPAD_TYPE_GEYSER1
  395         },
  396         [GEYSER1_17inch] = {
  397                 .data_len   = 81,
  398                 .n_xsensors = 26,
  399                 .n_ysensors = 16,
  400                 .prot       = FG_TRACKPAD_TYPE_GEYSER1
  401         },
  402         [GEYSER2] = {
  403                 .data_len   = 64,
  404                 .n_xsensors = 15,
  405                 .n_ysensors = 9,
  406                 .prot       = FG_TRACKPAD_TYPE_GEYSER2
  407         },
  408         [GEYSER3] = {
  409                 .data_len   = 64,
  410                 .n_xsensors = 20,
  411                 .n_ysensors = 10,
  412                 .prot       = FG_TRACKPAD_TYPE_GEYSER3
  413         },
  414         [GEYSER4] = {
  415                 .data_len   = 64,
  416                 .n_xsensors = 20,
  417                 .n_ysensors = 10,
  418                 .prot       = FG_TRACKPAD_TYPE_GEYSER4
  419         }
  420 };
  421 
  422 static const STRUCT_USB_HOST_ID fg_devs[] = {
  423         /* PowerBooks Feb 2005, iBooks G4 */
  424         { USB_VPI(USB_VENDOR_APPLE, 0x020e, FG_DRIVER_INFO(FOUNTAIN)) },
  425         { USB_VPI(USB_VENDOR_APPLE, 0x020f, FG_DRIVER_INFO(FOUNTAIN)) },
  426         { USB_VPI(USB_VENDOR_APPLE, 0x0210, FG_DRIVER_INFO(FOUNTAIN)) },
  427         { USB_VPI(USB_VENDOR_APPLE, 0x030a, FG_DRIVER_INFO(FOUNTAIN)) },
  428         { USB_VPI(USB_VENDOR_APPLE, 0x030b, FG_DRIVER_INFO(GEYSER1)) },
  429 
  430         /* PowerBooks Oct 2005 */
  431         { USB_VPI(USB_VENDOR_APPLE, 0x0214, FG_DRIVER_INFO(GEYSER2)) },
  432         { USB_VPI(USB_VENDOR_APPLE, 0x0215, FG_DRIVER_INFO(GEYSER2)) },
  433         { USB_VPI(USB_VENDOR_APPLE, 0x0216, FG_DRIVER_INFO(GEYSER2)) },
  434 
  435         /* Core Duo MacBook & MacBook Pro */
  436         { USB_VPI(USB_VENDOR_APPLE, 0x0217, FG_DRIVER_INFO(GEYSER3)) },
  437         { USB_VPI(USB_VENDOR_APPLE, 0x0218, FG_DRIVER_INFO(GEYSER3)) },
  438         { USB_VPI(USB_VENDOR_APPLE, 0x0219, FG_DRIVER_INFO(GEYSER3)) },
  439 
  440         /* Core2 Duo MacBook & MacBook Pro */
  441         { USB_VPI(USB_VENDOR_APPLE, 0x021a, FG_DRIVER_INFO(GEYSER4)) },
  442         { USB_VPI(USB_VENDOR_APPLE, 0x021b, FG_DRIVER_INFO(GEYSER4)) },
  443         { USB_VPI(USB_VENDOR_APPLE, 0x021c, FG_DRIVER_INFO(GEYSER4)) },
  444 
  445         /* Core2 Duo MacBook3,1 */
  446         { USB_VPI(USB_VENDOR_APPLE, 0x0229, FG_DRIVER_INFO(GEYSER4)) },
  447         { USB_VPI(USB_VENDOR_APPLE, 0x022a, FG_DRIVER_INFO(GEYSER4)) },
  448         { USB_VPI(USB_VENDOR_APPLE, 0x022b, FG_DRIVER_INFO(GEYSER4)) },
  449 
  450         /* 17 inch PowerBook */
  451         { USB_VPI(USB_VENDOR_APPLE, 0x020d, FG_DRIVER_INFO(GEYSER1_17inch)) },
  452 };
  453 
  454 static const struct wsp_dev_params wsp_dev_params[WELLSPRING_PRODUCT_MAX] = {
  455         [WELLSPRING1] = {
  456                 .caps       = 0,
  457                 .tp_type    = WSP_TRACKPAD_TYPE1,
  458                 .finger_data_offset  = WSP_TYPE1_FINGER_DATA_OFFSET,
  459         },
  460         [WELLSPRING2] = {
  461                 .caps       = 0,
  462                 .tp_type    = WSP_TRACKPAD_TYPE1,
  463                 .finger_data_offset  = WSP_TYPE1_FINGER_DATA_OFFSET,
  464         },
  465         [WELLSPRING3] = {
  466                 .caps       = HAS_INTEGRATED_BUTTON,
  467                 .tp_type    = WSP_TRACKPAD_TYPE2,
  468                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  469         },
  470         [WELLSPRING4] = {
  471                 .caps       = HAS_INTEGRATED_BUTTON,
  472                 .tp_type    = WSP_TRACKPAD_TYPE2,
  473                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  474         },
  475         [WELLSPRING4A] = {
  476                 .caps       = HAS_INTEGRATED_BUTTON,
  477                 .tp_type    = WSP_TRACKPAD_TYPE2,
  478                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  479         },
  480         [WELLSPRING5] = {
  481                 .caps       = HAS_INTEGRATED_BUTTON,
  482                 .tp_type    = WSP_TRACKPAD_TYPE2,
  483                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  484         },
  485         [WELLSPRING6] = {
  486                 .caps       = HAS_INTEGRATED_BUTTON,
  487                 .tp_type    = WSP_TRACKPAD_TYPE2,
  488                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  489         },
  490         [WELLSPRING5A] = {
  491                 .caps       = HAS_INTEGRATED_BUTTON,
  492                 .tp_type    = WSP_TRACKPAD_TYPE2,
  493                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  494         },
  495         [WELLSPRING6A] = {
  496                 .caps       = HAS_INTEGRATED_BUTTON,
  497                 .tp_type    = WSP_TRACKPAD_TYPE2,
  498                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  499         },
  500         [WELLSPRING7] = {
  501                 .caps       = HAS_INTEGRATED_BUTTON,
  502                 .tp_type    = WSP_TRACKPAD_TYPE2,
  503                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  504         },
  505         [WELLSPRING7A] = {
  506                 .caps       = HAS_INTEGRATED_BUTTON,
  507                 .tp_type    = WSP_TRACKPAD_TYPE2,
  508                 .finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
  509         },
  510         [WELLSPRING8] = {
  511                 .caps       = HAS_INTEGRATED_BUTTON,
  512                 .tp_type    = WSP_TRACKPAD_TYPE3,
  513                 .finger_data_offset  = WSP_TYPE3_FINGER_DATA_OFFSET,
  514         },
  515 };
  516 #define ATP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
  517 
  518 /* TODO: STRUCT_USB_HOST_ID */
  519 static const struct usb_device_id wsp_devs[] = {
  520         /* MacbookAir1.1 */
  521         ATP_DEV(APPLE, WELLSPRING_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING1)),
  522         ATP_DEV(APPLE, WELLSPRING_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING1)),
  523         ATP_DEV(APPLE, WELLSPRING_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING1)),
  524 
  525         /* MacbookProPenryn, aka wellspring2 */
  526         ATP_DEV(APPLE, WELLSPRING2_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING2)),
  527         ATP_DEV(APPLE, WELLSPRING2_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING2)),
  528         ATP_DEV(APPLE, WELLSPRING2_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING2)),
  529 
  530         /* Macbook5,1 (unibody), aka wellspring3 */
  531         ATP_DEV(APPLE, WELLSPRING3_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING3)),
  532         ATP_DEV(APPLE, WELLSPRING3_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING3)),
  533         ATP_DEV(APPLE, WELLSPRING3_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING3)),
  534 
  535         /* MacbookAir3,2 (unibody), aka wellspring4 */
  536         ATP_DEV(APPLE, WELLSPRING4_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING4)),
  537         ATP_DEV(APPLE, WELLSPRING4_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING4)),
  538         ATP_DEV(APPLE, WELLSPRING4_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING4)),
  539 
  540         /* MacbookAir3,1 (unibody), aka wellspring4 */
  541         ATP_DEV(APPLE, WELLSPRING4A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING4A)),
  542         ATP_DEV(APPLE, WELLSPRING4A_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING4A)),
  543         ATP_DEV(APPLE, WELLSPRING4A_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING4A)),
  544 
  545         /* Macbook8 (unibody, March 2011) */
  546         ATP_DEV(APPLE, WELLSPRING5_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING5)),
  547         ATP_DEV(APPLE, WELLSPRING5_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING5)),
  548         ATP_DEV(APPLE, WELLSPRING5_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING5)),
  549 
  550         /* MacbookAir4,1 (unibody, July 2011) */
  551         ATP_DEV(APPLE, WELLSPRING6A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING6A)),
  552         ATP_DEV(APPLE, WELLSPRING6A_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING6A)),
  553         ATP_DEV(APPLE, WELLSPRING6A_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING6A)),
  554 
  555         /* MacbookAir4,2 (unibody, July 2011) */
  556         ATP_DEV(APPLE, WELLSPRING6_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING6)),
  557         ATP_DEV(APPLE, WELLSPRING6_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING6)),
  558         ATP_DEV(APPLE, WELLSPRING6_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING6)),
  559 
  560         /* Macbook8,2 (unibody) */
  561         ATP_DEV(APPLE, WELLSPRING5A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING5A)),
  562         ATP_DEV(APPLE, WELLSPRING5A_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING5A)),
  563         ATP_DEV(APPLE, WELLSPRING5A_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING5A)),
  564 
  565         /* MacbookPro10,1 (unibody, June 2012) */
  566         /* MacbookPro11,? (unibody, June 2013) */
  567         ATP_DEV(APPLE, WELLSPRING7_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING7)),
  568         ATP_DEV(APPLE, WELLSPRING7_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING7)),
  569         ATP_DEV(APPLE, WELLSPRING7_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING7)),
  570 
  571         /* MacbookPro10,2 (unibody, October 2012) */
  572         ATP_DEV(APPLE, WELLSPRING7A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING7A)),
  573         ATP_DEV(APPLE, WELLSPRING7A_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING7A)),
  574         ATP_DEV(APPLE, WELLSPRING7A_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING7A)),
  575 
  576         /* MacbookAir6,2 (unibody, June 2013) */
  577         ATP_DEV(APPLE, WELLSPRING8_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING8)),
  578         ATP_DEV(APPLE, WELLSPRING8_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING8)),
  579         ATP_DEV(APPLE, WELLSPRING8_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING8)),
  580 };
  581 
  582 typedef enum atp_stroke_type {
  583         ATP_STROKE_TOUCH,
  584         ATP_STROKE_SLIDE,
  585 } atp_stroke_type;
  586 
  587 typedef enum atp_axis {
  588         X = 0,
  589         Y = 1,
  590         NUM_AXES
  591 } atp_axis;
  592 
  593 #define ATP_FIFO_BUF_SIZE        8 /* bytes */
  594 #define ATP_FIFO_QUEUE_MAXLEN   50 /* units */
  595 
  596 enum {
  597         ATP_INTR_DT,
  598         ATP_RESET,
  599         ATP_N_TRANSFER,
  600 };
  601 
  602 typedef struct fg_stroke_component {
  603         /* Fields encapsulating the pressure-span. */
  604         u_int loc;              /* location (scaled) */
  605         u_int cum_pressure;     /* cumulative compression */
  606         u_int max_cum_pressure; /* max cumulative compression */
  607         boolean_t matched; /*to track components as they match against pspans.*/
  608 
  609         int   delta_mickeys;    /* change in location (un-smoothened movement)*/
  610 } fg_stroke_component_t;
  611 
  612 /*
  613  * The following structure captures a finger contact with the
  614  * touchpad. A stroke comprises two p-span components and some state.
  615  */
  616 typedef struct atp_stroke {
  617         TAILQ_ENTRY(atp_stroke) entry;
  618 
  619         atp_stroke_type type;
  620         uint32_t        flags; /* the state of this stroke */
  621 #define ATSF_ZOMBIE 0x1
  622         boolean_t       matched;          /* to track match against fingers.*/
  623 
  624         struct timeval  ctime; /* create time; for coincident siblings. */
  625 
  626         /*
  627          * Unit: interrupts; we maintain this value in
  628          * addition to 'ctime' in order to avoid the
  629          * expensive call to microtime() at every
  630          * interrupt.
  631          */
  632         uint32_t age;
  633 
  634         /* Location */
  635         int x;
  636         int y;
  637 
  638         /* Fields containing information about movement. */
  639         int   instantaneous_dx; /* curr. change in X location (un-smoothened) */
  640         int   instantaneous_dy; /* curr. change in Y location (un-smoothened) */
  641         int   pending_dx;       /* cum. of pending short movements */
  642         int   pending_dy;       /* cum. of pending short movements */
  643         int   movement_dx;      /* interpreted smoothened movement */
  644         int   movement_dy;      /* interpreted smoothened movement */
  645         int   cum_movement_x;   /* cum. horizontal movement */
  646         int   cum_movement_y;   /* cum. vertical movement */
  647 
  648         /*
  649          * The following member is relevant only for fountain-geyser trackpads.
  650          * For these, there is the need to track pressure-spans and cumulative
  651          * pressures for stroke components.
  652          */
  653         fg_stroke_component_t components[NUM_AXES];
  654 } atp_stroke_t;
  655 
  656 struct atp_softc; /* forward declaration */
  657 typedef void (*sensor_data_interpreter_t)(struct atp_softc *sc, u_int len);
  658 
  659 struct atp_softc {
  660         device_t            sc_dev;
  661         struct usb_device  *sc_usb_device;
  662         struct mtx          sc_mutex; /* for synchronization */
  663         struct usb_fifo_sc  sc_fifo;
  664 
  665 #define MODE_LENGTH 8
  666         char                sc_mode_bytes[MODE_LENGTH]; /* device mode */
  667 
  668         trackpad_family_t   sc_family;
  669         const void         *sc_params; /* device configuration */
  670         sensor_data_interpreter_t sensor_data_interpreter;
  671 
  672         mousehw_t           sc_hw;
  673         mousemode_t         sc_mode;
  674         mousestatus_t       sc_status;
  675 
  676         u_int               sc_state;
  677 #define ATP_ENABLED          0x01
  678 #define ATP_ZOMBIES_EXIST    0x02
  679 #define ATP_DOUBLE_TAP_DRAG  0x04
  680 #define ATP_VALID            0x08
  681 
  682         struct usb_xfer    *sc_xfer[ATP_N_TRANSFER];
  683 
  684         u_int               sc_pollrate;
  685         int                 sc_fflags;
  686 
  687         atp_stroke_t        sc_strokes_data[ATP_MAX_STROKES];
  688         TAILQ_HEAD(,atp_stroke) sc_stroke_free;
  689         TAILQ_HEAD(,atp_stroke) sc_stroke_used;
  690         u_int               sc_n_strokes;
  691 
  692         struct callout      sc_callout;
  693 
  694         /*
  695          * button status. Set to non-zero if the mouse-button is physically
  696          * pressed. This state variable is exposed through softc to allow
  697          * reap_sibling_zombies to avoid registering taps while the trackpad
  698          * button is pressed.
  699          */
  700         uint8_t             sc_ibtn;
  701 
  702         /*
  703          * Time when touch zombies were last reaped; useful for detecting
  704          * double-touch-n-drag.
  705          */
  706         struct timeval      sc_touch_reap_time;
  707 
  708         u_int               sc_idlecount;
  709 
  710         /* Regarding the data transferred from t-pad in USB INTR packets. */
  711         u_int   sc_expected_sensor_data_len;
  712         uint8_t sc_sensor_data[ATP_SENSOR_DATA_BUF_MAX] __aligned(4);
  713 
  714         int      sc_cur_x[FG_MAX_XSENSORS];      /* current sensor readings */
  715         int      sc_cur_y[FG_MAX_YSENSORS];
  716         int      sc_base_x[FG_MAX_XSENSORS];     /* base sensor readings */
  717         int      sc_base_y[FG_MAX_YSENSORS];
  718         int      sc_pressure_x[FG_MAX_XSENSORS]; /* computed pressures */
  719         int      sc_pressure_y[FG_MAX_YSENSORS];
  720         fg_pspan sc_pspans_x[FG_MAX_PSPANS_PER_AXIS];
  721         fg_pspan sc_pspans_y[FG_MAX_PSPANS_PER_AXIS];
  722 };
  723 
  724 /*
  725  * The last byte of the fountain-geyser sensor data contains status bits; the
  726  * following values define the meanings of these bits.
  727  * (only Geyser 3/4)
  728  */
  729 enum geyser34_status_bits {
  730         FG_STATUS_BUTTON      = (uint8_t)0x01, /* The button was pressed */
  731         FG_STATUS_BASE_UPDATE = (uint8_t)0x04, /* Data from an untouched pad.*/
  732 };
  733 
  734 typedef enum interface_mode {
  735         RAW_SENSOR_MODE = (uint8_t)0x01,
  736         HID_MODE        = (uint8_t)0x08
  737 } interface_mode;
  738 
  739 /*
  740  * function prototypes
  741  */
  742 static usb_fifo_cmd_t   atp_start_read;
  743 static usb_fifo_cmd_t   atp_stop_read;
  744 static usb_fifo_open_t  atp_open;
  745 static usb_fifo_close_t atp_close;
  746 static usb_fifo_ioctl_t atp_ioctl;
  747 
  748 static struct usb_fifo_methods atp_fifo_methods = {
  749         .f_open       = &atp_open,
  750         .f_close      = &atp_close,
  751         .f_ioctl      = &atp_ioctl,
  752         .f_start_read = &atp_start_read,
  753         .f_stop_read  = &atp_stop_read,
  754         .basename[0]  = ATP_DRIVER_NAME,
  755 };
  756 
  757 /* device initialization and shutdown */
  758 static usb_error_t   atp_set_device_mode(struct atp_softc *, interface_mode);
  759 static void          atp_reset_callback(struct usb_xfer *, usb_error_t);
  760 static int           atp_enable(struct atp_softc *);
  761 static void          atp_disable(struct atp_softc *);
  762 
  763 /* sensor interpretation */
  764 static void          fg_interpret_sensor_data(struct atp_softc *, u_int);
  765 static void          fg_extract_sensor_data(const int8_t *, u_int, atp_axis,
  766     int *, enum fountain_geyser_trackpad_type);
  767 static void          fg_get_pressures(int *, const int *, const int *, int);
  768 static void          fg_detect_pspans(int *, u_int, u_int, fg_pspan *, u_int *);
  769 static void          wsp_interpret_sensor_data(struct atp_softc *, u_int);
  770 
  771 /* movement detection */
  772 static boolean_t     fg_match_stroke_component(fg_stroke_component_t *,
  773     const fg_pspan *, atp_stroke_type);
  774 static void          fg_match_strokes_against_pspans(struct atp_softc *,
  775     atp_axis, fg_pspan *, u_int, u_int);
  776 static boolean_t     wsp_match_strokes_against_fingers(struct atp_softc *,
  777     wsp_finger_t *, u_int);
  778 static boolean_t     fg_update_strokes(struct atp_softc *, fg_pspan *, u_int,
  779     fg_pspan *, u_int);
  780 static boolean_t     wsp_update_strokes(struct atp_softc *,
  781     wsp_finger_t [WSP_MAX_FINGERS], u_int);
  782 static void fg_add_stroke(struct atp_softc *, const fg_pspan *, const fg_pspan *);
  783 static void          fg_add_new_strokes(struct atp_softc *, fg_pspan *,
  784     u_int, fg_pspan *, u_int);
  785 static void wsp_add_stroke(struct atp_softc *, const wsp_finger_t *);
  786 static void          atp_advance_stroke_state(struct atp_softc *,
  787     atp_stroke_t *, boolean_t *);
  788 static boolean_t atp_stroke_has_small_movement(const atp_stroke_t *);
  789 static void          atp_update_pending_mickeys(atp_stroke_t *);
  790 static boolean_t     atp_compute_stroke_movement(atp_stroke_t *);
  791 static void          atp_terminate_stroke(struct atp_softc *, atp_stroke_t *);
  792 
  793 /* tap detection */
  794 static boolean_t atp_is_horizontal_scroll(const atp_stroke_t *);
  795 static boolean_t atp_is_vertical_scroll(const atp_stroke_t *);
  796 static void          atp_reap_sibling_zombies(void *);
  797 static void          atp_convert_to_slide(struct atp_softc *, atp_stroke_t *);
  798 
  799 /* updating fifo */
  800 static void          atp_reset_buf(struct atp_softc *);
  801 static void          atp_add_to_queue(struct atp_softc *, int, int, int, uint32_t);
  802 
  803 /* Device methods. */
  804 static device_probe_t  atp_probe;
  805 static device_attach_t atp_attach;
  806 static device_detach_t atp_detach;
  807 static usb_callback_t  atp_intr;
  808 
  809 static const struct usb_config atp_xfer_config[ATP_N_TRANSFER] = {
  810         [ATP_INTR_DT] = {
  811                 .type      = UE_INTERRUPT,
  812                 .endpoint  = UE_ADDR_ANY,
  813                 .direction = UE_DIR_IN,
  814                 .flags = {
  815                         .pipe_bof = 1, /* block pipe on failure */
  816                         .short_xfer_ok = 1,
  817                 },
  818                 .bufsize   = ATP_SENSOR_DATA_BUF_MAX,
  819                 .callback  = &atp_intr,
  820         },
  821         [ATP_RESET] = {
  822                 .type      = UE_CONTROL,
  823                 .endpoint  = 0, /* Control pipe */
  824                 .direction = UE_DIR_ANY,
  825                 .bufsize   = sizeof(struct usb_device_request) + MODE_LENGTH,
  826                 .callback  = &atp_reset_callback,
  827                 .interval  = 0,  /* no pre-delay */
  828         },
  829 };
  830 
  831 static atp_stroke_t *
  832 atp_alloc_stroke(struct atp_softc *sc)
  833 {
  834         atp_stroke_t *pstroke;
  835 
  836         pstroke = TAILQ_FIRST(&sc->sc_stroke_free);
  837         if (pstroke == NULL)
  838                 goto done;
  839 
  840         TAILQ_REMOVE(&sc->sc_stroke_free, pstroke, entry);
  841         memset(pstroke, 0, sizeof(*pstroke));
  842         TAILQ_INSERT_TAIL(&sc->sc_stroke_used, pstroke, entry);
  843 
  844         sc->sc_n_strokes++;
  845 done:
  846         return (pstroke);
  847 }
  848 
  849 static void
  850 atp_free_stroke(struct atp_softc *sc, atp_stroke_t *pstroke)
  851 {
  852         if (pstroke == NULL)
  853                 return;
  854 
  855         sc->sc_n_strokes--;
  856 
  857         TAILQ_REMOVE(&sc->sc_stroke_used, pstroke, entry);
  858         TAILQ_INSERT_TAIL(&sc->sc_stroke_free, pstroke, entry);
  859 }
  860 
  861 static void
  862 atp_init_stroke_pool(struct atp_softc *sc)
  863 {
  864         u_int x;
  865 
  866         TAILQ_INIT(&sc->sc_stroke_free);
  867         TAILQ_INIT(&sc->sc_stroke_used);
  868 
  869         sc->sc_n_strokes = 0;
  870 
  871         memset(&sc->sc_strokes_data, 0, sizeof(sc->sc_strokes_data));
  872 
  873         for (x = 0; x != ATP_MAX_STROKES; x++) {
  874                 TAILQ_INSERT_TAIL(&sc->sc_stroke_free, &sc->sc_strokes_data[x],
  875                     entry);
  876         }
  877 }
  878 
  879 static usb_error_t
  880 atp_set_device_mode(struct atp_softc *sc, interface_mode newMode)
  881 {
  882         uint8_t mode_value;
  883         usb_error_t err;
  884 
  885         if ((newMode != RAW_SENSOR_MODE) && (newMode != HID_MODE))
  886                 return (USB_ERR_INVAL);
  887 
  888         if ((newMode == RAW_SENSOR_MODE) &&
  889             (sc->sc_family == TRACKPAD_FAMILY_FOUNTAIN_GEYSER))
  890                 mode_value = (uint8_t)0x04;
  891         else
  892                 mode_value = newMode;
  893 
  894         err = usbd_req_get_report(sc->sc_usb_device, NULL /* mutex */,
  895             sc->sc_mode_bytes, sizeof(sc->sc_mode_bytes), 0 /* interface idx */,
  896             0x03 /* type */, 0x00 /* id */);
  897         if (err != USB_ERR_NORMAL_COMPLETION) {
  898                 DPRINTF("Failed to read device mode (%d)\n", err);
  899                 return (err);
  900         }
  901 
  902         if (sc->sc_mode_bytes[0] == mode_value)
  903                 return (err);
  904 
  905         /*
  906          * XXX Need to wait at least 250ms for hardware to get
  907          * ready. The device mode handling appears to be handled
  908          * asynchronously and we should not issue these commands too
  909          * quickly.
  910          */
  911         pause("WHW", hz / 4);
  912 
  913         sc->sc_mode_bytes[0] = mode_value;
  914         return (usbd_req_set_report(sc->sc_usb_device, NULL /* mutex */,
  915             sc->sc_mode_bytes, sizeof(sc->sc_mode_bytes), 0 /* interface idx */,
  916             0x03 /* type */, 0x00 /* id */));
  917 }
  918 
  919 static void
  920 atp_reset_callback(struct usb_xfer *xfer, usb_error_t error)
  921 {
  922         usb_device_request_t   req;
  923         struct usb_page_cache *pc;
  924         struct atp_softc      *sc = usbd_xfer_softc(xfer);
  925 
  926         uint8_t mode_value;
  927         if (sc->sc_family == TRACKPAD_FAMILY_FOUNTAIN_GEYSER)
  928                 mode_value = 0x04;
  929         else
  930                 mode_value = RAW_SENSOR_MODE;
  931 
  932         switch (USB_GET_STATE(xfer)) {
  933         case USB_ST_SETUP:
  934                 sc->sc_mode_bytes[0] = mode_value;
  935                 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  936                 req.bRequest = UR_SET_REPORT;
  937                 USETW2(req.wValue,
  938                     (uint8_t)0x03 /* type */, (uint8_t)0x00 /* id */);
  939                 USETW(req.wIndex, 0);
  940                 USETW(req.wLength, MODE_LENGTH);
  941 
  942                 pc = usbd_xfer_get_frame(xfer, 0);
  943                 usbd_copy_in(pc, 0, &req, sizeof(req));
  944                 pc = usbd_xfer_get_frame(xfer, 1);
  945                 usbd_copy_in(pc, 0, sc->sc_mode_bytes, MODE_LENGTH);
  946 
  947                 usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
  948                 usbd_xfer_set_frame_len(xfer, 1, MODE_LENGTH);
  949                 usbd_xfer_set_frames(xfer, 2);
  950                 usbd_transfer_submit(xfer);
  951                 break;
  952 
  953         case USB_ST_TRANSFERRED:
  954         default:
  955                 break;
  956         }
  957 }
  958 
  959 static int
  960 atp_enable(struct atp_softc *sc)
  961 {
  962         if (sc->sc_state & ATP_ENABLED)
  963                 return (0);
  964 
  965         /* reset status */
  966         memset(&sc->sc_status, 0, sizeof(sc->sc_status));
  967 
  968         atp_init_stroke_pool(sc);
  969 
  970         sc->sc_state |= ATP_ENABLED;
  971 
  972         DPRINTFN(ATP_LLEVEL_INFO, "enabled atp\n");
  973         return (0);
  974 }
  975 
  976 static void
  977 atp_disable(struct atp_softc *sc)
  978 {
  979         sc->sc_state &= ~(ATP_ENABLED | ATP_VALID);
  980         DPRINTFN(ATP_LLEVEL_INFO, "disabled atp\n");
  981 }
  982 
  983 static void
  984 fg_interpret_sensor_data(struct atp_softc *sc, u_int data_len)
  985 {
  986         u_int n_xpspans = 0;
  987         u_int n_ypspans = 0;
  988         uint8_t status_bits;
  989 
  990         const struct fg_dev_params *params =
  991             (const struct fg_dev_params *)sc->sc_params;
  992 
  993         fg_extract_sensor_data(sc->sc_sensor_data, params->n_xsensors, X,
  994             sc->sc_cur_x, params->prot);
  995         fg_extract_sensor_data(sc->sc_sensor_data, params->n_ysensors, Y,
  996             sc->sc_cur_y, params->prot);
  997 
  998         /*
  999          * If this is the initial update (from an untouched
 1000          * pad), we should set the base values for the sensor
 1001          * data; deltas with respect to these base values can
 1002          * be used as pressure readings subsequently.
 1003          */
 1004         status_bits = sc->sc_sensor_data[params->data_len - 1];
 1005         if (((params->prot == FG_TRACKPAD_TYPE_GEYSER3) ||
 1006              (params->prot == FG_TRACKPAD_TYPE_GEYSER4))  &&
 1007             ((sc->sc_state & ATP_VALID) == 0)) {
 1008                 if (status_bits & FG_STATUS_BASE_UPDATE) {
 1009                         memcpy(sc->sc_base_x, sc->sc_cur_x,
 1010                             params->n_xsensors * sizeof(*sc->sc_base_x));
 1011                         memcpy(sc->sc_base_y, sc->sc_cur_y,
 1012                             params->n_ysensors * sizeof(*sc->sc_base_y));
 1013                         sc->sc_state |= ATP_VALID;
 1014                         return;
 1015                 }
 1016         }
 1017 
 1018         /* Get pressure readings and detect p-spans for both axes. */
 1019         fg_get_pressures(sc->sc_pressure_x, sc->sc_cur_x, sc->sc_base_x,
 1020             params->n_xsensors);
 1021         fg_detect_pspans(sc->sc_pressure_x, params->n_xsensors,
 1022             FG_MAX_PSPANS_PER_AXIS, sc->sc_pspans_x, &n_xpspans);
 1023         fg_get_pressures(sc->sc_pressure_y, sc->sc_cur_y, sc->sc_base_y,
 1024             params->n_ysensors);
 1025         fg_detect_pspans(sc->sc_pressure_y, params->n_ysensors,
 1026             FG_MAX_PSPANS_PER_AXIS, sc->sc_pspans_y, &n_ypspans);
 1027 
 1028         /* Update strokes with new pspans to detect movements. */
 1029         if (fg_update_strokes(sc, sc->sc_pspans_x, n_xpspans, sc->sc_pspans_y, n_ypspans))
 1030                 sc->sc_status.flags |= MOUSE_POSCHANGED;
 1031 
 1032         sc->sc_ibtn = (status_bits & FG_STATUS_BUTTON) ? MOUSE_BUTTON1DOWN : 0;
 1033         sc->sc_status.button = sc->sc_ibtn;
 1034 
 1035         /*
 1036          * The Fountain/Geyser device continues to trigger interrupts
 1037          * at a fast rate even after touchpad activity has
 1038          * stopped. Upon detecting that the device has remained idle
 1039          * beyond a threshold, we reinitialize it to silence the
 1040          * interrupts.
 1041          */
 1042         if ((sc->sc_status.flags  == 0) && (sc->sc_n_strokes == 0)) {
 1043                 sc->sc_idlecount++;
 1044                 if (sc->sc_idlecount >= ATP_IDLENESS_THRESHOLD) {
 1045                         /*
 1046                          * Use the last frame before we go idle for
 1047                          * calibration on pads which do not send
 1048                          * calibration frames.
 1049                          */
 1050                         const struct fg_dev_params *params =
 1051                             (const struct fg_dev_params *)sc->sc_params;
 1052 
 1053                         DPRINTFN(ATP_LLEVEL_INFO, "idle\n");
 1054 
 1055                         if (params->prot < FG_TRACKPAD_TYPE_GEYSER3) {
 1056                                 memcpy(sc->sc_base_x, sc->sc_cur_x,
 1057                                     params->n_xsensors * sizeof(*(sc->sc_base_x)));
 1058                                 memcpy(sc->sc_base_y, sc->sc_cur_y,
 1059                                     params->n_ysensors * sizeof(*(sc->sc_base_y)));
 1060                         }
 1061 
 1062                         sc->sc_idlecount = 0;
 1063                         usbd_transfer_start(sc->sc_xfer[ATP_RESET]);
 1064                 }
 1065         } else {
 1066                 sc->sc_idlecount = 0;
 1067         }
 1068 }
 1069 
 1070 /*
 1071  * Interpret the data from the X and Y pressure sensors. This function
 1072  * is called separately for the X and Y sensor arrays. The data in the
 1073  * USB packet is laid out in the following manner:
 1074  *
 1075  * sensor_data:
 1076  *            --,--,Y1,Y2,--,Y3,Y4,--,Y5,...,Y10, ... X1,X2,--,X3,X4
 1077  *  indices:   0  1  2  3  4  5  6  7  8 ...  15  ... 20 21 22 23 24
 1078  *
 1079  * '--' (in the above) indicates that the value is unimportant.
 1080  *
 1081  * Information about the above layout was obtained from the
 1082  * implementation of the AppleTouch driver in Linux.
 1083  *
 1084  * parameters:
 1085  *   sensor_data
 1086  *       raw sensor data from the USB packet.
 1087  *   num
 1088  *       The number of elements in the array 'arr'.
 1089  *   axis
 1090  *       Axis of data to fetch
 1091  *   arr
 1092  *       The array to be initialized with the readings.
 1093  *   prot
 1094  *       The protocol to use to interpret the data
 1095  */
 1096 static void
 1097 fg_extract_sensor_data(const int8_t *sensor_data, u_int num, atp_axis axis,
 1098     int *arr, enum fountain_geyser_trackpad_type prot)
 1099 {
 1100         u_int i;
 1101         u_int di;   /* index into sensor data */
 1102 
 1103         switch (prot) {
 1104         case FG_TRACKPAD_TYPE_GEYSER1:
 1105                 /*
 1106                  * For Geyser 1, the sensors are laid out in pairs
 1107                  * every 5 bytes.
 1108                  */
 1109                 for (i = 0, di = (axis == Y) ? 1 : 2; i < 8; di += 5, i++) {
 1110                         arr[i] = sensor_data[di];
 1111                         arr[i+8] = sensor_data[di+2];
 1112                         if ((axis == X) && (num > 16))
 1113                                 arr[i+16] = sensor_data[di+40];
 1114                 }
 1115 
 1116                 break;
 1117         case FG_TRACKPAD_TYPE_GEYSER2:
 1118                 for (i = 0, di = (axis == Y) ? 1 : 19; i < num; /* empty */ ) {
 1119                         arr[i++] = sensor_data[di++];
 1120                         arr[i++] = sensor_data[di++];
 1121                         di++;
 1122                 }
 1123                 break;
 1124         case FG_TRACKPAD_TYPE_GEYSER3:
 1125         case FG_TRACKPAD_TYPE_GEYSER4:
 1126                 for (i = 0, di = (axis == Y) ? 2 : 20; i < num; /* empty */ ) {
 1127                         arr[i++] = sensor_data[di++];
 1128                         arr[i++] = sensor_data[di++];
 1129                         di++;
 1130                 }
 1131                 break;
 1132         default:
 1133                 break;
 1134         }
 1135 }
 1136 
 1137 static void
 1138 fg_get_pressures(int *p, const int *cur, const int *base, int n)
 1139 {
 1140         int i;
 1141 
 1142         for (i = 0; i < n; i++) {
 1143                 p[i] = cur[i] - base[i];
 1144                 if (p[i] > 127)
 1145                         p[i] -= 256;
 1146                 if (p[i] < -127)
 1147                         p[i] += 256;
 1148                 if (p[i] < 0)
 1149                         p[i] = 0;
 1150 
 1151                 /*
 1152                  * Shave off pressures below the noise-pressure
 1153                  * threshold; this will reduce the contribution from
 1154                  * lower pressure readings.
 1155                  */
 1156                 if ((u_int)p[i] <= FG_SENSOR_NOISE_THRESHOLD)
 1157                         p[i] = 0; /* filter away noise */
 1158                 else
 1159                         p[i] -= FG_SENSOR_NOISE_THRESHOLD;
 1160         }
 1161 }
 1162 
 1163 static void
 1164 fg_detect_pspans(int *p, u_int num_sensors,
 1165     u_int      max_spans, /* max # of pspans permitted */
 1166     fg_pspan  *spans,     /* finger spans */
 1167     u_int     *nspans_p)  /* num spans detected */
 1168 {
 1169         u_int i;
 1170         int   maxp;             /* max pressure seen within a span */
 1171         u_int num_spans = 0;
 1172 
 1173         enum fg_pspan_state {
 1174                 ATP_PSPAN_INACTIVE,
 1175                 ATP_PSPAN_INCREASING,
 1176                 ATP_PSPAN_DECREASING,
 1177         } state; /* state of the pressure span */
 1178 
 1179         /*
 1180          * The following is a simple state machine to track
 1181          * the phase of the pressure span.
 1182          */
 1183         memset(spans, 0, max_spans * sizeof(fg_pspan));
 1184         maxp = 0;
 1185         state = ATP_PSPAN_INACTIVE;
 1186         for (i = 0; i < num_sensors; i++) {
 1187                 if (num_spans >= max_spans)
 1188                         break;
 1189 
 1190                 if (p[i] == 0) {
 1191                         if (state == ATP_PSPAN_INACTIVE) {
 1192                                 /*
 1193                                  * There is no pressure information for this
 1194                                  * sensor, and we aren't tracking a finger.
 1195                                  */
 1196                                 continue;
 1197                         } else {
 1198                                 state = ATP_PSPAN_INACTIVE;
 1199                                 maxp = 0;
 1200                                 num_spans++;
 1201                         }
 1202                 } else {
 1203                         switch (state) {
 1204                         case ATP_PSPAN_INACTIVE:
 1205                                 state = ATP_PSPAN_INCREASING;
 1206                                 maxp  = p[i];
 1207                                 break;
 1208 
 1209                         case ATP_PSPAN_INCREASING:
 1210                                 if (p[i] > maxp)
 1211                                         maxp = p[i];
 1212                                 else if (p[i] <= (maxp >> 1))
 1213                                         state = ATP_PSPAN_DECREASING;
 1214                                 break;
 1215 
 1216                         case ATP_PSPAN_DECREASING:
 1217                                 if (p[i] > p[i - 1]) {
 1218                                         /*
 1219                                          * This is the beginning of
 1220                                          * another span; change state
 1221                                          * to give the appearance that
 1222                                          * we're starting from an
 1223                                          * inactive span, and then
 1224                                          * re-process this reading in
 1225                                          * the next iteration.
 1226                                          */
 1227                                         num_spans++;
 1228                                         state = ATP_PSPAN_INACTIVE;
 1229                                         maxp  = 0;
 1230                                         i--;
 1231                                         continue;
 1232                                 }
 1233                                 break;
 1234                         }
 1235 
 1236                         /* Update the finger span with this reading. */
 1237                         spans[num_spans].width++;
 1238                         spans[num_spans].cum += p[i];
 1239                         spans[num_spans].cog += p[i] * (i + 1);
 1240                 }
 1241         }
 1242         if (state != ATP_PSPAN_INACTIVE)
 1243                 num_spans++;    /* close the last finger span */
 1244 
 1245         /* post-process the spans */
 1246         for (i = 0; i < num_spans; i++) {
 1247                 /* filter away unwanted pressure spans */
 1248                 if ((spans[i].cum < FG_PSPAN_MIN_CUM_PRESSURE) ||
 1249                     (spans[i].width > FG_PSPAN_MAX_WIDTH)) {
 1250                         if ((i + 1) < num_spans) {
 1251                                 memcpy(&spans[i], &spans[i + 1],
 1252                                     (num_spans - i - 1) * sizeof(fg_pspan));
 1253                                 i--;
 1254                         }
 1255                         num_spans--;
 1256                         continue;
 1257                 }
 1258 
 1259                 /* compute this span's representative location */
 1260                 spans[i].loc = spans[i].cog * FG_SCALE_FACTOR /
 1261                         spans[i].cum;
 1262 
 1263                 spans[i].matched = false; /* not yet matched against a stroke */
 1264         }
 1265 
 1266         *nspans_p = num_spans;
 1267 }
 1268 
 1269 static void
 1270 wsp_interpret_sensor_data(struct atp_softc *sc, u_int data_len)
 1271 {
 1272         const struct wsp_dev_params *params = sc->sc_params;
 1273         wsp_finger_t fingers[WSP_MAX_FINGERS];
 1274         struct wsp_finger_sensor_data *source_fingerp;
 1275         u_int n_source_fingers;
 1276         u_int n_fingers;
 1277         u_int i;
 1278 
 1279         /* validate sensor data length */
 1280         if ((data_len < params->finger_data_offset) ||
 1281             ((data_len - params->finger_data_offset) %
 1282              WSP_SIZEOF_FINGER_SENSOR_DATA) != 0)
 1283                 return;
 1284 
 1285         /* compute number of source fingers */
 1286         n_source_fingers = (data_len - params->finger_data_offset) /
 1287             WSP_SIZEOF_FINGER_SENSOR_DATA;
 1288 
 1289         if (n_source_fingers > WSP_MAX_FINGERS)
 1290                 n_source_fingers = WSP_MAX_FINGERS;
 1291 
 1292         /* iterate over the source data collecting useful fingers */
 1293         n_fingers = 0;
 1294         source_fingerp = (struct wsp_finger_sensor_data *)(sc->sc_sensor_data +
 1295              params->finger_data_offset);
 1296 
 1297         for (i = 0; i < n_source_fingers; i++, source_fingerp++) {
 1298                 /* swap endianness, if any */
 1299                 if (le16toh(0x1234) != 0x1234) {
 1300                         source_fingerp->origin      = le16toh((uint16_t)source_fingerp->origin);
 1301                         source_fingerp->abs_x       = le16toh((uint16_t)source_fingerp->abs_x);
 1302                         source_fingerp->abs_y       = le16toh((uint16_t)source_fingerp->abs_y);
 1303                         source_fingerp->rel_x       = le16toh((uint16_t)source_fingerp->rel_x);
 1304                         source_fingerp->rel_y       = le16toh((uint16_t)source_fingerp->rel_y);
 1305                         source_fingerp->tool_major  = le16toh((uint16_t)source_fingerp->tool_major);
 1306                         source_fingerp->tool_minor  = le16toh((uint16_t)source_fingerp->tool_minor);
 1307                         source_fingerp->orientation = le16toh((uint16_t)source_fingerp->orientation);
 1308                         source_fingerp->touch_major = le16toh((uint16_t)source_fingerp->touch_major);
 1309                         source_fingerp->touch_minor = le16toh((uint16_t)source_fingerp->touch_minor);
 1310                         source_fingerp->multi       = le16toh((uint16_t)source_fingerp->multi);
 1311                 }
 1312 
 1313                 /* check for minium threshold */
 1314                 if (source_fingerp->touch_major == 0)
 1315                         continue;
 1316 
 1317                 fingers[n_fingers].matched = false;
 1318                 fingers[n_fingers].x       = source_fingerp->abs_x;
 1319                 fingers[n_fingers].y       = -source_fingerp->abs_y;
 1320 
 1321                 n_fingers++;
 1322         }
 1323 
 1324         if ((sc->sc_n_strokes == 0) && (n_fingers == 0))
 1325                 return;
 1326 
 1327         if (wsp_update_strokes(sc, fingers, n_fingers))
 1328                 sc->sc_status.flags |= MOUSE_POSCHANGED;
 1329 
 1330         switch(params->tp_type) {
 1331         case WSP_TRACKPAD_TYPE2:
 1332                 sc->sc_ibtn = sc->sc_sensor_data[WSP_TYPE2_BUTTON_DATA_OFFSET];
 1333                 break;
 1334         case WSP_TRACKPAD_TYPE3:
 1335                 sc->sc_ibtn = sc->sc_sensor_data[WSP_TYPE3_BUTTON_DATA_OFFSET];
 1336                 break;
 1337         default:
 1338                 break;
 1339         }
 1340         sc->sc_status.button = sc->sc_ibtn ? MOUSE_BUTTON1DOWN : 0;
 1341 }
 1342 
 1343 /*
 1344  * Match a pressure-span against a stroke-component. If there is a
 1345  * match, update the component's state and return true.
 1346  */
 1347 static boolean_t
 1348 fg_match_stroke_component(fg_stroke_component_t *component,
 1349     const fg_pspan *pspan, atp_stroke_type stroke_type)
 1350 {
 1351         int   delta_mickeys;
 1352         u_int min_pressure;
 1353 
 1354         delta_mickeys = pspan->loc - component->loc;
 1355 
 1356         if (abs(delta_mickeys) > (int)FG_MAX_DELTA_MICKEYS)
 1357                 return (false); /* the finger span is too far out; no match */
 1358 
 1359         component->loc = pspan->loc;
 1360 
 1361         /*
 1362          * A sudden and significant increase in a pspan's cumulative
 1363          * pressure indicates the incidence of a new finger
 1364          * contact. This usually revises the pspan's
 1365          * centre-of-gravity, and hence the location of any/all
 1366          * matching stroke component(s). But such a change should
 1367          * *not* be interpreted as a movement.
 1368          */
 1369         if (pspan->cum > ((3 * component->cum_pressure) >> 1))
 1370                 delta_mickeys = 0;
 1371 
 1372         component->cum_pressure = pspan->cum;
 1373         if (pspan->cum > component->max_cum_pressure)
 1374                 component->max_cum_pressure = pspan->cum;
 1375 
 1376         /*
 1377          * Disregard the component's movement if its cumulative
 1378          * pressure drops below a fraction of the maximum; this
 1379          * fraction is determined based on the stroke's type.
 1380          */
 1381         if (stroke_type == ATP_STROKE_TOUCH)
 1382                 min_pressure = (3 * component->max_cum_pressure) >> 2;
 1383         else
 1384                 min_pressure = component->max_cum_pressure >> 2;
 1385         if (component->cum_pressure < min_pressure)
 1386                 delta_mickeys = 0;
 1387 
 1388         component->delta_mickeys = delta_mickeys;
 1389         return (true);
 1390 }
 1391 
 1392 static void
 1393 fg_match_strokes_against_pspans(struct atp_softc *sc, atp_axis axis,
 1394     fg_pspan *pspans, u_int n_pspans, u_int repeat_count)
 1395 {
 1396         atp_stroke_t *strokep;
 1397         u_int repeat_index = 0;
 1398         u_int i;
 1399 
 1400         /* Determine the index of the multi-span. */
 1401         if (repeat_count) {
 1402                 for (i = 0; i < n_pspans; i++) {
 1403                         if (pspans[i].cum > pspans[repeat_index].cum)
 1404                                 repeat_index = i;
 1405                 }
 1406         }
 1407 
 1408         TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
 1409                 if (strokep->components[axis].matched)
 1410                         continue; /* skip matched components */
 1411 
 1412                 for (i = 0; i < n_pspans; i++) {
 1413                         if (pspans[i].matched)
 1414                                 continue; /* skip matched pspans */
 1415 
 1416                         if (fg_match_stroke_component(
 1417                             &strokep->components[axis], &pspans[i],
 1418                             strokep->type)) {
 1419                                 /* There is a match. */
 1420                                 strokep->components[axis].matched = true;
 1421 
 1422                                 /* Take care to repeat at the multi-span. */
 1423                                 if ((repeat_count > 0) && (i == repeat_index))
 1424                                         repeat_count--;
 1425                                 else
 1426                                         pspans[i].matched = true;
 1427 
 1428                                 break; /* skip to the next strokep */
 1429                         }
 1430                 } /* loop over pspans */
 1431         } /* loop over strokes */
 1432 }
 1433 
 1434 static boolean_t
 1435 wsp_match_strokes_against_fingers(struct atp_softc *sc,
 1436     wsp_finger_t *fingers, u_int n_fingers)
 1437 {
 1438         boolean_t movement = false;
 1439         atp_stroke_t *strokep;
 1440         u_int i;
 1441 
 1442         /* reset the matched status for all strokes */
 1443         TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry)
 1444                 strokep->matched = false;
 1445 
 1446         for (i = 0; i != n_fingers; i++) {
 1447                 u_int least_distance_sq = WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ;
 1448                 atp_stroke_t *strokep_best = NULL;
 1449 
 1450                 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
 1451                         int instantaneous_dx;
 1452                         int instantaneous_dy;
 1453                         u_int d_squared;
 1454 
 1455                         if (strokep->matched)
 1456                                 continue;
 1457 
 1458                         instantaneous_dx = fingers[i].x - strokep->x;
 1459                         instantaneous_dy = fingers[i].y - strokep->y;
 1460 
 1461                         /* skip strokes which are far away */
 1462                         d_squared =
 1463                             (instantaneous_dx * instantaneous_dx) +
 1464                             (instantaneous_dy * instantaneous_dy);
 1465 
 1466                         if (d_squared < least_distance_sq) {
 1467                                 least_distance_sq = d_squared;
 1468                                 strokep_best = strokep;
 1469                         }
 1470                 }
 1471 
 1472                 strokep = strokep_best;
 1473 
 1474                 if (strokep != NULL) {
 1475                         fingers[i].matched = true;
 1476 
 1477                         strokep->matched          = true;
 1478                         strokep->instantaneous_dx = fingers[i].x - strokep->x;
 1479                         strokep->instantaneous_dy = fingers[i].y - strokep->y;
 1480                         strokep->x                = fingers[i].x;
 1481                         strokep->y                = fingers[i].y;
 1482 
 1483                         atp_advance_stroke_state(sc, strokep, &movement);
 1484                 }
 1485         }
 1486         return (movement);
 1487 }
 1488 
 1489 /*
 1490  * Update strokes by matching against current pressure-spans.
 1491  * Return true if any movement is detected.
 1492  */
 1493 static boolean_t
 1494 fg_update_strokes(struct atp_softc *sc, fg_pspan *pspans_x,
 1495     u_int n_xpspans, fg_pspan *pspans_y, u_int n_ypspans)
 1496 {
 1497         atp_stroke_t *strokep;
 1498         atp_stroke_t *strokep_next;
 1499         boolean_t movement = false;
 1500         u_int repeat_count = 0;
 1501         u_int i;
 1502         u_int j;
 1503 
 1504         /* Reset X and Y components of all strokes as unmatched. */
 1505         TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
 1506                 strokep->components[X].matched = false;
 1507                 strokep->components[Y].matched = false;
 1508         }
 1509 
 1510         /*
 1511          * Usually, the X and Y pspans come in pairs (the common case
 1512          * being a single pair). It is possible, however, that
 1513          * multiple contacts resolve to a single pspan along an
 1514          * axis, as illustrated in the following:
 1515          *
 1516          *   F = finger-contact
 1517          *
 1518          *                pspan  pspan
 1519          *        +-----------------------+
 1520          *        |         .      .      |
 1521          *        |         .      .      |
 1522          *        |         .      .      |
 1523          *        |         .      .      |
 1524          *  pspan |.........F......F      |
 1525          *        |                       |
 1526          *        |                       |
 1527          *        |                       |
 1528          *        +-----------------------+
 1529          *
 1530          *
 1531          * The above case can be detected by a difference in the
 1532          * number of X and Y pspans. When this happens, X and Y pspans
 1533          * aren't easy to pair or match against strokes.
 1534          *
 1535          * When X and Y pspans differ in number, the axis with the
 1536          * smaller number of pspans is regarded as having a repeating
 1537          * pspan (or a multi-pspan)--in the above illustration, the
 1538          * Y-axis has a repeating pspan. Our approach is to try to
 1539          * match the multi-pspan repeatedly against strokes. The
 1540          * difference between the number of X and Y pspans gives us a
 1541          * crude repeat_count for matching multi-pspans--i.e. the
 1542          * multi-pspan along the Y axis (above) has a repeat_count of 1.
 1543          */
 1544         repeat_count = abs(n_xpspans - n_ypspans);
 1545 
 1546         fg_match_strokes_against_pspans(sc, X, pspans_x, n_xpspans,
 1547             (((repeat_count != 0) && ((n_xpspans < n_ypspans))) ?
 1548                 repeat_count : 0));
 1549         fg_match_strokes_against_pspans(sc, Y, pspans_y, n_ypspans,
 1550             (((repeat_count != 0) && (n_ypspans < n_xpspans)) ?
 1551                 repeat_count : 0));
 1552 
 1553         /* Update the state of strokes based on the above pspan matches. */
 1554         TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) {
 1555                 if (strokep->components[X].matched &&
 1556                     strokep->components[Y].matched) {
 1557                         strokep->matched = true;
 1558                         strokep->instantaneous_dx =
 1559                             strokep->components[X].delta_mickeys;
 1560                         strokep->instantaneous_dy =
 1561                             strokep->components[Y].delta_mickeys;
 1562                         atp_advance_stroke_state(sc, strokep, &movement);
 1563                 } else {
 1564                         /*
 1565                          * At least one component of this stroke
 1566                          * didn't match against current pspans;
 1567                          * terminate it.
 1568                          */
 1569                         atp_terminate_stroke(sc, strokep);
 1570                 }
 1571         }
 1572 
 1573         /* Add new strokes for pairs of unmatched pspans */
 1574         for (i = 0; i < n_xpspans; i++) {
 1575                 if (pspans_x[i].matched == false) break;
 1576         }
 1577         for (j = 0; j < n_ypspans; j++) {
 1578                 if (pspans_y[j].matched == false) break;
 1579         }
 1580         if ((i < n_xpspans) && (j < n_ypspans)) {
 1581 #ifdef USB_DEBUG
 1582                 if (atp_debug >= ATP_LLEVEL_INFO) {
 1583                         printf("unmatched pspans:");
 1584                         for (; i < n_xpspans; i++) {
 1585                                 if (pspans_x[i].matched)
 1586                                         continue;
 1587                                 printf(" X:[loc:%u,cum:%u]",
 1588                                     pspans_x[i].loc, pspans_x[i].cum);
 1589                         }
 1590                         for (; j < n_ypspans; j++) {
 1591                                 if (pspans_y[j].matched)
 1592                                         continue;
 1593                                 printf(" Y:[loc:%u,cum:%u]",
 1594                                     pspans_y[j].loc, pspans_y[j].cum);
 1595                         }
 1596                         printf("\n");
 1597                 }
 1598 #endif /* USB_DEBUG */
 1599                 if ((n_xpspans == 1) && (n_ypspans == 1))
 1600                         /* The common case of a single pair of new pspans. */
 1601                         fg_add_stroke(sc, &pspans_x[0], &pspans_y[0]);
 1602                 else
 1603                         fg_add_new_strokes(sc, pspans_x, n_xpspans,
 1604                             pspans_y, n_ypspans);
 1605         }
 1606 
 1607 #ifdef USB_DEBUG
 1608         if (atp_debug >= ATP_LLEVEL_INFO) {
 1609                 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
 1610                         printf(" %s%clc:%u,dm:%d,cum:%d,max:%d,%c"
 1611                             ",%clc:%u,dm:%d,cum:%d,max:%d,%c",
 1612                             (strokep->flags & ATSF_ZOMBIE) ? "zomb:" : "",
 1613                             (strokep->type == ATP_STROKE_TOUCH) ? '[' : '<',
 1614                             strokep->components[X].loc,
 1615                             strokep->components[X].delta_mickeys,
 1616                             strokep->components[X].cum_pressure,
 1617                             strokep->components[X].max_cum_pressure,
 1618                             (strokep->type == ATP_STROKE_TOUCH) ? ']' : '>',
 1619                             (strokep->type == ATP_STROKE_TOUCH) ? '[' : '<',
 1620                             strokep->components[Y].loc,
 1621                             strokep->components[Y].delta_mickeys,
 1622                             strokep->components[Y].cum_pressure,
 1623                             strokep->components[Y].max_cum_pressure,
 1624                             (strokep->type == ATP_STROKE_TOUCH) ? ']' : '>');
 1625                 }
 1626                 if (TAILQ_FIRST(&sc->sc_stroke_used) != NULL)
 1627                         printf("\n");
 1628         }
 1629 #endif /* USB_DEBUG */
 1630         return (movement);
 1631 }
 1632 
 1633 /*
 1634  * Update strokes by matching against current pressure-spans.
 1635  * Return true if any movement is detected.
 1636  */
 1637 static boolean_t
 1638 wsp_update_strokes(struct atp_softc *sc, wsp_finger_t fingers[WSP_MAX_FINGERS],
 1639     u_int n_fingers)
 1640 {
 1641         boolean_t movement = false;
 1642         atp_stroke_t *strokep_next;
 1643         atp_stroke_t *strokep;
 1644         u_int i;
 1645 
 1646         if (sc->sc_n_strokes > 0) {
 1647                 movement = wsp_match_strokes_against_fingers(
 1648                     sc, fingers, n_fingers);
 1649 
 1650                 /* handle zombie strokes */
 1651                 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) {
 1652                         if (strokep->matched)
 1653                                 continue;
 1654                         atp_terminate_stroke(sc, strokep);
 1655                 }
 1656         }
 1657 
 1658         /* initialize unmatched fingers as strokes */
 1659         for (i = 0; i != n_fingers; i++) {
 1660                 if (fingers[i].matched)
 1661                         continue;
 1662 
 1663                 wsp_add_stroke(sc, fingers + i);
 1664         }
 1665         return (movement);
 1666 }
 1667 
 1668 /* Initialize a stroke using a pressure-span. */
 1669 static void
 1670 fg_add_stroke(struct atp_softc *sc, const fg_pspan *pspan_x,
 1671     const fg_pspan *pspan_y)
 1672 {
 1673         atp_stroke_t *strokep;
 1674 
 1675         strokep = atp_alloc_stroke(sc);
 1676         if (strokep == NULL)
 1677                 return;
 1678 
 1679         /*
 1680          * Strokes begin as potential touches. If a stroke survives
 1681          * longer than a threshold, or if it records significant
 1682          * cumulative movement, then it is considered a 'slide'.
 1683          */
 1684         strokep->type    = ATP_STROKE_TOUCH;
 1685         strokep->matched = false;
 1686         microtime(&strokep->ctime);
 1687         strokep->age     = 1;           /* number of interrupts */
 1688         strokep->x       = pspan_x->loc;
 1689         strokep->y       = pspan_y->loc;
 1690 
 1691         strokep->components[X].loc              = pspan_x->loc;
 1692         strokep->components[X].cum_pressure     = pspan_x->cum;
 1693         strokep->components[X].max_cum_pressure = pspan_x->cum;
 1694         strokep->components[X].matched          = true;
 1695 
 1696         strokep->components[Y].loc              = pspan_y->loc;
 1697         strokep->components[Y].cum_pressure     = pspan_y->cum;
 1698         strokep->components[Y].max_cum_pressure = pspan_y->cum;
 1699         strokep->components[Y].matched          = true;
 1700 
 1701         if (sc->sc_n_strokes > 1) {
 1702                 /* Reset double-tap-n-drag if we have more than one strokes. */
 1703                 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG;
 1704         }
 1705 
 1706         DPRINTFN(ATP_LLEVEL_INFO, "[%u,%u], time: %u,%ld\n",
 1707             strokep->components[X].loc,
 1708             strokep->components[Y].loc,
 1709             (u_int)strokep->ctime.tv_sec,
 1710             (unsigned long int)strokep->ctime.tv_usec);
 1711 }
 1712 
 1713 static void
 1714 fg_add_new_strokes(struct atp_softc *sc, fg_pspan *pspans_x,
 1715     u_int n_xpspans, fg_pspan *pspans_y, u_int n_ypspans)
 1716 {
 1717         fg_pspan spans[2][FG_MAX_PSPANS_PER_AXIS];
 1718         u_int nspans[2];
 1719         u_int i;
 1720         u_int j;
 1721 
 1722         /* Copy unmatched pspans into the local arrays. */
 1723         for (i = 0, nspans[X] = 0; i < n_xpspans; i++) {
 1724                 if (pspans_x[i].matched == false) {
 1725                         spans[X][nspans[X]] = pspans_x[i];
 1726                         nspans[X]++;
 1727                 }
 1728         }
 1729         for (j = 0, nspans[Y] = 0; j < n_ypspans; j++) {
 1730                 if (pspans_y[j].matched == false) {
 1731                         spans[Y][nspans[Y]] = pspans_y[j];
 1732                         nspans[Y]++;
 1733                 }
 1734         }
 1735 
 1736         if (nspans[X] == nspans[Y]) {
 1737                 /* Create new strokes from pairs of unmatched pspans */
 1738                 for (i = 0, j = 0; (i < nspans[X]) && (j < nspans[Y]); i++, j++)
 1739                         fg_add_stroke(sc, &spans[X][i], &spans[Y][j]);
 1740         } else {
 1741                 u_int    cum = 0;
 1742                 atp_axis repeat_axis;      /* axis with multi-pspans */
 1743                 u_int    repeat_count;     /* repeat count for the multi-pspan*/
 1744                 u_int    repeat_index = 0; /* index of the multi-span */
 1745 
 1746                 repeat_axis  = (nspans[X] > nspans[Y]) ? Y : X;
 1747                 repeat_count = abs(nspans[X] - nspans[Y]);
 1748                 for (i = 0; i < nspans[repeat_axis]; i++) {
 1749                         if (spans[repeat_axis][i].cum > cum) {
 1750                                 repeat_index = i;
 1751                                 cum = spans[repeat_axis][i].cum;
 1752                         }
 1753                 }
 1754 
 1755                 /* Create new strokes from pairs of unmatched pspans */
 1756                 i = 0, j = 0;
 1757                 for (; (i < nspans[X]) && (j < nspans[Y]); i++, j++) {
 1758                         fg_add_stroke(sc, &spans[X][i], &spans[Y][j]);
 1759 
 1760                         /* Take care to repeat at the multi-pspan. */
 1761                         if (repeat_count > 0) {
 1762                                 if ((repeat_axis == X) &&
 1763                                     (repeat_index == i)) {
 1764                                         i--; /* counter loop increment */
 1765                                         repeat_count--;
 1766                                 } else if ((repeat_axis == Y) &&
 1767                                     (repeat_index == j)) {
 1768                                         j--; /* counter loop increment */
 1769                                         repeat_count--;
 1770                                 }
 1771                         }
 1772                 }
 1773         }
 1774 }
 1775 
 1776 /* Initialize a stroke from an unmatched finger. */
 1777 static void
 1778 wsp_add_stroke(struct atp_softc *sc, const wsp_finger_t *fingerp)
 1779 {
 1780         atp_stroke_t *strokep;
 1781 
 1782         strokep = atp_alloc_stroke(sc);
 1783         if (strokep == NULL)
 1784                 return;
 1785 
 1786         /*
 1787          * Strokes begin as potential touches. If a stroke survives
 1788          * longer than a threshold, or if it records significant
 1789          * cumulative movement, then it is considered a 'slide'.
 1790          */
 1791         strokep->type    = ATP_STROKE_TOUCH;
 1792         strokep->matched = true;
 1793         microtime(&strokep->ctime);
 1794         strokep->age = 1;       /* number of interrupts */
 1795         strokep->x = fingerp->x;
 1796         strokep->y = fingerp->y;
 1797 
 1798         /* Reset double-tap-n-drag if we have more than one strokes. */
 1799         if (sc->sc_n_strokes > 1)
 1800                 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG;
 1801 
 1802         DPRINTFN(ATP_LLEVEL_INFO, "[%d,%d]\n", strokep->x, strokep->y);
 1803 }
 1804 
 1805 static void
 1806 atp_advance_stroke_state(struct atp_softc *sc, atp_stroke_t *strokep,
 1807     boolean_t *movementp)
 1808 {
 1809         /* Revitalize stroke if it had previously been marked as a zombie. */
 1810         if (strokep->flags & ATSF_ZOMBIE)
 1811                 strokep->flags &= ~ATSF_ZOMBIE;
 1812 
 1813         strokep->age++;
 1814         if (strokep->age <= atp_stroke_maturity_threshold) {
 1815                 /* Avoid noise from immature strokes. */
 1816                 strokep->instantaneous_dx = 0;
 1817                 strokep->instantaneous_dy = 0;
 1818         }
 1819 
 1820         if (atp_compute_stroke_movement(strokep))
 1821                 *movementp = true;
 1822 
 1823         if (strokep->type != ATP_STROKE_TOUCH)
 1824                 return;
 1825 
 1826         /* Convert touch strokes to slides upon detecting movement or age. */
 1827         if ((abs(strokep->cum_movement_x) > atp_slide_min_movement) ||
 1828             (abs(strokep->cum_movement_y) > atp_slide_min_movement))
 1829                 atp_convert_to_slide(sc, strokep);
 1830         else {
 1831                 /* Compute the stroke's age. */
 1832                 struct timeval tdiff;
 1833                 getmicrotime(&tdiff);
 1834                 if (timevalcmp(&tdiff, &strokep->ctime, >)) {
 1835                         timevalsub(&tdiff, &strokep->ctime);
 1836 
 1837                         if ((tdiff.tv_sec > (atp_touch_timeout / 1000000)) ||
 1838                             ((tdiff.tv_sec == (atp_touch_timeout / 1000000)) &&
 1839                              (tdiff.tv_usec >= (atp_touch_timeout % 1000000))))
 1840                                 atp_convert_to_slide(sc, strokep);
 1841                 }
 1842         }
 1843 }
 1844 
 1845 static boolean_t
 1846 atp_stroke_has_small_movement(const atp_stroke_t *strokep)
 1847 {
 1848         return (((u_int)abs(strokep->instantaneous_dx) <=
 1849                  atp_small_movement_threshold) &&
 1850                 ((u_int)abs(strokep->instantaneous_dy) <=
 1851                  atp_small_movement_threshold));
 1852 }
 1853 
 1854 /*
 1855  * Accumulate instantaneous changes into the stroke's 'pending' bucket; if
 1856  * the aggregate exceeds the small_movement_threshold, then retain
 1857  * instantaneous changes for later.
 1858  */
 1859 static void
 1860 atp_update_pending_mickeys(atp_stroke_t *strokep)
 1861 {
 1862         /* accumulate instantaneous movement */
 1863         strokep->pending_dx += strokep->instantaneous_dx;
 1864         strokep->pending_dy += strokep->instantaneous_dy;
 1865 
 1866 #define UPDATE_INSTANTANEOUS_AND_PENDING(I, P)                          \
 1867         if (abs((P)) <= atp_small_movement_threshold)                   \
 1868                 (I) = 0; /* clobber small movement */                   \
 1869         else {                                                          \
 1870                 if ((I) > 0) {                                          \
 1871                         /*                                              \
 1872                          * Round up instantaneous movement to the nearest \
 1873                          * ceiling. This helps preserve small mickey    \
 1874                          * movements from being lost in following scaling \
 1875                          * operation.                                   \
 1876                          */                                             \
 1877                         (I) = (((I) + (atp_mickeys_scale_factor - 1)) / \
 1878                                atp_mickeys_scale_factor) *              \
 1879                               atp_mickeys_scale_factor;                 \
 1880                                                                         \
 1881                         /*                                              \
 1882                          * Deduct the rounded mickeys from pending mickeys. \
 1883                          * Note: we multiply by 2 to offset the previous \
 1884                          * accumulation of instantaneous movement into  \
 1885                          * pending.                                     \
 1886                          */                                             \
 1887                         (P) -= ((I) << 1);                              \
 1888                                                                         \
 1889                         /* truncate pending to 0 if it becomes negative. */ \
 1890                         (P) = imax((P), 0);                             \
 1891                 } else {                                                \
 1892                         /*                                              \
 1893                          * Round down instantaneous movement to the nearest \
 1894                          * ceiling. This helps preserve small mickey    \
 1895                          * movements from being lost in following scaling \
 1896                          * operation.                                   \
 1897                          */                                             \
 1898                         (I) = (((I) - (atp_mickeys_scale_factor - 1)) / \
 1899                                atp_mickeys_scale_factor) *              \
 1900                               atp_mickeys_scale_factor;                 \
 1901                                                                         \
 1902                         /*                                              \
 1903                          * Deduct the rounded mickeys from pending mickeys. \
 1904                          * Note: we multiply by 2 to offset the previous \
 1905                          * accumulation of instantaneous movement into  \
 1906                          * pending.                                     \
 1907                          */                                             \
 1908                         (P) -= ((I) << 1);                              \
 1909                                                                         \
 1910                         /* truncate pending to 0 if it becomes positive. */ \
 1911                         (P) = imin((P), 0);                             \
 1912                 }                                                       \
 1913         }
 1914 
 1915         UPDATE_INSTANTANEOUS_AND_PENDING(strokep->instantaneous_dx,
 1916             strokep->pending_dx);
 1917         UPDATE_INSTANTANEOUS_AND_PENDING(strokep->instantaneous_dy,
 1918             strokep->pending_dy);
 1919 }
 1920 
 1921 /*
 1922  * Compute a smoothened value for the stroke's movement from
 1923  * instantaneous changes in the X and Y components.
 1924  */
 1925 static boolean_t
 1926 atp_compute_stroke_movement(atp_stroke_t *strokep)
 1927 {
 1928         /*
 1929          * Short movements are added first to the 'pending' bucket,
 1930          * and then acted upon only when their aggregate exceeds a
 1931          * threshold. This has the effect of filtering away movement
 1932          * noise.
 1933          */
 1934         if (atp_stroke_has_small_movement(strokep))
 1935                 atp_update_pending_mickeys(strokep);
 1936         else {                /* large movement */
 1937                 /* clear away any pending mickeys if there are large movements*/
 1938                 strokep->pending_dx = 0;
 1939                 strokep->pending_dy = 0;
 1940         }
 1941 
 1942         /* scale movement */
 1943         strokep->movement_dx = (strokep->instantaneous_dx) /
 1944             (int)atp_mickeys_scale_factor;
 1945         strokep->movement_dy = (strokep->instantaneous_dy) /
 1946             (int)atp_mickeys_scale_factor;
 1947 
 1948         if ((abs(strokep->instantaneous_dx) >= ATP_FAST_MOVEMENT_TRESHOLD) ||
 1949             (abs(strokep->instantaneous_dy) >= ATP_FAST_MOVEMENT_TRESHOLD)) {
 1950                 strokep->movement_dx <<= 1;
 1951                 strokep->movement_dy <<= 1;
 1952         }
 1953 
 1954         strokep->cum_movement_x += strokep->movement_dx;
 1955         strokep->cum_movement_y += strokep->movement_dy;
 1956 
 1957         return ((strokep->movement_dx != 0) || (strokep->movement_dy != 0));
 1958 }
 1959 
 1960 /*
 1961  * Terminate a stroke. Aside from immature strokes, a slide or touch is
 1962  * retained as a zombies so as to reap all their termination siblings
 1963  * together; this helps establish the number of fingers involved at the
 1964  * end of a multi-touch gesture.
 1965  */
 1966 static void
 1967 atp_terminate_stroke(struct atp_softc *sc, atp_stroke_t *strokep)
 1968 {
 1969         if (strokep->flags & ATSF_ZOMBIE)
 1970                 return;
 1971 
 1972         /* Drop immature strokes rightaway. */
 1973         if (strokep->age <= atp_stroke_maturity_threshold) {
 1974                 atp_free_stroke(sc, strokep);
 1975                 return;
 1976         }
 1977 
 1978         strokep->flags |= ATSF_ZOMBIE;
 1979         sc->sc_state |= ATP_ZOMBIES_EXIST;
 1980 
 1981         callout_reset(&sc->sc_callout, ATP_ZOMBIE_STROKE_REAP_INTERVAL,
 1982             atp_reap_sibling_zombies, sc);
 1983 
 1984         /*
 1985          * Reset the double-click-n-drag at the termination of any
 1986          * slide stroke.
 1987          */
 1988         if (strokep->type == ATP_STROKE_SLIDE)
 1989                 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG;
 1990 }
 1991 
 1992 static boolean_t
 1993 atp_is_horizontal_scroll(const atp_stroke_t *strokep)
 1994 {
 1995         if (abs(strokep->cum_movement_x) < atp_slide_min_movement)
 1996                 return (false);
 1997         if (strokep->cum_movement_y == 0)
 1998                 return (true);
 1999         return (abs(strokep->cum_movement_x / strokep->cum_movement_y) >= 4);
 2000 }
 2001 
 2002 static boolean_t
 2003 atp_is_vertical_scroll(const atp_stroke_t *strokep)
 2004 {
 2005         if (abs(strokep->cum_movement_y) < atp_slide_min_movement)
 2006                 return (false);
 2007         if (strokep->cum_movement_x == 0)
 2008                 return (true);
 2009         return (abs(strokep->cum_movement_y / strokep->cum_movement_x) >= 4);
 2010 }
 2011 
 2012 static void
 2013 atp_reap_sibling_zombies(void *arg)
 2014 {
 2015         struct atp_softc *sc = (struct atp_softc *)arg;
 2016         u_int8_t n_touches_reaped = 0;
 2017         u_int8_t n_slides_reaped = 0;
 2018         u_int8_t n_horizontal_scrolls = 0;
 2019         int horizontal_scroll = 0;
 2020         atp_stroke_t *strokep;
 2021         atp_stroke_t *strokep_next;
 2022 
 2023         DPRINTFN(ATP_LLEVEL_INFO, "\n");
 2024 
 2025         TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) {
 2026                 if ((strokep->flags & ATSF_ZOMBIE) == 0)
 2027                         continue;
 2028 
 2029                 if (strokep->type == ATP_STROKE_TOUCH) {
 2030                         n_touches_reaped++;
 2031                 } else {
 2032                         n_slides_reaped++;
 2033 
 2034                         if (atp_is_horizontal_scroll(strokep)) {
 2035                                 n_horizontal_scrolls++;
 2036                                 horizontal_scroll += strokep->cum_movement_x;
 2037                         }
 2038                 }
 2039 
 2040                 atp_free_stroke(sc, strokep);
 2041         }
 2042 
 2043         DPRINTFN(ATP_LLEVEL_INFO, "reaped %u zombies\n",
 2044             n_touches_reaped + n_slides_reaped);
 2045         sc->sc_state &= ~ATP_ZOMBIES_EXIST;
 2046 
 2047         /* No further processing necessary if physical button is depressed. */
 2048         if (sc->sc_ibtn != 0)
 2049                 return;
 2050 
 2051         if ((n_touches_reaped == 0) && (n_slides_reaped == 0))
 2052                 return;
 2053 
 2054         /* Add a pair of virtual button events (button-down and button-up) if
 2055          * the physical button isn't pressed. */
 2056         if (n_touches_reaped != 0) {
 2057                 if (n_touches_reaped < atp_tap_minimum)
 2058                         return;
 2059 
 2060                 switch (n_touches_reaped) {
 2061                 case 1:
 2062                         atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON1DOWN);
 2063                         microtime(&sc->sc_touch_reap_time); /* remember this time */
 2064                         break;
 2065                 case 2:
 2066                         atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON3DOWN);
 2067                         break;
 2068                 case 3:
 2069                         atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON2DOWN);
 2070                         break;
 2071                 default:
 2072                         /* we handle taps of only up to 3 fingers */
 2073                         return;
 2074                 }
 2075                 atp_add_to_queue(sc, 0, 0, 0, 0); /* button release */
 2076 
 2077         } else if ((n_slides_reaped == 2) && (n_horizontal_scrolls == 2)) {
 2078                 if (horizontal_scroll < 0)
 2079                         atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON4DOWN);
 2080                 else
 2081                         atp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON5DOWN);
 2082                 atp_add_to_queue(sc, 0, 0, 0, 0); /* button release */
 2083         }
 2084 }
 2085 
 2086 /* Switch a given touch stroke to being a slide. */
 2087 static void
 2088 atp_convert_to_slide(struct atp_softc *sc, atp_stroke_t *strokep)
 2089 {
 2090         strokep->type = ATP_STROKE_SLIDE;
 2091 
 2092         /* Are we at the beginning of a double-click-n-drag? */
 2093         if ((sc->sc_n_strokes == 1) &&
 2094             ((sc->sc_state & ATP_ZOMBIES_EXIST) == 0) &&
 2095             timevalcmp(&strokep->ctime, &sc->sc_touch_reap_time, >)) {
 2096                 struct timeval delta;
 2097                 struct timeval window = {
 2098                         atp_double_tap_threshold / 1000000,
 2099                         atp_double_tap_threshold % 1000000
 2100                 };
 2101 
 2102                 delta = strokep->ctime;
 2103                 timevalsub(&delta, &sc->sc_touch_reap_time);
 2104                 if (timevalcmp(&delta, &window, <=))
 2105                         sc->sc_state |= ATP_DOUBLE_TAP_DRAG;
 2106         }
 2107 }
 2108 
 2109 static void
 2110 atp_reset_buf(struct atp_softc *sc)
 2111 {
 2112         /* reset read queue */
 2113         usb_fifo_reset(sc->sc_fifo.fp[USB_FIFO_RX]);
 2114 }
 2115 
 2116 static void
 2117 atp_add_to_queue(struct atp_softc *sc, int dx, int dy, int dz,
 2118     uint32_t buttons_in)
 2119 {
 2120         uint32_t buttons_out;
 2121         uint8_t  buf[8];
 2122 
 2123         dx = imin(dx,  254); dx = imax(dx, -256);
 2124         dy = imin(dy,  254); dy = imax(dy, -256);
 2125         dz = imin(dz,  126); dz = imax(dz, -128);
 2126 
 2127         buttons_out = MOUSE_MSC_BUTTONS;
 2128         if (buttons_in & MOUSE_BUTTON1DOWN)
 2129                 buttons_out &= ~MOUSE_MSC_BUTTON1UP;
 2130         else if (buttons_in & MOUSE_BUTTON2DOWN)
 2131                 buttons_out &= ~MOUSE_MSC_BUTTON2UP;
 2132         else if (buttons_in & MOUSE_BUTTON3DOWN)
 2133                 buttons_out &= ~MOUSE_MSC_BUTTON3UP;
 2134 
 2135         DPRINTFN(ATP_LLEVEL_INFO, "dx=%d, dy=%d, buttons=%x\n",
 2136             dx, dy, buttons_out);
 2137 
 2138         /* Encode the mouse data in standard format; refer to mouse(4) */
 2139         buf[0] = sc->sc_mode.syncmask[1];
 2140         buf[0] |= buttons_out;
 2141         buf[1] = dx >> 1;
 2142         buf[2] = dy >> 1;
 2143         buf[3] = dx - (dx >> 1);
 2144         buf[4] = dy - (dy >> 1);
 2145         /* Encode extra bytes for level 1 */
 2146         if (sc->sc_mode.level == 1) {
 2147                 buf[5] = dz >> 1;
 2148                 buf[6] = dz - (dz >> 1);
 2149                 buf[7] = (((~buttons_in) >> 3) & MOUSE_SYS_EXTBUTTONS);
 2150         }
 2151 
 2152         usb_fifo_put_data_linear(sc->sc_fifo.fp[USB_FIFO_RX], buf,
 2153             sc->sc_mode.packetsize, 1);
 2154 }
 2155 
 2156 static int
 2157 atp_probe(device_t self)
 2158 {
 2159         struct usb_attach_arg *uaa = device_get_ivars(self);
 2160 
 2161         if (uaa->usb_mode != USB_MODE_HOST)
 2162                 return (ENXIO);
 2163 
 2164         if (uaa->info.bInterfaceClass != UICLASS_HID)
 2165                 return (ENXIO);
 2166         /*
 2167          * Note: for some reason, the check
 2168          * (uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) doesn't hold true
 2169          * for wellspring trackpads, so we've removed it from the common path.
 2170          */
 2171 
 2172         if ((usbd_lookup_id_by_uaa(fg_devs, sizeof(fg_devs), uaa)) == 0)
 2173                 return ((uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) ?
 2174                         BUS_PROBE_DEFAULT : ENXIO);
 2175 
 2176         if ((usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa)) == 0)
 2177                 if (uaa->info.bIfaceIndex == WELLSPRING_INTERFACE_INDEX)
 2178                         return (BUS_PROBE_DEFAULT);
 2179 
 2180         return (ENXIO);
 2181 }
 2182 
 2183 static int
 2184 atp_attach(device_t dev)
 2185 {
 2186         struct atp_softc      *sc  = device_get_softc(dev);
 2187         struct usb_attach_arg *uaa = device_get_ivars(dev);
 2188         usb_error_t            err;
 2189         void *descriptor_ptr = NULL;
 2190         uint16_t descriptor_len;
 2191         unsigned long di;
 2192 
 2193         DPRINTFN(ATP_LLEVEL_INFO, "sc=%p\n", sc);
 2194 
 2195         sc->sc_dev        = dev;
 2196         sc->sc_usb_device = uaa->device;
 2197 
 2198         /* Get HID descriptor */
 2199         if (usbd_req_get_hid_desc(uaa->device, NULL, &descriptor_ptr,
 2200             &descriptor_len, M_TEMP, uaa->info.bIfaceIndex) !=
 2201             USB_ERR_NORMAL_COMPLETION)
 2202                 return (ENXIO);
 2203 
 2204         /* Get HID report descriptor length */
 2205         sc->sc_expected_sensor_data_len = hid_report_size_max(descriptor_ptr,
 2206             descriptor_len, hid_input, NULL);
 2207         free(descriptor_ptr, M_TEMP);
 2208 
 2209         if ((sc->sc_expected_sensor_data_len <= 0) ||
 2210             (sc->sc_expected_sensor_data_len > ATP_SENSOR_DATA_BUF_MAX)) {
 2211                 DPRINTF("atp_attach: datalength invalid or too large: %d\n",
 2212                         sc->sc_expected_sensor_data_len);
 2213                 return (ENXIO);
 2214         }
 2215 
 2216         di = USB_GET_DRIVER_INFO(uaa);
 2217         sc->sc_family = DECODE_FAMILY_FROM_DRIVER_INFO(di);
 2218 
 2219         /*
 2220          * By default the touchpad behaves like an HID device, sending
 2221          * packets with reportID = 2. Such reports contain only
 2222          * limited information--they encode movement deltas and button
 2223          * events,--but do not include data from the pressure
 2224          * sensors. The device input mode can be switched from HID
 2225          * reports to raw sensor data using vendor-specific USB
 2226          * control commands.
 2227          * FOUNTAIN devices will give an error when trying to switch
 2228          * input mode, so we skip this command
 2229          */
 2230         if ((sc->sc_family == TRACKPAD_FAMILY_FOUNTAIN_GEYSER) &&
 2231                 (DECODE_PRODUCT_FROM_DRIVER_INFO(di) == FOUNTAIN))
 2232                 DPRINTF("device mode switch skipped: Fountain device\n");
 2233         else if ((err = atp_set_device_mode(sc, RAW_SENSOR_MODE)) != 0) {
 2234                 DPRINTF("failed to set mode to 'RAW_SENSOR' (%d)\n", err);
 2235                 return (ENXIO);
 2236         }
 2237 
 2238         mtx_init(&sc->sc_mutex, "atpmtx", NULL, MTX_DEF | MTX_RECURSE);
 2239 
 2240         switch(sc->sc_family) {
 2241         case TRACKPAD_FAMILY_FOUNTAIN_GEYSER:
 2242                 sc->sc_params =
 2243                     &fg_dev_params[DECODE_PRODUCT_FROM_DRIVER_INFO(di)];
 2244                 sc->sensor_data_interpreter = fg_interpret_sensor_data;
 2245                 break;
 2246         case TRACKPAD_FAMILY_WELLSPRING:
 2247                 sc->sc_params =
 2248                     &wsp_dev_params[DECODE_PRODUCT_FROM_DRIVER_INFO(di)];
 2249                 sc->sensor_data_interpreter = wsp_interpret_sensor_data;
 2250                 break;
 2251         default:
 2252                 goto detach;
 2253         }
 2254 
 2255         err = usbd_transfer_setup(uaa->device,
 2256             &uaa->info.bIfaceIndex, sc->sc_xfer, atp_xfer_config,
 2257             ATP_N_TRANSFER, sc, &sc->sc_mutex);
 2258         if (err) {
 2259                 DPRINTF("error=%s\n", usbd_errstr(err));
 2260                 goto detach;
 2261         }
 2262 
 2263         if (usb_fifo_attach(sc->sc_usb_device, sc, &sc->sc_mutex,
 2264             &atp_fifo_methods, &sc->sc_fifo,
 2265             device_get_unit(dev), -1, uaa->info.bIfaceIndex,
 2266             UID_ROOT, GID_OPERATOR, 0644)) {
 2267                 goto detach;
 2268         }
 2269 
 2270         device_set_usb_desc(dev);
 2271 
 2272         sc->sc_hw.buttons       = 3;
 2273         sc->sc_hw.iftype        = MOUSE_IF_USB;
 2274         sc->sc_hw.type          = MOUSE_PAD;
 2275         sc->sc_hw.model         = MOUSE_MODEL_GENERIC;
 2276         sc->sc_hw.hwid          = 0;
 2277         sc->sc_mode.protocol    = MOUSE_PROTO_MSC;
 2278         sc->sc_mode.rate        = -1;
 2279         sc->sc_mode.resolution  = MOUSE_RES_UNKNOWN;
 2280         sc->sc_mode.packetsize  = MOUSE_MSC_PACKETSIZE;
 2281         sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
 2282         sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
 2283         sc->sc_mode.accelfactor = 0;
 2284         sc->sc_mode.level       = 0;
 2285 
 2286         sc->sc_state            = 0;
 2287         sc->sc_ibtn             = 0;
 2288 
 2289         callout_init_mtx(&sc->sc_callout, &sc->sc_mutex, 0);
 2290 
 2291         return (0);
 2292 
 2293 detach:
 2294         atp_detach(dev);
 2295         return (ENOMEM);
 2296 }
 2297 
 2298 static int
 2299 atp_detach(device_t dev)
 2300 {
 2301         struct atp_softc *sc;
 2302 
 2303         sc = device_get_softc(dev);
 2304         atp_set_device_mode(sc, HID_MODE);
 2305 
 2306         mtx_lock(&sc->sc_mutex);
 2307         callout_drain(&sc->sc_callout);
 2308         if (sc->sc_state & ATP_ENABLED)
 2309                 atp_disable(sc);
 2310         mtx_unlock(&sc->sc_mutex);
 2311 
 2312         usb_fifo_detach(&sc->sc_fifo);
 2313 
 2314         usbd_transfer_unsetup(sc->sc_xfer, ATP_N_TRANSFER);
 2315 
 2316         mtx_destroy(&sc->sc_mutex);
 2317 
 2318         return (0);
 2319 }
 2320 
 2321 static void
 2322 atp_intr(struct usb_xfer *xfer, usb_error_t error)
 2323 {
 2324         struct atp_softc      *sc = usbd_xfer_softc(xfer);
 2325         struct usb_page_cache *pc;
 2326         int len;
 2327 
 2328         usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
 2329 
 2330         switch (USB_GET_STATE(xfer)) {
 2331         case USB_ST_TRANSFERRED:
 2332                 pc = usbd_xfer_get_frame(xfer, 0);
 2333                 usbd_copy_out(pc, 0, sc->sc_sensor_data, len);
 2334                 if (len < sc->sc_expected_sensor_data_len) {
 2335                         /* make sure we don't process old data */
 2336                         memset(sc->sc_sensor_data + len, 0,
 2337                             sc->sc_expected_sensor_data_len - len);
 2338                 }
 2339 
 2340                 sc->sc_status.flags &= ~(MOUSE_STDBUTTONSCHANGED |
 2341                     MOUSE_POSCHANGED);
 2342                 sc->sc_status.obutton = sc->sc_status.button;
 2343 
 2344                 (sc->sensor_data_interpreter)(sc, len);
 2345 
 2346                 if (sc->sc_status.button != 0) {
 2347                         /* Reset DOUBLE_TAP_N_DRAG if the button is pressed. */
 2348                         sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG;
 2349                 } else if (sc->sc_state & ATP_DOUBLE_TAP_DRAG) {
 2350                         /* Assume a button-press with DOUBLE_TAP_N_DRAG. */
 2351                         sc->sc_status.button = MOUSE_BUTTON1DOWN;
 2352                 }
 2353 
 2354                 sc->sc_status.flags |=
 2355                     sc->sc_status.button ^ sc->sc_status.obutton;
 2356                 if (sc->sc_status.flags & MOUSE_STDBUTTONSCHANGED) {
 2357                     DPRINTFN(ATP_LLEVEL_INFO, "button %s\n",
 2358                         ((sc->sc_status.button & MOUSE_BUTTON1DOWN) ?
 2359                         "pressed" : "released"));
 2360                 }
 2361 
 2362                 if (sc->sc_status.flags & (MOUSE_POSCHANGED |
 2363                     MOUSE_STDBUTTONSCHANGED)) {
 2364                         atp_stroke_t *strokep;
 2365                         u_int8_t n_movements = 0;
 2366                         int dx = 0;
 2367                         int dy = 0;
 2368                         int dz = 0;
 2369 
 2370                         TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
 2371                                 if (strokep->flags & ATSF_ZOMBIE)
 2372                                         continue;
 2373 
 2374                                 dx += strokep->movement_dx;
 2375                                 dy += strokep->movement_dy;
 2376                                 if (strokep->movement_dx ||
 2377                                     strokep->movement_dy)
 2378                                         n_movements++;
 2379                         }
 2380 
 2381                         /* average movement if multiple strokes record motion.*/
 2382                         if (n_movements > 1) {
 2383                                 dx /= (int)n_movements;
 2384                                 dy /= (int)n_movements;
 2385                         }
 2386 
 2387                         /* detect multi-finger vertical scrolls */
 2388                         if (n_movements >= 2) {
 2389                                 boolean_t all_vertical_scrolls = true;
 2390                                 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
 2391                                         if (strokep->flags & ATSF_ZOMBIE)
 2392                                                 continue;
 2393 
 2394                                         if (!atp_is_vertical_scroll(strokep))
 2395                                                 all_vertical_scrolls = false;
 2396                                 }
 2397                                 if (all_vertical_scrolls) {
 2398                                         dz = dy;
 2399                                         dy = dx = 0;
 2400                                 }
 2401                         }
 2402 
 2403                         sc->sc_status.dx += dx;
 2404                         sc->sc_status.dy += dy;
 2405                         sc->sc_status.dz += dz;
 2406                         atp_add_to_queue(sc, dx, -dy, -dz, sc->sc_status.button);
 2407                 }
 2408 
 2409         case USB_ST_SETUP:
 2410         tr_setup:
 2411                 /* check if we can put more data into the FIFO */
 2412                 if (usb_fifo_put_bytes_max(sc->sc_fifo.fp[USB_FIFO_RX]) != 0) {
 2413                         usbd_xfer_set_frame_len(xfer, 0,
 2414                             sc->sc_expected_sensor_data_len);
 2415                         usbd_transfer_submit(xfer);
 2416                 }
 2417                 break;
 2418 
 2419         default:                        /* Error */
 2420                 if (error != USB_ERR_CANCELLED) {
 2421                         /* try clear stall first */
 2422                         usbd_xfer_set_stall(xfer);
 2423                         goto tr_setup;
 2424                 }
 2425                 break;
 2426         }
 2427 }
 2428 
 2429 static void
 2430 atp_start_read(struct usb_fifo *fifo)
 2431 {
 2432         struct atp_softc *sc = usb_fifo_softc(fifo);
 2433         int rate;
 2434 
 2435         /* Check if we should override the default polling interval */
 2436         rate = sc->sc_pollrate;
 2437         /* Range check rate */
 2438         if (rate > 1000)
 2439                 rate = 1000;
 2440         /* Check for set rate */
 2441         if ((rate > 0) && (sc->sc_xfer[ATP_INTR_DT] != NULL)) {
 2442                 /* Stop current transfer, if any */
 2443                 usbd_transfer_stop(sc->sc_xfer[ATP_INTR_DT]);
 2444                 /* Set new interval */
 2445                 usbd_xfer_set_interval(sc->sc_xfer[ATP_INTR_DT], 1000 / rate);
 2446                 /* Only set pollrate once */
 2447                 sc->sc_pollrate = 0;
 2448         }
 2449 
 2450         usbd_transfer_start(sc->sc_xfer[ATP_INTR_DT]);
 2451 }
 2452 
 2453 static void
 2454 atp_stop_read(struct usb_fifo *fifo)
 2455 {
 2456         struct atp_softc *sc = usb_fifo_softc(fifo);
 2457         usbd_transfer_stop(sc->sc_xfer[ATP_INTR_DT]);
 2458 }
 2459 
 2460 static int
 2461 atp_open(struct usb_fifo *fifo, int fflags)
 2462 {
 2463         struct atp_softc *sc = usb_fifo_softc(fifo);
 2464 
 2465         /* check for duplicate open, should not happen */
 2466         if (sc->sc_fflags & fflags)
 2467                 return (EBUSY);
 2468 
 2469         /* check for first open */
 2470         if (sc->sc_fflags == 0) {
 2471                 int rc;
 2472                 if ((rc = atp_enable(sc)) != 0)
 2473                         return (rc);
 2474         }
 2475 
 2476         if (fflags & FREAD) {
 2477                 if (usb_fifo_alloc_buffer(fifo,
 2478                     ATP_FIFO_BUF_SIZE, ATP_FIFO_QUEUE_MAXLEN)) {
 2479                         return (ENOMEM);
 2480                 }
 2481         }
 2482 
 2483         sc->sc_fflags |= (fflags & (FREAD | FWRITE));
 2484         return (0);
 2485 }
 2486 
 2487 static void
 2488 atp_close(struct usb_fifo *fifo, int fflags)
 2489 {
 2490         struct atp_softc *sc = usb_fifo_softc(fifo);
 2491         if (fflags & FREAD)
 2492                 usb_fifo_free_buffer(fifo);
 2493 
 2494         sc->sc_fflags &= ~(fflags & (FREAD | FWRITE));
 2495         if (sc->sc_fflags == 0) {
 2496                 atp_disable(sc);
 2497         }
 2498 }
 2499 
 2500 static int
 2501 atp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
 2502 {
 2503         struct atp_softc *sc = usb_fifo_softc(fifo);
 2504         mousemode_t mode;
 2505         int error = 0;
 2506 
 2507         mtx_lock(&sc->sc_mutex);
 2508 
 2509         switch(cmd) {
 2510         case MOUSE_GETHWINFO:
 2511                 *(mousehw_t *)addr = sc->sc_hw;
 2512                 break;
 2513         case MOUSE_GETMODE:
 2514                 *(mousemode_t *)addr = sc->sc_mode;
 2515                 break;
 2516         case MOUSE_SETMODE:
 2517                 mode = *(mousemode_t *)addr;
 2518 
 2519                 if (mode.level == -1)
 2520                         /* Don't change the current setting */
 2521                         ;
 2522                 else if ((mode.level < 0) || (mode.level > 1)) {
 2523                         error = EINVAL;
 2524                         break;
 2525                 }
 2526                 sc->sc_mode.level = mode.level;
 2527                 sc->sc_pollrate   = mode.rate;
 2528                 sc->sc_hw.buttons = 3;
 2529 
 2530                 if (sc->sc_mode.level == 0) {
 2531                         sc->sc_mode.protocol    = MOUSE_PROTO_MSC;
 2532                         sc->sc_mode.packetsize  = MOUSE_MSC_PACKETSIZE;
 2533                         sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
 2534                         sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
 2535                 } else if (sc->sc_mode.level == 1) {
 2536                         sc->sc_mode.protocol    = MOUSE_PROTO_SYSMOUSE;
 2537                         sc->sc_mode.packetsize  = MOUSE_SYS_PACKETSIZE;
 2538                         sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
 2539                         sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
 2540                 }
 2541                 atp_reset_buf(sc);
 2542                 break;
 2543         case MOUSE_GETLEVEL:
 2544                 *(int *)addr = sc->sc_mode.level;
 2545                 break;
 2546         case MOUSE_SETLEVEL:
 2547                 if ((*(int *)addr < 0) || (*(int *)addr > 1)) {
 2548                         error = EINVAL;
 2549                         break;
 2550                 }
 2551                 sc->sc_mode.level = *(int *)addr;
 2552                 sc->sc_hw.buttons = 3;
 2553 
 2554                 if (sc->sc_mode.level == 0) {
 2555                         sc->sc_mode.protocol    = MOUSE_PROTO_MSC;
 2556                         sc->sc_mode.packetsize  = MOUSE_MSC_PACKETSIZE;
 2557                         sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
 2558                         sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
 2559                 } else if (sc->sc_mode.level == 1) {
 2560                         sc->sc_mode.protocol    = MOUSE_PROTO_SYSMOUSE;
 2561                         sc->sc_mode.packetsize  = MOUSE_SYS_PACKETSIZE;
 2562                         sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
 2563                         sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
 2564                 }
 2565                 atp_reset_buf(sc);
 2566                 break;
 2567         case MOUSE_GETSTATUS: {
 2568                 mousestatus_t *status = (mousestatus_t *)addr;
 2569 
 2570                 *status = sc->sc_status;
 2571                 sc->sc_status.obutton = sc->sc_status.button;
 2572                 sc->sc_status.button  = 0;
 2573                 sc->sc_status.dx      = 0;
 2574                 sc->sc_status.dy      = 0;
 2575                 sc->sc_status.dz      = 0;
 2576 
 2577                 if (status->dx || status->dy || status->dz)
 2578                         status->flags |= MOUSE_POSCHANGED;
 2579                 if (status->button != status->obutton)
 2580                         status->flags |= MOUSE_BUTTONSCHANGED;
 2581                 break;
 2582         }
 2583 
 2584         default:
 2585                 error = ENOTTY;
 2586                 break;
 2587         }
 2588 
 2589         mtx_unlock(&sc->sc_mutex);
 2590         return (error);
 2591 }
 2592 
 2593 static int
 2594 atp_sysctl_scale_factor_handler(SYSCTL_HANDLER_ARGS)
 2595 {
 2596         int error;
 2597         u_int tmp;
 2598 
 2599         tmp = atp_mickeys_scale_factor;
 2600         error = sysctl_handle_int(oidp, &tmp, 0, req);
 2601         if (error != 0 || req->newptr == NULL)
 2602                 return (error);
 2603 
 2604         if (tmp == atp_mickeys_scale_factor)
 2605                 return (0);     /* no change */
 2606         if ((tmp == 0) || (tmp > (10 * ATP_SCALE_FACTOR)))
 2607                 return (EINVAL);
 2608 
 2609         atp_mickeys_scale_factor = tmp;
 2610         DPRINTFN(ATP_LLEVEL_INFO, "%s: resetting mickeys_scale_factor to %u\n",
 2611             ATP_DRIVER_NAME, tmp);
 2612 
 2613         return (0);
 2614 }
 2615 
 2616 static device_method_t atp_methods[] = {
 2617         DEVMETHOD(device_probe,  atp_probe),
 2618         DEVMETHOD(device_attach, atp_attach),
 2619         DEVMETHOD(device_detach, atp_detach),
 2620 
 2621         DEVMETHOD_END
 2622 };
 2623 
 2624 static driver_t atp_driver = {
 2625         .name    = ATP_DRIVER_NAME,
 2626         .methods = atp_methods,
 2627         .size    = sizeof(struct atp_softc)
 2628 };
 2629 
 2630 DRIVER_MODULE(atp, uhub, atp_driver, NULL, NULL);
 2631 MODULE_DEPEND(atp, usb, 1, 1, 1);
 2632 MODULE_DEPEND(atp, hid, 1, 1, 1);
 2633 MODULE_VERSION(atp, 1);
 2634 USB_PNP_HOST_INFO(fg_devs);
 2635 USB_PNP_HOST_INFO(wsp_devs);

Cache object: d635b8346e1d2f14a6e5c6d6d55ede50


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.