source: rtems-libbsd/freebsd/sys/dev/usb/input/atp.c @ 3e7de30

55-freebsd-126-freebsd-12
Last change on this file since 3e7de30 was 3e7de30, checked in by Kevin Kirspel <kevin-kirspel@…>, on 05/17/17 at 12:40:28

Add FREEBSD USB input device files

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