svn commit: r263067 - stable/8/sys/dev/usb/input

Hans Petter Selasky hselasky at FreeBSD.org
Wed Mar 12 08:04:09 UTC 2014


Author: hselasky
Date: Wed Mar 12 08:04:08 2014
New Revision: 263067
URL: http://svnweb.freebsd.org/changeset/base/263067

Log:
  MFC r262417, r262439, r262454, r262455 and r262478:
  - Several updates and improvements to ATP driver.
  - Start effort merging WSP and ATP driver.

Modified:
  stable/8/sys/dev/usb/input/atp.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/dev/   (props changed)
  stable/8/sys/dev/usb/   (props changed)

Modified: stable/8/sys/dev/usb/input/atp.c
==============================================================================
--- stable/8/sys/dev/usb/input/atp.c	Wed Mar 12 08:00:20 2014	(r263066)
+++ stable/8/sys/dev/usb/input/atp.c	Wed Mar 12 08:04:08 2014	(r263067)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009 Rohit Grover
+ * Copyright (c) 2014 Rohit Grover
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -24,29 +24,64 @@
  * SUCH DAMAGE.
  */
 
+/*
+ * Some tables, structures, definitions and constant values for the
+ * touchpad protocol has been copied from Linux's
+ * "drivers/input/mouse/bcm5974.c" which has the following copyright
+ * holders under GPLv2. All device specific code in this driver has
+ * been written from scratch. The decoding algorithm is based on
+ * output from FreeBSD's usbdump.
+ *
+ * Copyright (C) 2008      Henrik Rydberg (rydberg at euromail.se)
+ * Copyright (C) 2008      Scott Shawcroft (scott.shawcroft at gmail.com)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg at kroah.com)
+ * Copyright (C) 2005      Johannes Berg (johannes at sipsolutions.net)
+ * Copyright (C) 2005      Stelian Pop (stelian at popies.net)
+ * Copyright (C) 2005      Frank Arnold (frank at scirocco-5v-turbo.de)
+ * Copyright (C) 2005      Peter Osterlund (petero2 at telia.com)
+ * Copyright (C) 2005      Michael Hanselmann (linux-kernel at hansmi.ch)
+ * Copyright (C) 2006      Nicolas Boichat (nicolas at boichat.ch)
+ */
+
+/*
+ * Author's note: 'atp' supports two distinct families of Apple trackpad
+ * products: the older Fountain/Geyser and the latest Wellspring trackpads.
+ * The first version made its appearance with FreeBSD 8 and worked only with
+ * the Fountain/Geyser hardware. A fork of this driver for Wellspring was
+ * contributed by Huang Wen Hui. This driver unifies the Wellspring effort
+ * and also improves upon the original work.
+ *
+ * I'm grateful to Stephan Scheunig, Angela Naegele, and Nokia IT-support
+ * for helping me with access to hardware. Thanks also go to Nokia for
+ * giving me an opportunity to do this work.
+ */
+
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/stdint.h>
+#include <sys/stddef.h>
 #include <sys/param.h>
+#include <sys/types.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
-#include <sys/malloc.h>
+#include <sys/bus.h>
 #include <sys/module.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
-#include <sys/bus.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
 #include <sys/conf.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
 #include <sys/selinfo.h>
 #include <sys/poll.h>
-#include <sys/sysctl.h>
-#include <sys/uio.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
 #include <dev/usb/usbhid.h>
+
 #include "usbdevs.h"
 
 #define USB_DEBUG_VAR atp_debug
@@ -54,6 +89,14 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/mouse.h>
 
+#ifndef true
+#define	true 1
+#endif
+
+#ifndef false
+#define	false 0
+#endif
+
 #define ATP_DRIVER_NAME "atp"
 
 /*
@@ -61,17 +104,35 @@ __FBSDID("$FreeBSD$");
  * `options' statements in the kernel configuration file.
  */
 
-/* The multiplier used to translate sensor reported positions to mickeys. */
+/* The divisor used to translate sensor reported positions to mickeys. */
 #ifndef ATP_SCALE_FACTOR
-#define ATP_SCALE_FACTOR 48
+#define ATP_SCALE_FACTOR                  16
+#endif
+
+/* Threshold for small movement noise (in mickeys) */
+#ifndef ATP_SMALL_MOVEMENT_THRESHOLD
+#define ATP_SMALL_MOVEMENT_THRESHOLD      30
+#endif
+
+/* Threshold of instantaneous deltas beyond which movement is considered fast.*/
+#ifndef ATP_FAST_MOVEMENT_TRESHOLD
+#define ATP_FAST_MOVEMENT_TRESHOLD        150
 #endif
 
 /*
- * This is the age (in microseconds) beyond which a touch is
- * considered to be a slide; and therefore a tap event isn't registered.
+ * This is the age in microseconds beyond which a touch is considered
+ * to be a slide; and therefore a tap event isn't registered.
  */
 #ifndef ATP_TOUCH_TIMEOUT
-#define ATP_TOUCH_TIMEOUT 125000
+#define ATP_TOUCH_TIMEOUT                 125000
+#endif
+
+#ifndef ATP_IDLENESS_THRESHOLD
+#define	ATP_IDLENESS_THRESHOLD 10
+#endif
+
+#ifndef FG_SENSOR_NOISE_THRESHOLD
+#define FG_SENSOR_NOISE_THRESHOLD 2
 #endif
 
 /*
@@ -82,39 +143,40 @@ __FBSDID("$FreeBSD$");
  * tap events preceding the slide for such a gesture.
  */
 #ifndef ATP_DOUBLE_TAP_N_DRAG_THRESHOLD
-#define ATP_DOUBLE_TAP_N_DRAG_THRESHOLD 200000
+#define ATP_DOUBLE_TAP_N_DRAG_THRESHOLD   200000
 #endif
 
 /*
- * The device provides us only with pressure readings from an array of
- * X and Y sensors; for our algorithms, we need to interpret groups
- * (typically pairs) of X and Y readings as being related to a single
- * finger stroke. We can relate X and Y readings based on their times
- * of incidence. The coincidence window should be at least 10000us
- * since it is used against values from getmicrotime(), which has a
- * precision of around 10ms.
- */
-#ifndef ATP_COINCIDENCE_THRESHOLD
-#define ATP_COINCIDENCE_THRESHOLD  40000 /* unit: microseconds */
-#if ATP_COINCIDENCE_THRESHOLD > 100000
-#error "ATP_COINCIDENCE_THRESHOLD too large"
-#endif
-#endif /* #ifndef ATP_COINCIDENCE_THRESHOLD */
+ * The wait duration in ticks after losing a touch contact before
+ * zombied strokes are reaped and turned into button events.
+ */
+#define ATP_ZOMBIE_STROKE_REAP_INTERVAL   (hz / 20)	/* 50 ms */
+
+/* The multiplier used to translate sensor reported positions to mickeys. */
+#define FG_SCALE_FACTOR                   380
 
 /*
- * The wait duration (in microseconds) after losing a touch contact
- * before zombied strokes are reaped and turned into button events.
+ * The movement threshold for a stroke; this is the maximum difference
+ * in position which will be resolved as a continuation of a stroke
+ * component.
  */
-#define ATP_ZOMBIE_STROKE_REAP_WINDOW   50000
-#if ATP_ZOMBIE_STROKE_REAP_WINDOW > 100000
-#error "ATP_ZOMBIE_STROKE_REAP_WINDOW too large"
+#define FG_MAX_DELTA_MICKEYS             ((3 * (FG_SCALE_FACTOR)) >> 1)
+
+/* Distance-squared threshold for matching a finger with a known stroke */
+#ifndef WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ
+#define WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ 1000000
 #endif
 
-/* end of driver specific options */
+/* Ignore pressure spans with cumulative press. below this value. */
+#define FG_PSPAN_MIN_CUM_PRESSURE         10
+
+/* Maximum allowed width for pressure-spans.*/
+#define FG_PSPAN_MAX_WIDTH                4
 
+/* end of driver specific options */
 
 /* Tunables */
-SYSCTL_NODE(_hw_usb, OID_AUTO, atp, CTLFLAG_RW, 0, "USB atp");
+static SYSCTL_NODE(_hw_usb, OID_AUTO, atp, CTLFLAG_RW, 0, "USB ATP");
 
 #ifdef USB_DEBUG
 enum atp_log_level {
@@ -129,13 +191,14 @@ SYSCTL_INT(_hw_usb_atp, OID_AUTO, debug,
 #endif /* USB_DEBUG */
 
 static u_int atp_touch_timeout = ATP_TOUCH_TIMEOUT;
-SYSCTL_INT(_hw_usb_atp, OID_AUTO, touch_timeout, CTLFLAG_RW, &atp_touch_timeout,
-    125000, "age threshold (in micros) for a touch");
+SYSCTL_UINT(_hw_usb_atp, OID_AUTO, touch_timeout, CTLFLAG_RW,
+    &atp_touch_timeout, 125000, "age threshold in microseconds for a touch");
 
 static u_int atp_double_tap_threshold = ATP_DOUBLE_TAP_N_DRAG_THRESHOLD;
-SYSCTL_INT(_hw_usb_atp, OID_AUTO, double_tap_threshold, CTLFLAG_RW,
+SYSCTL_UINT(_hw_usb_atp, OID_AUTO, double_tap_threshold, CTLFLAG_RW,
     &atp_double_tap_threshold, ATP_DOUBLE_TAP_N_DRAG_THRESHOLD,
-    "maximum time (in micros) between a double-tap");
+    "maximum time in microseconds to allow association between a double-tap and "
+    "drag gesture");
 
 static u_int atp_mickeys_scale_factor = ATP_SCALE_FACTOR;
 static int atp_sysctl_scale_factor_handler(SYSCTL_HANDLER_ARGS);
@@ -143,264 +206,539 @@ SYSCTL_PROC(_hw_usb_atp, OID_AUTO, scale
     &atp_mickeys_scale_factor, sizeof(atp_mickeys_scale_factor),
     atp_sysctl_scale_factor_handler, "IU", "movement scale factor");
 
-static u_int atp_small_movement_threshold = ATP_SCALE_FACTOR >> 3;
+static u_int atp_small_movement_threshold = ATP_SMALL_MOVEMENT_THRESHOLD;
 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, small_movement, CTLFLAG_RW,
-    &atp_small_movement_threshold, ATP_SCALE_FACTOR >> 3,
+    &atp_small_movement_threshold, ATP_SMALL_MOVEMENT_THRESHOLD,
     "the small movement black-hole for filtering noise");
-/*
- * The movement threshold for a stroke; this is the maximum difference
- * in position which will be resolved as a continuation of a stroke
- * component.
- */
-static u_int atp_max_delta_mickeys = ((3 * ATP_SCALE_FACTOR) >> 1);
-SYSCTL_UINT(_hw_usb_atp, OID_AUTO, max_delta_mickeys, CTLFLAG_RW,
-    &atp_max_delta_mickeys, ((3 * ATP_SCALE_FACTOR) >> 1),
-    "max. mickeys-delta which will match against an existing stroke");
+
+static u_int atp_tap_minimum = 1;
+SYSCTL_UINT(_hw_usb_atp, OID_AUTO, tap_minimum, CTLFLAG_RW,
+    &atp_tap_minimum, 1, "Minimum number of taps before detection");
+
 /*
  * Strokes which accumulate at least this amount of absolute movement
  * from the aggregate of their components are considered as
  * slides. Unit: mickeys.
  */
-static u_int atp_slide_min_movement = (ATP_SCALE_FACTOR >> 3);
+static u_int atp_slide_min_movement = 2 * ATP_SMALL_MOVEMENT_THRESHOLD;
 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, slide_min_movement, CTLFLAG_RW,
-    &atp_slide_min_movement, (ATP_SCALE_FACTOR >> 3),
+    &atp_slide_min_movement, 2 * ATP_SMALL_MOVEMENT_THRESHOLD,
     "strokes with at least this amt. of movement are considered slides");
 
 /*
  * The minimum age of a stroke for it to be considered mature; this
  * helps filter movements (noise) from immature strokes. Units: interrupts.
  */
-static u_int atp_stroke_maturity_threshold = 2;
+static u_int atp_stroke_maturity_threshold = 4;
 SYSCTL_UINT(_hw_usb_atp, OID_AUTO, stroke_maturity_threshold, CTLFLAG_RW,
-    &atp_stroke_maturity_threshold, 2,
+    &atp_stroke_maturity_threshold, 4,
     "the minimum age of a stroke for it to be considered mature");
 
-/* Accept pressure readings from sensors only if above this value. */
-static u_int atp_sensor_noise_threshold = 2;
-SYSCTL_UINT(_hw_usb_atp, OID_AUTO, sensor_noise_threshold, CTLFLAG_RW,
-    &atp_sensor_noise_threshold, 2,
-    "accept pressure readings from sensors only if above this value");
+typedef enum atp_trackpad_family {
+	TRACKPAD_FAMILY_FOUNTAIN_GEYSER,
+	TRACKPAD_FAMILY_WELLSPRING,
+	TRACKPAD_FAMILY_MAX /* keep this at the tail end of the enumeration */
+} trackpad_family_t;
+
+enum fountain_geyser_product {
+	FOUNTAIN,
+	GEYSER1,
+	GEYSER1_17inch,
+	GEYSER2,
+	GEYSER3,
+	GEYSER4,
+	FOUNTAIN_GEYSER_PRODUCT_MAX /* keep this at the end */
+};
 
-/* Ignore pressure spans with cumulative press. below this value. */
-static u_int atp_pspan_min_cum_pressure = 10;
-SYSCTL_UINT(_hw_usb_atp, OID_AUTO, pspan_min_cum_pressure, CTLFLAG_RW,
-    &atp_pspan_min_cum_pressure, 10,
-    "ignore pressure spans with cumulative press. below this value");
+enum wellspring_product {
+	WELLSPRING1,
+	WELLSPRING2,
+	WELLSPRING3,
+	WELLSPRING4,
+	WELLSPRING4A,
+	WELLSPRING5,
+	WELLSPRING6A,
+	WELLSPRING6,
+	WELLSPRING5A,
+	WELLSPRING7,
+	WELLSPRING7A,
+	WELLSPRING8,
+	WELLSPRING_PRODUCT_MAX /* keep this at the end of the enumeration */
+};
 
-/* Maximum allowed width for pressure-spans.*/
-static u_int atp_pspan_max_width = 4;
-SYSCTL_UINT(_hw_usb_atp, OID_AUTO, pspan_max_width, CTLFLAG_RW,
-    &atp_pspan_max_width, 4,
-    "maximum allowed width (in sensors) for pressure-spans");
-
-/* We support three payload protocols */
-typedef enum {
-	ATP_PROT_GEYSER1,
-	ATP_PROT_GEYSER2,
-	ATP_PROT_GEYSER3,
-} atp_protocol;
+/* trackpad header types */
+enum fountain_geyser_trackpad_type {
+	FG_TRACKPAD_TYPE_GEYSER1,
+	FG_TRACKPAD_TYPE_GEYSER2,
+	FG_TRACKPAD_TYPE_GEYSER3,
+	FG_TRACKPAD_TYPE_GEYSER4,
+};
+enum wellspring_trackpad_type {
+	WSP_TRACKPAD_TYPE1,      /* plain trackpad */
+	WSP_TRACKPAD_TYPE2,      /* button integrated in trackpad */
+	WSP_TRACKPAD_TYPE3       /* additional header fields since June 2013 */
+};
 
-/* Define the various flavours of devices supported by this driver. */
-enum {
-	ATP_DEV_PARAMS_0,
-	ATP_DEV_PARAMS_PBOOK,
-	ATP_DEV_PARAMS_PBOOK_15A,
-	ATP_DEV_PARAMS_PBOOK_17,
-	ATP_N_DEV_PARAMS
+/*
+ * Trackpad family and product and family are encoded together in the
+ * driver_info value associated with a trackpad product.
+ */
+#define N_PROD_BITS 8  /* Number of bits used to encode product */
+#define ENCODE_DRIVER_INFO(FAMILY, PROD)      \
+    (((FAMILY) << N_PROD_BITS) | (PROD))
+#define DECODE_FAMILY_FROM_DRIVER_INFO(INFO)  ((INFO) >> N_PROD_BITS)
+#define DECODE_PRODUCT_FROM_DRIVER_INFO(INFO) \
+    ((INFO) & ((1 << N_PROD_BITS) - 1))
+
+#define FG_DRIVER_INFO(PRODUCT)               \
+    ENCODE_DRIVER_INFO(TRACKPAD_FAMILY_FOUNTAIN_GEYSER, PRODUCT)
+#define WELLSPRING_DRIVER_INFO(PRODUCT)       \
+    ENCODE_DRIVER_INFO(TRACKPAD_FAMILY_WELLSPRING, PRODUCT)
+
+/*
+ * The following structure captures the state of a pressure span along
+ * an axis. Each contact with the touchpad results in separate
+ * pressure spans along the two axes.
+ */
+typedef struct fg_pspan {
+	u_int width;       /* in units of sensors */
+	u_int cum;         /* cumulative compression (from all sensors) */
+	u_int cog;         /* center of gravity */
+	u_int loc;         /* location (scaled using the mickeys factor) */
+	boolean_t matched; /* to track pspans as they match against strokes. */
+} fg_pspan;
+
+#define FG_MAX_PSPANS_PER_AXIS 3
+#define FG_MAX_STROKES         (2 * FG_MAX_PSPANS_PER_AXIS)
+
+#define WELLSPRING_INTERFACE_INDEX 1
+
+/* trackpad finger data offsets, le16-aligned */
+#define WSP_TYPE1_FINGER_DATA_OFFSET  (13 * 2)
+#define WSP_TYPE2_FINGER_DATA_OFFSET  (15 * 2)
+#define WSP_TYPE3_FINGER_DATA_OFFSET  (19 * 2)
+
+/* trackpad button data offsets */
+#define WSP_TYPE2_BUTTON_DATA_OFFSET   15
+#define WSP_TYPE3_BUTTON_DATA_OFFSET   23
+
+/* list of device capability bits */
+#define HAS_INTEGRATED_BUTTON   1
+
+/* trackpad finger structure - little endian */
+struct wsp_finger_sensor_data {
+	int16_t origin;       /* zero when switching track finger */
+	int16_t abs_x;        /* absolute x coordinate */
+	int16_t abs_y;        /* absolute y coordinate */
+	int16_t rel_x;        /* relative x coordinate */
+	int16_t rel_y;        /* relative y coordinate */
+	int16_t tool_major;   /* tool area, major axis */
+	int16_t tool_minor;   /* tool area, minor axis */
+	int16_t orientation;  /* 16384 when point, else 15 bit angle */
+	int16_t touch_major;  /* touch area, major axis */
+	int16_t touch_minor;  /* touch area, minor axis */
+	int16_t unused[3];    /* zeros */
+	int16_t multi;        /* one finger: varies, more fingers: constant */
+} __packed;
+
+typedef struct wsp_finger {
+	/* to track fingers as they match against strokes. */
+	boolean_t matched;
+
+	/* location (scaled using the mickeys factor) */
+	int x;
+	int y;
+} wsp_finger_t;
+
+#define WSP_MAX_FINGERS               16
+#define WSP_SIZEOF_FINGER_SENSOR_DATA sizeof(struct wsp_finger_sensor_data)
+#define WSP_SIZEOF_ALL_FINGER_DATA    (WSP_MAX_FINGERS * \
+				       WSP_SIZEOF_FINGER_SENSOR_DATA)
+#define WSP_MAX_FINGER_ORIENTATION    16384
+
+#define ATP_SENSOR_DATA_BUF_MAX       1024
+#if (ATP_SENSOR_DATA_BUF_MAX < ((WSP_MAX_FINGERS * 14 * 2) + \
+				WSP_TYPE3_FINGER_DATA_OFFSET))
+/* note: 14 * 2 in the above is based on sizeof(struct wsp_finger_sensor_data)*/
+#error "ATP_SENSOR_DATA_BUF_MAX is too small"
+#endif
+
+#define ATP_MAX_STROKES               MAX(WSP_MAX_FINGERS, FG_MAX_STROKES)
+
+#define FG_MAX_XSENSORS 26
+#define FG_MAX_YSENSORS 16
+
+/* device-specific configuration */
+struct fg_dev_params {
+	u_int                              data_len;   /* for sensor data */
+	u_int                              n_xsensors;
+	u_int                              n_ysensors;
+	enum fountain_geyser_trackpad_type prot;
 };
-struct atp_dev_params {
-	u_int            data_len;   /* for sensor data */
-	u_int            n_xsensors;
-	u_int            n_ysensors;
-	atp_protocol     prot;
-} atp_dev_params[ATP_N_DEV_PARAMS] = {
-	[ATP_DEV_PARAMS_0] = {
-		.data_len   = 64,
-		.n_xsensors = 20,
-		.n_ysensors = 10,
-		.prot       = ATP_PROT_GEYSER3
+struct wsp_dev_params {
+	uint8_t  caps;               /* device capability bitmask */
+	uint8_t  tp_type;            /* type of trackpad interface */
+	uint8_t  finger_data_offset; /* offset to trackpad finger data */
+};
+
+static const struct fg_dev_params fg_dev_params[FOUNTAIN_GEYSER_PRODUCT_MAX] = {
+	[FOUNTAIN] = {
+		.data_len   = 81,
+		.n_xsensors = 16,
+		.n_ysensors = 16,
+		.prot       = FG_TRACKPAD_TYPE_GEYSER1
 	},
-	[ATP_DEV_PARAMS_PBOOK] = {
+	[GEYSER1] = {
 		.data_len   = 81,
 		.n_xsensors = 16,
 		.n_ysensors = 16,
-		.prot       = ATP_PROT_GEYSER1
+		.prot       = FG_TRACKPAD_TYPE_GEYSER1
 	},
-	[ATP_DEV_PARAMS_PBOOK_15A] = {
+	[GEYSER1_17inch] = {
+		.data_len   = 81,
+		.n_xsensors = 26,
+		.n_ysensors = 16,
+		.prot       = FG_TRACKPAD_TYPE_GEYSER1
+	},
+	[GEYSER2] = {
 		.data_len   = 64,
 		.n_xsensors = 15,
 		.n_ysensors = 9,
-		.prot       = ATP_PROT_GEYSER2
+		.prot       = FG_TRACKPAD_TYPE_GEYSER2
 	},
-	[ATP_DEV_PARAMS_PBOOK_17] = {
-		.data_len   = 81,
-		.n_xsensors = 26,
-		.n_ysensors = 16,
-		.prot       = ATP_PROT_GEYSER1
+	[GEYSER3] = {
+		.data_len   = 64,
+		.n_xsensors = 20,
+		.n_ysensors = 10,
+		.prot       = FG_TRACKPAD_TYPE_GEYSER3
 	},
+	[GEYSER4] = {
+		.data_len   = 64,
+		.n_xsensors = 20,
+		.n_ysensors = 10,
+		.prot       = FG_TRACKPAD_TYPE_GEYSER4
+	}
 };
 
-static const STRUCT_USB_HOST_ID atp_devs[] = {
+static const STRUCT_USB_HOST_ID fg_devs[] = {
+	/* PowerBooks Feb 2005, iBooks G4 */
+	{ USB_VPI(USB_VENDOR_APPLE, 0x020e, FG_DRIVER_INFO(FOUNTAIN)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x020f, FG_DRIVER_INFO(FOUNTAIN)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x0210, FG_DRIVER_INFO(FOUNTAIN)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x030a, FG_DRIVER_INFO(FOUNTAIN)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x030b, FG_DRIVER_INFO(GEYSER1)) },
+
+	/* PowerBooks Oct 2005 */
+	{ USB_VPI(USB_VENDOR_APPLE, 0x0214, FG_DRIVER_INFO(GEYSER2)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x0215, FG_DRIVER_INFO(GEYSER2)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x0216, FG_DRIVER_INFO(GEYSER2)) },
+
 	/* Core Duo MacBook & MacBook Pro */
-	{ USB_VPI(USB_VENDOR_APPLE, 0x0217, ATP_DEV_PARAMS_0) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x0218, ATP_DEV_PARAMS_0) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x0219, ATP_DEV_PARAMS_0) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x0217, FG_DRIVER_INFO(GEYSER3)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x0218, FG_DRIVER_INFO(GEYSER3)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x0219, FG_DRIVER_INFO(GEYSER3)) },
 
 	/* Core2 Duo MacBook & MacBook Pro */
-	{ USB_VPI(USB_VENDOR_APPLE, 0x021a, ATP_DEV_PARAMS_0) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x021b, ATP_DEV_PARAMS_0) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x021c, ATP_DEV_PARAMS_0) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x021a, FG_DRIVER_INFO(GEYSER4)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x021b, FG_DRIVER_INFO(GEYSER4)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x021c, FG_DRIVER_INFO(GEYSER4)) },
 
 	/* Core2 Duo MacBook3,1 */
-	{ USB_VPI(USB_VENDOR_APPLE, 0x0229, ATP_DEV_PARAMS_0) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x022a, ATP_DEV_PARAMS_0) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x022b, ATP_DEV_PARAMS_0) },
-
-	/* 12 inch PowerBook and iBook */
-	{ USB_VPI(USB_VENDOR_APPLE, 0x030a, ATP_DEV_PARAMS_PBOOK) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x030b, ATP_DEV_PARAMS_PBOOK) },
-
-	/* 15 inch PowerBook */
-	{ USB_VPI(USB_VENDOR_APPLE, 0x020e, ATP_DEV_PARAMS_PBOOK) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x020f, ATP_DEV_PARAMS_PBOOK) },
-	{ USB_VPI(USB_VENDOR_APPLE, 0x0215, ATP_DEV_PARAMS_PBOOK_15A) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x0229, FG_DRIVER_INFO(GEYSER4)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x022a, FG_DRIVER_INFO(GEYSER4)) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x022b, FG_DRIVER_INFO(GEYSER4)) },
 
 	/* 17 inch PowerBook */
-	{ USB_VPI(USB_VENDOR_APPLE, 0x020d, ATP_DEV_PARAMS_PBOOK_17) },
+	{ USB_VPI(USB_VENDOR_APPLE, 0x020d, FG_DRIVER_INFO(GEYSER1_17inch)) },
+};
 
+static const struct wsp_dev_params wsp_dev_params[WELLSPRING_PRODUCT_MAX] = {
+	[WELLSPRING1] = {
+		.caps       = 0,
+		.tp_type    = WSP_TRACKPAD_TYPE1,
+		.finger_data_offset  = WSP_TYPE1_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING2] = {
+		.caps       = 0,
+		.tp_type    = WSP_TRACKPAD_TYPE1,
+		.finger_data_offset  = WSP_TYPE1_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING3] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING4] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING4A] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING5] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING6] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING5A] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING6A] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING7] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING7A] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE2,
+		.finger_data_offset  = WSP_TYPE2_FINGER_DATA_OFFSET,
+	},
+	[WELLSPRING8] = {
+		.caps       = HAS_INTEGRATED_BUTTON,
+		.tp_type    = WSP_TRACKPAD_TYPE3,
+		.finger_data_offset  = WSP_TYPE3_FINGER_DATA_OFFSET,
+	},
 };
 
-/*
- * The following structure captures the state of a pressure span along
- * an axis. Each contact with the touchpad results in separate
- * pressure spans along the two axes.
- */
-typedef struct atp_pspan {
-	u_int width;   /* in units of sensors */
-	u_int cum;     /* cumulative compression (from all sensors) */
-	u_int cog;     /* center of gravity */
-	u_int loc;     /* location (scaled using the mickeys factor) */
-	boolean_t matched; /* to track pspans as they match against strokes. */
-} atp_pspan;
+#define ATP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
+
+/* TODO: STRUCT_USB_HOST_ID */
+static const struct usb_device_id wsp_devs[] = {
+	/* MacbookAir1.1 */
+	ATP_DEV(APPLE, WELLSPRING_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING1)),
+	ATP_DEV(APPLE, WELLSPRING_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING1)),
+	ATP_DEV(APPLE, WELLSPRING_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING1)),
+
+	/* MacbookProPenryn, aka wellspring2 */
+	ATP_DEV(APPLE, WELLSPRING2_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING2)),
+	ATP_DEV(APPLE, WELLSPRING2_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING2)),
+	ATP_DEV(APPLE, WELLSPRING2_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING2)),
+
+	/* Macbook5,1 (unibody), aka wellspring3 */
+	ATP_DEV(APPLE, WELLSPRING3_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING3)),
+	ATP_DEV(APPLE, WELLSPRING3_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING3)),
+	ATP_DEV(APPLE, WELLSPRING3_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING3)),
+
+	/* MacbookAir3,2 (unibody), aka wellspring4 */
+	ATP_DEV(APPLE, WELLSPRING4_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING4)),
+	ATP_DEV(APPLE, WELLSPRING4_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING4)),
+	ATP_DEV(APPLE, WELLSPRING4_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING4)),
+
+	/* MacbookAir3,1 (unibody), aka wellspring4 */
+	ATP_DEV(APPLE, WELLSPRING4A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING4A)),
+	ATP_DEV(APPLE, WELLSPRING4A_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING4A)),
+	ATP_DEV(APPLE, WELLSPRING4A_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING4A)),
+
+	/* Macbook8 (unibody, March 2011) */
+	ATP_DEV(APPLE, WELLSPRING5_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING5)),
+	ATP_DEV(APPLE, WELLSPRING5_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING5)),
+	ATP_DEV(APPLE, WELLSPRING5_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING5)),
+
+	/* MacbookAir4,1 (unibody, July 2011) */
+	ATP_DEV(APPLE, WELLSPRING6A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING6A)),
+	ATP_DEV(APPLE, WELLSPRING6A_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING6A)),
+	ATP_DEV(APPLE, WELLSPRING6A_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING6A)),
+
+	/* MacbookAir4,2 (unibody, July 2011) */
+	ATP_DEV(APPLE, WELLSPRING6_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING6)),
+	ATP_DEV(APPLE, WELLSPRING6_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING6)),
+	ATP_DEV(APPLE, WELLSPRING6_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING6)),
+
+	/* Macbook8,2 (unibody) */
+	ATP_DEV(APPLE, WELLSPRING5A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING5A)),
+	ATP_DEV(APPLE, WELLSPRING5A_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING5A)),
+	ATP_DEV(APPLE, WELLSPRING5A_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING5A)),
+
+	/* MacbookPro10,1 (unibody, June 2012) */
+	/* MacbookPro11,? (unibody, June 2013) */
+	ATP_DEV(APPLE, WELLSPRING7_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING7)),
+	ATP_DEV(APPLE, WELLSPRING7_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING7)),
+	ATP_DEV(APPLE, WELLSPRING7_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING7)),
+
+	/* MacbookPro10,2 (unibody, October 2012) */
+	ATP_DEV(APPLE, WELLSPRING7A_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING7A)),
+	ATP_DEV(APPLE, WELLSPRING7A_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING7A)),
+	ATP_DEV(APPLE, WELLSPRING7A_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING7A)),
+
+	/* MacbookAir6,2 (unibody, June 2013) */
+	ATP_DEV(APPLE, WELLSPRING8_ANSI, WELLSPRING_DRIVER_INFO(WELLSPRING8)),
+	ATP_DEV(APPLE, WELLSPRING8_ISO,  WELLSPRING_DRIVER_INFO(WELLSPRING8)),
+	ATP_DEV(APPLE, WELLSPRING8_JIS,  WELLSPRING_DRIVER_INFO(WELLSPRING8)),
+};
 
 typedef enum atp_stroke_type {
 	ATP_STROKE_TOUCH,
 	ATP_STROKE_SLIDE,
 } atp_stroke_type;
 
-#define ATP_MAX_PSPANS_PER_AXIS 3
+typedef enum atp_axis {
+	X = 0,
+	Y = 1,
+	NUM_AXES
+} atp_axis;
 
-typedef struct atp_stroke_component {
+#define ATP_FIFO_BUF_SIZE        8 /* bytes */
+#define ATP_FIFO_QUEUE_MAXLEN   50 /* units */
+
+enum {
+	ATP_INTR_DT,
+	ATP_RESET,
+	ATP_N_TRANSFER,
+};
+
+typedef struct fg_stroke_component {
 	/* Fields encapsulating the pressure-span. */
 	u_int loc;              /* location (scaled) */
 	u_int cum_pressure;     /* cumulative compression */
 	u_int max_cum_pressure; /* max cumulative compression */
 	boolean_t matched; /*to track components as they match against pspans.*/
 
-	/* Fields containing information about movement. */
 	int   delta_mickeys;    /* change in location (un-smoothened movement)*/
-	int   pending;          /* cum. of pending short movements */
-	int   movement;         /* current smoothened movement */
-} atp_stroke_component;
-
-typedef enum atp_axis {
-	X = 0,
-	Y = 1
-} atp_axis;
-
-#define ATP_MAX_STROKES         (2 * ATP_MAX_PSPANS_PER_AXIS)
+} fg_stroke_component_t;
 
 /*
  * The following structure captures a finger contact with the
  * touchpad. A stroke comprises two p-span components and some state.
  */
 typedef struct atp_stroke {
-	atp_stroke_type      type;
-	struct timeval       ctime; /* create time; for coincident siblings. */
-	u_int                age;   /*
-				     * Unit: interrupts; we maintain
-				     * this value in addition to
-				     * 'ctime' in order to avoid the
-				     * expensive call to microtime()
-				     * at every interrupt.
-				     */
-
-	atp_stroke_component components[2];
-	u_int                velocity_squared; /*
-						* Average magnitude (squared)
-						* of recent velocity.
-						*/
-	u_int                cum_movement; /* cum. absolute movement so far */
-
-	uint32_t             flags;  /* the state of this stroke */
-#define ATSF_ZOMBIE          0x1
-} atp_stroke;
+	TAILQ_ENTRY(atp_stroke) entry;
 
-#define ATP_FIFO_BUF_SIZE        8 /* bytes */
-#define ATP_FIFO_QUEUE_MAXLEN   50 /* units */
+	atp_stroke_type type;
+	uint32_t        flags; /* the state of this stroke */
+#define ATSF_ZOMBIE 0x1
+	boolean_t       matched;          /* to track match against fingers.*/
 
-enum {
-	ATP_INTR_DT,
-	ATP_RESET,
-	ATP_N_TRANSFER,
-};
+	struct timeval  ctime; /* create time; for coincident siblings. */
+
+	/*
+	 * Unit: interrupts; we maintain this value in
+	 * addition to 'ctime' in order to avoid the
+	 * expensive call to microtime() at every
+	 * interrupt.
+	 */
+	uint32_t age;
+
+	/* Location */
+	int x;
+	int y;
+
+	/* Fields containing information about movement. */
+	int   instantaneous_dx; /* curr. change in X location (un-smoothened) */
+	int   instantaneous_dy; /* curr. change in Y location (un-smoothened) */
+	int   pending_dx;       /* cum. of pending short movements */
+	int   pending_dy;       /* cum. of pending short movements */
+	int   movement_dx;      /* interpreted smoothened movement */
+	int   movement_dy;      /* interpreted smoothened movement */
+	int   cum_movement_x;   /* cum. horizontal movement */
+	int   cum_movement_y;   /* cum. vertical movement */
+
+	/*
+	 * The following member is relevant only for fountain-geyser trackpads.
+	 * For these, there is the need to track pressure-spans and cumulative
+	 * pressures for stroke components.
+	 */
+	fg_stroke_component_t components[NUM_AXES];
+} atp_stroke_t;
+
+struct atp_softc; /* forward declaration */
+typedef void (*sensor_data_interpreter_t)(struct atp_softc *sc, u_int len);
 
 struct atp_softc {
-	device_t               sc_dev;
-	struct usb_device     *sc_usb_device;
-#define MODE_LENGTH 8
-	char                   sc_mode_bytes[MODE_LENGTH]; /* device mode */
-	struct mtx             sc_mutex; /* for synchronization */
-	struct usb_xfer       *sc_xfer[ATP_N_TRANSFER];
-	struct usb_fifo_sc     sc_fifo;
-
-	struct atp_dev_params *sc_params;
-
-	mousehw_t              sc_hw;
-	mousemode_t            sc_mode;
-	u_int                  sc_pollrate;
-	mousestatus_t          sc_status;
-	u_int                  sc_state;
-#define ATP_ENABLED            0x01
-#define ATP_ZOMBIES_EXIST      0x02
-#define ATP_DOUBLE_TAP_DRAG    0x04
-#define ATP_VALID              0x08
-
-	u_int                  sc_left_margin;
-	u_int                  sc_right_margin;
-
-	atp_stroke             sc_strokes[ATP_MAX_STROKES];
-	u_int                  sc_n_strokes;
-
-	int8_t                *sensor_data; /* from interrupt packet */
-	int                   *base_x;      /* base sensor readings */
-	int                   *base_y;
-	int                   *cur_x;       /* current sensor readings */
-	int                   *cur_y;
-	int                   *pressure_x;  /* computed pressures */
-	int                   *pressure_y;
+	device_t            sc_dev;
+	struct usb_device  *sc_usb_device;
+	struct mtx          sc_mutex; /* for synchronization */
+	struct usb_fifo_sc  sc_fifo;
+
+#define	MODE_LENGTH 8
+	char                sc_mode_bytes[MODE_LENGTH]; /* device mode */
+
+	trackpad_family_t   sc_family;
+	const void         *sc_params; /* device configuration */
+	sensor_data_interpreter_t sensor_data_interpreter;
+
+	mousehw_t           sc_hw;
+	mousemode_t         sc_mode;
+	mousestatus_t       sc_status;
+
+	u_int               sc_state;
+#define ATP_ENABLED          0x01
+#define ATP_ZOMBIES_EXIST    0x02
+#define ATP_DOUBLE_TAP_DRAG  0x04
+#define ATP_VALID            0x08
+
+	struct usb_xfer    *sc_xfer[ATP_N_TRANSFER];
+
+	u_int               sc_pollrate;
+	int                 sc_fflags;
+
+	atp_stroke_t        sc_strokes_data[ATP_MAX_STROKES];
+	TAILQ_HEAD(,atp_stroke) sc_stroke_free;
+	TAILQ_HEAD(,atp_stroke) sc_stroke_used;
+	u_int               sc_n_strokes;
 
-	u_int                  sc_idlecount; /* preceding idle interrupts */
-#define ATP_IDLENESS_THRESHOLD 10
+	struct callout	    sc_callout;
 
-	struct timeval         sc_reap_time;
-	struct timeval         sc_reap_ctime; /*ctime of siblings to be reaped*/
+	/*
+	 * button status. Set to non-zero if the mouse-button is physically
+	 * pressed. This state variable is exposed through softc to allow
+	 * reap_sibling_zombies to avoid registering taps while the trackpad
+	 * button is pressed.
+         */
+	uint8_t             sc_ibtn;
+
+	/*
+	 * Time when touch zombies were last reaped; useful for detecting
+	 * double-touch-n-drag.
+	 */
+	struct timeval      sc_touch_reap_time;
+
+	u_int	            sc_idlecount;
+
+	/* Regarding the data transferred from t-pad in USB INTR packets. */
+	u_int   sc_expected_sensor_data_len;
+	uint8_t sc_sensor_data[ATP_SENSOR_DATA_BUF_MAX] __aligned(4);
+
+	int      sc_cur_x[FG_MAX_XSENSORS];      /* current sensor readings */
+	int      sc_cur_y[FG_MAX_YSENSORS];
+	int      sc_base_x[FG_MAX_XSENSORS];     /* base sensor readings */
+	int      sc_base_y[FG_MAX_YSENSORS];
+	int      sc_pressure_x[FG_MAX_XSENSORS]; /* computed pressures */
+	int      sc_pressure_y[FG_MAX_YSENSORS];
+	fg_pspan sc_pspans_x[FG_MAX_PSPANS_PER_AXIS];
+	fg_pspan sc_pspans_y[FG_MAX_PSPANS_PER_AXIS];
 };
 
 /*
- * The last byte of the sensor data contains status bits; the
+ * The last byte of the fountain-geyser sensor data contains status bits; the
  * following values define the meanings of these bits.
+ * (only Geyser 3/4)
  */
-enum atp_status_bits {
-	ATP_STATUS_BUTTON      = (uint8_t)0x01, /* The button was pressed */
-	ATP_STATUS_BASE_UPDATE = (uint8_t)0x04, /* Data from an untouched pad.*/
+enum geyser34_status_bits {
+	FG_STATUS_BUTTON      = (uint8_t)0x01, /* The button was pressed */
+	FG_STATUS_BASE_UPDATE = (uint8_t)0x04, /* Data from an untouched pad.*/
 };
 
 typedef enum interface_mode {
-	RAW_SENSOR_MODE = (uint8_t)0x04,
+	RAW_SENSOR_MODE = (uint8_t)0x01,
 	HID_MODE        = (uint8_t)0x08
 } interface_mode;
 
+
 /*
  * function prototypes
  */
@@ -420,100 +758,183 @@ static struct usb_fifo_methods atp_fifo_
 };
 
 /* device initialization and shutdown */
-static usb_error_t   atp_req_get_report(struct usb_device *udev, void *data);
-static int           atp_set_device_mode(device_t dev, interface_mode mode);
-static void          atp_reset_callback(struct usb_xfer *, usb_error_t);
-static int           atp_enable(struct atp_softc *sc);
-static void          atp_disable(struct atp_softc *sc);
-static int           atp_softc_populate(struct atp_softc *);
-static void          atp_softc_unpopulate(struct atp_softc *);
+static usb_error_t   atp_set_device_mode(struct atp_softc *, interface_mode);
+static void	     atp_reset_callback(struct usb_xfer *, usb_error_t);
+static int	     atp_enable(struct atp_softc *);
+static void	     atp_disable(struct atp_softc *);
 
 /* sensor interpretation */
-static __inline void atp_interpret_sensor_data(const int8_t *, u_int, atp_axis,
-			 int *, atp_protocol);
-static __inline void atp_get_pressures(int *, const int *, const int *, int);
-static void          atp_detect_pspans(int *, u_int, u_int, atp_pspan *,
-			 u_int *);
+static void	     fg_interpret_sensor_data(struct atp_softc *, u_int);
+static void	     fg_extract_sensor_data(const int8_t *, u_int, atp_axis,
+    int *, enum fountain_geyser_trackpad_type);
+static void	     fg_get_pressures(int *, const int *, const int *, int);
+static void	     fg_detect_pspans(int *, u_int, u_int, fg_pspan *, u_int *);
+static void	     wsp_interpret_sensor_data(struct atp_softc *, u_int);
 
 /* movement detection */
-static boolean_t     atp_match_stroke_component(atp_stroke_component *,
-                         const atp_pspan *, atp_stroke_type);
-static void          atp_match_strokes_against_pspans(struct atp_softc *,
-			 atp_axis, atp_pspan *, u_int, u_int);
-static boolean_t     atp_update_strokes(struct atp_softc *,
-			 atp_pspan *, u_int, atp_pspan *, u_int);
-static __inline void atp_add_stroke(struct atp_softc *, const atp_pspan *,
-			 const atp_pspan *);
-static void          atp_add_new_strokes(struct atp_softc *, atp_pspan *,
-			 u_int, atp_pspan *, u_int);
-static void          atp_advance_stroke_state(struct atp_softc *,
-			 atp_stroke *, boolean_t *);
-static void          atp_terminate_stroke(struct atp_softc *, u_int);
-static __inline boolean_t atp_stroke_has_small_movement(const atp_stroke *);
-static __inline void atp_update_pending_mickeys(atp_stroke_component *);
-static void          atp_compute_smoothening_scale_ratio(atp_stroke *, int *,
-			 int *);
-static boolean_t     atp_compute_stroke_movement(atp_stroke *);
+static boolean_t     fg_match_stroke_component(fg_stroke_component_t *,
+    const fg_pspan *, atp_stroke_type);
+static void	     fg_match_strokes_against_pspans(struct atp_softc *,
+    atp_axis, fg_pspan *, u_int, u_int);
+static boolean_t     wsp_match_strokes_against_fingers(struct atp_softc *,
+    wsp_finger_t *, u_int);
+static boolean_t     fg_update_strokes(struct atp_softc *, fg_pspan *, u_int,
+    fg_pspan *, u_int);
+static boolean_t     wsp_update_strokes(struct atp_softc *,
+    wsp_finger_t [WSP_MAX_FINGERS], u_int);
+static void fg_add_stroke(struct atp_softc *, const fg_pspan *, const fg_pspan *);
+static void	     fg_add_new_strokes(struct atp_softc *, fg_pspan *,
+    u_int, fg_pspan *, u_int);
+static void wsp_add_stroke(struct atp_softc *, const wsp_finger_t *);
+static void	     atp_advance_stroke_state(struct atp_softc *,
+    atp_stroke_t *, boolean_t *);
+static boolean_t atp_stroke_has_small_movement(const atp_stroke_t *);
+static void	     atp_update_pending_mickeys(atp_stroke_t *);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-stable-8 mailing list