Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 19 Nov 2015 10:01:50 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r291066 - in stable/9/sys/dev/usb: . input
Message-ID:  <201511191001.tAJA1oOi093424@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Thu Nov 19 10:01:50 2015
New Revision: 291066
URL: https://svnweb.freebsd.org/changeset/base/291066

Log:
  MFC r290639:
  Update the wsp driver to support newer touch pads, like found in
  MacBookPro11,4 and MacBook12,1. This update adds support for the
  force touch parameter.
  
  PR:		204420

Modified:
  stable/9/sys/dev/usb/input/wsp.c
  stable/9/sys/dev/usb/usbdevs
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/usb/input/wsp.c
==============================================================================
--- stable/9/sys/dev/usb/input/wsp.c	Thu Nov 19 10:00:17 2015	(r291065)
+++ stable/9/sys/dev/usb/input/wsp.c	Thu Nov 19 10:01:50 2015	(r291066)
@@ -94,8 +94,8 @@ static struct wsp_tuning {
 	.z_factor = 5,
 	.pressure_touch_threshold = 50,
 	.pressure_untouch_threshold = 10,
-	.pressure_tap_threshold = 100,
-	.scr_hor_threshold = 10,
+	.pressure_tap_threshold = 120,
+	.scr_hor_threshold = 20,
 };
 
 static void
@@ -122,8 +122,6 @@ SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressu
 SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scr_hor_threshold, CTLFLAG_RW,
     &wsp_tuning.scr_hor_threshold, 0, "horizontal scrolling threshold");
 
-#define	WSP_IFACE_INDEX	1
-
 /*
  * Some tables, structures, definitions and constant values for the
  * touchpad protocol has been copied from Linux's
@@ -155,21 +153,30 @@ struct bt_data {
 enum tp_type {
 	TYPE1,			/* plain trackpad */
 	TYPE2,			/* button integrated in trackpad */
-	TYPE3			/* additional header fields since June 2013 */
+	TYPE3,			/* additional header fields since June 2013 */
+	TYPE4                   /* additional header field for pressure data */
 };
 
 /* trackpad finger data offsets, le16-aligned */
 #define	FINGER_TYPE1		(13 * 2)
 #define	FINGER_TYPE2		(15 * 2)
 #define	FINGER_TYPE3		(19 * 2)
+#define	FINGER_TYPE4		(23 * 2)
 
 /* trackpad button data offsets */
 #define	BUTTON_TYPE2		15
 #define	BUTTON_TYPE3		23
+#define	BUTTON_TYPE4		31
 
 /* list of device capability bits */
 #define	HAS_INTEGRATED_BUTTON	1
 
+/* trackpad finger data block size */
+#define FSIZE_TYPE1             (14 * 2)
+#define FSIZE_TYPE2             (14 * 2)
+#define FSIZE_TYPE3             (14 * 2)
+#define FSIZE_TYPE4             (15 * 2)
+
 /* trackpad finger header - little endian */
 struct tp_header {
 	uint8_t	flag;
@@ -197,9 +204,10 @@ struct tp_finger {
 	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	unused[2];		/* zeros */
+	int16_t pressure;		/* pressure on forcetouch touchpad */
 	int16_t	multi;			/* one finger: varies, more fingers:
-					 * constant */
+				 	 * constant */
 } __packed;
 
 /* trackpad finger data size, empirically at least ten fingers */
@@ -207,7 +215,7 @@ struct tp_finger {
 #define	SIZEOF_FINGER		sizeof(struct tp_finger)
 #define	SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
 
-#if (WSP_BUFFER_MAX < ((MAX_FINGERS * 14 * 2) + FINGER_TYPE3))
+#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
 #error "WSP_BUFFER_MAX is too small"
 #endif
 
@@ -224,6 +232,7 @@ enum {
 	WSP_FLAG_WELLSPRING7,
 	WSP_FLAG_WELLSPRING7A,
 	WSP_FLAG_WELLSPRING8,
+	WSP_FLAG_WELLSPRING9,
 	WSP_FLAG_MAX,
 };
 
@@ -231,69 +240,213 @@ enum {
 struct wsp_dev_params {
 	uint8_t	caps;			/* device capability bitmask */
 	uint8_t	tp_type;		/* type of trackpad interface */
+	uint8_t	tp_button;		/* offset to button data */
 	uint8_t	tp_offset;		/* offset to trackpad finger data */
+	uint8_t tp_fsize;		/* bytes in single finger block */
+	uint8_t tp_delta;		/* offset from header to finger struct */
+	uint8_t iface_index;
+	uint8_t um_size;		/* usb control message length */
+	uint8_t um_req_val;		/* usb control message value */
+	uint8_t um_req_idx;		/* usb control message index */
+	uint8_t um_switch_idx;		/* usb control message mode switch index */
+	uint8_t um_switch_on;		/* usb control message mode switch on */
+	uint8_t um_switch_off;		/* usb control message mode switch off */
 };
 
 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
 	[WSP_FLAG_WELLSPRING1] = {
 		.caps = 0,
 		.tp_type = TYPE1,
+		.tp_button = 0,
 		.tp_offset = FINGER_TYPE1,
+		.tp_fsize = FSIZE_TYPE1,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING2] = {
 		.caps = 0,
 		.tp_type = TYPE1,
+		.tp_button = 0,
 		.tp_offset = FINGER_TYPE1,
+		.tp_fsize = FSIZE_TYPE1,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING3] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING4] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING4A] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING5] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING6] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING5A] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING6A] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING7] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING7A] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
 		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
 	},
 	[WSP_FLAG_WELLSPRING8] = {
 		.caps = HAS_INTEGRATED_BUTTON,
 		.tp_type = TYPE3,
+		.tp_button = BUTTON_TYPE3,
 		.tp_offset = FINGER_TYPE3,
+		.tp_fsize = FSIZE_TYPE3,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING9] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE4,
+		.tp_button = BUTTON_TYPE4,
+		.tp_offset = FINGER_TYPE4,
+		.tp_fsize = FSIZE_TYPE4,
+		.tp_delta = 2,
+		.iface_index = 2,
+		.um_size = 2,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x02,
+		.um_switch_idx = 1,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x00,
 	},
 };
 
@@ -346,7 +499,7 @@ static const STRUCT_USB_HOST_ID wsp_devs
 	WSP_DEV(APPLE, WELLSPRING5A_JIS, WSP_FLAG_WELLSPRING5A),
 
 	/* MacbookPro10,1 (unibody, June 2012) */
-	/* MacbookPro11,? (unibody, June 2013) */
+	/* MacbookPro11,1-3 (unibody, June 2013) */
 	WSP_DEV(APPLE, WELLSPRING7_ANSI, WSP_FLAG_WELLSPRING7),
 	WSP_DEV(APPLE, WELLSPRING7_ISO, WSP_FLAG_WELLSPRING7),
 	WSP_DEV(APPLE, WELLSPRING7_JIS, WSP_FLAG_WELLSPRING7),
@@ -360,6 +513,11 @@ static const STRUCT_USB_HOST_ID wsp_devs
 	WSP_DEV(APPLE, WELLSPRING8_ANSI, WSP_FLAG_WELLSPRING8),
 	WSP_DEV(APPLE, WELLSPRING8_ISO, WSP_FLAG_WELLSPRING8),
 	WSP_DEV(APPLE, WELLSPRING8_JIS, WSP_FLAG_WELLSPRING8),
+
+	/* MacbookPro12,1 MacbookPro11,4 */
+	WSP_DEV(APPLE, WELLSPRING9_ANSI, WSP_FLAG_WELLSPRING9),
+	WSP_DEV(APPLE, WELLSPRING9_ISO, WSP_FLAG_WELLSPRING9),
+	WSP_DEV(APPLE, WELLSPRING9_JIS, WSP_FLAG_WELLSPRING9),
 };
 
 #define	WSP_FIFO_BUF_SIZE	 8	/* bytes */
@@ -421,11 +579,6 @@ struct wsp_softc {
 	uint8_t tp_data[WSP_BUFFER_MAX] __aligned(4);		/* trackpad transferred data */
 };
 
-typedef enum interface_mode {
-	RAW_SENSOR_MODE = 0x01,
-	HID_MODE = 0x08
-} interface_mode;
-
 /*
  * function prototypes
  */
@@ -473,14 +626,19 @@ static const struct usb_config wsp_confi
 };
 
 static usb_error_t
-wsp_set_device_mode(struct wsp_softc *sc, interface_mode mode)
+wsp_set_device_mode(struct wsp_softc *sc, uint8_t on)
 {
+	const struct wsp_dev_params *params = sc->sc_params;
 	uint8_t	mode_bytes[8];
 	usb_error_t err;
 
+	/* Type 3 does not require a mode switch */
+	if (params->tp_type == TYPE3)
+		return 0;
+
 	err = usbd_req_get_report(sc->sc_usb_device, NULL,
-	    mode_bytes, sizeof(mode_bytes), 0,
-	    0x03, 0x00);
+	    mode_bytes, params->um_size, params->iface_index,
+	    params->um_req_val, params->um_req_idx);
 
 	if (err != USB_ERR_NORMAL_COMPLETION) {
 		DPRINTF("Failed to read device mode (%d)\n", err);
@@ -495,11 +653,12 @@ wsp_set_device_mode(struct wsp_softc *sc
 	 */
 	pause("WHW", hz / 4);
 
-	mode_bytes[0] = mode;
+	mode_bytes[params->um_switch_idx] = 
+	    on ? params->um_switch_on : params->um_switch_off;
 
 	return (usbd_req_set_report(sc->sc_usb_device, NULL,
-	    mode_bytes, sizeof(mode_bytes), 0,
-	    0x03, 0x00));
+	    mode_bytes, params->um_size, params->iface_index, 
+	    params->um_req_val, params->um_req_idx));
 }
 
 static int
@@ -524,17 +683,29 @@ static int
 wsp_probe(device_t self)
 {
 	struct usb_attach_arg *uaa = device_get_ivars(self);
+	struct usb_interface_descriptor *id;
+	struct usb_interface *iface;
+	uint8_t i;
 
 	if (uaa->usb_mode != USB_MODE_HOST)
 		return (ENXIO);
 
-	if (uaa->info.bIfaceIndex != WSP_IFACE_INDEX)
-		return (ENXIO);
-
-	if ((uaa->info.bInterfaceClass != UICLASS_HID) ||
-	    (uaa->info.bInterfaceProtocol != 0))
+	/* figure out first interface matching */
+	for (i = 1;; i++) {
+		iface = usbd_get_iface(uaa->device, i);
+		if (iface == NULL || i == 3)
+			return (ENXIO);
+		id = iface->idesc;
+		if ((id == NULL) ||
+		    (id->bInterfaceClass != UICLASS_HID) ||
+		    (id->bInterfaceProtocol != 0 &&
+		    id->bInterfaceProtocol != UIPROTO_MOUSE))
+			continue;
+		break;
+	}
+	/* check if we are attaching to the first match */
+	if (uaa->info.bIfaceIndex != i)
 		return (ENXIO);
-
 	return (usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa));
 }
 
@@ -569,6 +740,9 @@ wsp_attach(device_t dev)
 
 	sc->sc_usb_device = uaa->device;
 
+	/* get device specific configuration */
+	sc->sc_params = wsp_dev_params + USB_GET_DRIVER_INFO(uaa);
+
 	/*
 	 * By default the touchpad behaves like a HID device, sending
 	 * packets with reportID = 8. Such reports contain only
@@ -584,13 +758,13 @@ wsp_attach(device_t dev)
 	 * device back into HID mode before switching it to RAW
 	 * mode. Else the device does not work like expected.
 	 */
-	err = wsp_set_device_mode(sc, HID_MODE);
+	err = wsp_set_device_mode(sc, 0);
 	if (err != USB_ERR_NORMAL_COMPLETION) {
 		DPRINTF("Failed to set mode to HID MODE (%d)\n", err);
 		return (ENXIO);
 	}
 
-	err = wsp_set_device_mode(sc, RAW_SENSOR_MODE);
+	err = wsp_set_device_mode(sc, 1);
 	if (err != USB_ERR_NORMAL_COMPLETION) {
 		DPRINTF("failed to set mode to RAW MODE (%d)\n", err);
 		return (ENXIO);
@@ -598,9 +772,6 @@ wsp_attach(device_t dev)
 
 	mtx_init(&sc->sc_mutex, "wspmtx", NULL, MTX_DEF | MTX_RECURSE);
 
-	/* get device specific configuration */
-	sc->sc_params = wsp_dev_params + USB_GET_DRIVER_INFO(uaa);
-
 	err = usbd_transfer_setup(uaa->device,
 	    &uaa->info.bIfaceIndex, sc->sc_xfer, wsp_config,
 	    WSP_N_TRANSFER, sc, &sc->sc_mutex);
@@ -642,7 +813,7 @@ wsp_detach(device_t dev)
 {
 	struct wsp_softc *sc = device_get_softc(dev);
 
-	(void) wsp_set_device_mode(sc, HID_MODE);
+	(void) wsp_set_device_mode(sc, 0);
 
 	mtx_lock(&sc->sc_mutex);
 	if (sc->sc_state & WSP_ENABLED)
@@ -692,6 +863,13 @@ wsp_intr_callback(struct usb_xfer *xfer,
 		pc = usbd_xfer_get_frame(xfer, 0);
 		usbd_copy_out(pc, 0, sc->tp_data, len);
 
+		if ((len < params->tp_offset + params->tp_fsize) ||
+		    ((len - params->tp_offset) % params->tp_fsize) != 0) {
+			DPRINTFN(WSP_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
+			    len, sc->tp_data[0], sc->tp_data[1]);
+			goto tr_setup;
+		}
+
 		if (len < sc->tp_datalen) {
 			/* make sure we don't process old data */
 			memset(sc->tp_data + len, 0, sc->tp_datalen - len);
@@ -699,12 +877,9 @@ wsp_intr_callback(struct usb_xfer *xfer,
 
 		h = (struct tp_header *)(sc->tp_data);
 
-		if (params->tp_type == TYPE2) {
-			ibt = sc->tp_data[BUTTON_TYPE2];
-			ntouch = sc->tp_data[BUTTON_TYPE2 - 1];
-		} else if (params->tp_type == TYPE3) {
-			ibt = sc->tp_data[BUTTON_TYPE3];
-			ntouch = sc->tp_data[BUTTON_TYPE3 - 1];
+		if (params->tp_type >= TYPE2) {
+			ibt = sc->tp_data[params->tp_button];
+			ntouch = sc->tp_data[params->tp_button - 1];
 		}
 		/* range check */
 		if (ntouch < 0)
@@ -712,33 +887,33 @@ wsp_intr_callback(struct usb_xfer *xfer,
 		else if (ntouch > MAX_FINGERS)
 			ntouch = MAX_FINGERS;
 
-		f = (struct tp_finger *)(sc->tp_data + params->tp_offset);
-
 		for (i = 0; i != ntouch; i++) {
+			f = (struct tp_finger *)(sc->tp_data + params->tp_offset + params->tp_delta + i * params->tp_fsize);
 			/* swap endianness, if any */
 			if (le16toh(0x1234) != 0x1234) {
-				f[i].origin = le16toh((uint16_t)f[i].origin);
-				f[i].abs_x = le16toh((uint16_t)f[i].abs_x);
-				f[i].abs_y = le16toh((uint16_t)f[i].abs_y);
-				f[i].rel_x = le16toh((uint16_t)f[i].rel_x);
-				f[i].rel_y = le16toh((uint16_t)f[i].rel_y);
-				f[i].tool_major = le16toh((uint16_t)f[i].tool_major);
-				f[i].tool_minor = le16toh((uint16_t)f[i].tool_minor);
-				f[i].orientation = le16toh((uint16_t)f[i].orientation);
-				f[i].touch_major = le16toh((uint16_t)f[i].touch_major);
-				f[i].touch_minor = le16toh((uint16_t)f[i].touch_minor);
-				f[i].multi = le16toh((uint16_t)f[i].multi);
+				f->origin = le16toh((uint16_t)f->origin);
+				f->abs_x = le16toh((uint16_t)f->abs_x);
+				f->abs_y = le16toh((uint16_t)f->abs_y);
+				f->rel_x = le16toh((uint16_t)f->rel_x);
+				f->rel_y = le16toh((uint16_t)f->rel_y);
+				f->tool_major = le16toh((uint16_t)f->tool_major);
+				f->tool_minor = le16toh((uint16_t)f->tool_minor);
+				f->orientation = le16toh((uint16_t)f->orientation);
+				f->touch_major = le16toh((uint16_t)f->touch_major);
+				f->touch_minor = le16toh((uint16_t)f->touch_minor);
+				f->pressure = le16toh((uint16_t)f->pressure);
+				f->multi = le16toh((uint16_t)f->multi);
 			}
-			DPRINTFN(WSP_LLEVEL_INFO, "[%d]ibt=%d, taps=%d, u=%x, o=%4d, ax=%5d, ay=%5d, "
-			    "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%5d, tchmaj=%4d, tchmin=%4d, m=%4x\n",
-			    i, ibt, ntouch, h->q2,
-			    f[i].origin, f[i].abs_x, f[i].abs_y, f[i].rel_x, f[i].rel_y,
-			    f[i].tool_major, f[i].tool_minor, f[i].orientation,
-			    f[i].touch_major, f[i].touch_minor, f[i].multi);
-
-			sc->pos_x[i] = f[i].abs_x;
-			sc->pos_y[i] = -f[i].abs_y;
-			sc->index[i] = &f[i];
+			DPRINTFN(WSP_LLEVEL_INFO, 
+			    "[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
+			    "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
+			    "tchmaj=%4d, tchmin=%4d, presure=%4d, m=%4x\n",
+			    i, ibt, ntouch, f->origin, f->abs_x, f->abs_y,
+			    f->rel_x, f->rel_y, f->tool_major, f->tool_minor, f->orientation,
+			    f->touch_major, f->touch_minor, f->pressure, f->multi);
+			sc->pos_x[i] = f->abs_x;
+			sc->pos_y[i] = -f->abs_y;
+			sc->index[i] = f;
 		}
 
 		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
@@ -750,24 +925,24 @@ wsp_intr_callback(struct usb_xfer *xfer,
 			sc->sc_status.button |= MOUSE_BUTTON1DOWN;
 			sc->ibtn = 1;
 		}
-		if (h->q2 == 4)
-			sc->intr_count++;
+		sc->intr_count++;
 
 		if (sc->ntaps < ntouch) {
 			switch (ntouch) {
 			case 1:
-				if (f[0].touch_major > tun.pressure_tap_threshold)
+				if (sc->index[0]->touch_major > tun.pressure_tap_threshold &&
+				    sc->index[0]->tool_major <= 1200)
 					sc->ntaps = 1;
 				break;
 			case 2:
-				if (f[0].touch_major > tun.pressure_tap_threshold &&
-				    f[1].touch_major > tun.pressure_tap_threshold)
+				if (sc->index[0]->touch_major > tun.pressure_tap_threshold-30 &&
+				    sc->index[1]->touch_major > tun.pressure_tap_threshold-30)
 					sc->ntaps = 2;
 				break;
 			case 3:
-				if (f[0].touch_major > tun.pressure_tap_threshold &&
-				    f[1].touch_major > tun.pressure_tap_threshold &&
-				    f[2].touch_major > tun.pressure_tap_threshold)
+				if (sc->index[0]->touch_major > tun.pressure_tap_threshold-40 &&
+				    sc->index[1]->touch_major > tun.pressure_tap_threshold-40 &&
+				    sc->index[2]->touch_major > tun.pressure_tap_threshold-40)
 					sc->ntaps = 3;
 				break;
 			default:
@@ -779,7 +954,7 @@ wsp_intr_callback(struct usb_xfer *xfer,
 			    abs(sc->pos_x[0] - sc->pos_x[1]),
 			    abs(sc->pos_y[0] - sc->pos_y[1])));
 		}
-		if (f[0].touch_major < tun.pressure_untouch_threshold &&
+		if (sc->index[0]->touch_major < tun.pressure_untouch_threshold &&
 		    sc->sc_status.button == 0) {
 			sc->sc_touch = WSP_UNTOUCH;
 			if (sc->intr_count < WSP_TAP_MAX_COUNT &&
@@ -840,10 +1015,10 @@ wsp_intr_callback(struct usb_xfer *xfer,
 			sc->rdy = 0;
 			sc->rdz = 0;
 			sc->scr_mode = WSP_SCR_NONE;
-		} else if (f[0].touch_major >= tun.pressure_touch_threshold &&
+		} else if (sc->index[0]->touch_major >= tun.pressure_touch_threshold &&
 		    sc->sc_touch == WSP_UNTOUCH) {	/* ignore first touch */
 			sc->sc_touch = WSP_FIRST_TOUCH;
-		} else if (f[0].touch_major >= tun.pressure_touch_threshold &&
+		} else if (sc->index[0]->touch_major >= tun.pressure_touch_threshold &&
 		    sc->sc_touch == WSP_FIRST_TOUCH) {	/* ignore second touch */
 			sc->sc_touch = WSP_SECOND_TOUCH;
 			DPRINTFN(WSP_LLEVEL_INFO, "Fist pre_x=%5d, pre_y=%5d\n",
@@ -853,22 +1028,26 @@ wsp_intr_callback(struct usb_xfer *xfer,
 				sc->sc_touch = WSP_TOUCHING;
 
 			if (ntouch != 0 &&
-			    h->q2 == 4 &&
-			    f[0].touch_major >= tun.pressure_touch_threshold) {
+			    sc->index[0]->touch_major >= tun.pressure_touch_threshold) {
 				dx = sc->pos_x[0] - sc->pre_pos_x;
 				dy = sc->pos_y[0] - sc->pre_pos_y;
 
-				/* Ignore movement from ibt=1 to ibt=0 */
-				if (sc->sc_status.obutton != 0 && 
-				    sc->sc_status.button == 0) {
-					dx = 0;
-					dy = 0;
-				}
+				/* Ignore movement during button is releasing */
+				if (sc->ibtn != 0 && sc->sc_status.button == 0)
+					dx = dy = 0;
+
 				/* Ignore movement if ntouch changed */
-				if (sc->o_ntouch != ntouch) {
-					dx = 0;
-					dy = 0;
-				}
+				if (sc->o_ntouch != ntouch)
+					dx = dy = 0;
+
+				/* Ignore unexpeted movment when typing */
+				if (ntouch == 1 && sc->index[0]->tool_major > 1200)
+					dx = dy = 0;
+
+				if (sc->ibtn != 0 && ntouch == 1 && 
+				    sc->intr_count < WSP_TAP_MAX_COUNT && 
+				    abs(sc->dx_sum) < 1 && abs(sc->dy_sum) < 1 )
+					dx = dy = 0;
 
 				if (ntouch == 2 && sc->sc_status.button != 0) {
 					dx = sc->pos_x[sc->finger] - sc->pre_pos_x;
@@ -878,26 +1057,23 @@ wsp_intr_callback(struct usb_xfer *xfer,
 					 * Ignore movement of switch finger or
 					 * movement from ibt=0 to ibt=1
 					 */
-					if (f[0].origin == 0 || f[1].origin == 0 ||
+					if (sc->index[0]->origin == 0 || sc->index[1]->origin == 0 ||
 					    sc->sc_status.obutton != sc->sc_status.button) {
-						dx = 0;
-						dy = 0;
+						dx = dy = 0;
 						sc->finger = 0;
 					}
-					if ((abs(f[0].rel_x) + abs(f[0].rel_y)) <
-					    (abs(f[1].rel_x) + abs(f[1].rel_y)) &&
+					if ((abs(sc->index[0]->rel_x) + abs(sc->index[0]->rel_y)) <
+					    (abs(sc->index[1]->rel_x) + abs(sc->index[1]->rel_y)) &&
 					    sc->finger == 0) {
 						sc->sc_touch = WSP_SECOND_TOUCH;
-						dx = 0;
-						dy = 0;
+						dx = dy = 0;
 						sc->finger = 1;
 					}
-					if ((abs(f[0].rel_x) + abs(f[0].rel_y)) >=
-					    (abs(f[1].rel_x) + abs(f[1].rel_y)) &&
+					if ((abs(sc->index[0]->rel_x) + abs(sc->index[0]->rel_y)) >=
+					    (abs(sc->index[1]->rel_x) + abs(sc->index[1]->rel_y)) &&
 					    sc->finger == 1) {
 						sc->sc_touch = WSP_SECOND_TOUCH;
-						dx = 0;
-						dy = 0;
+						dx = dy = 0;
 						sc->finger = 0;
 					}
 					DPRINTFN(WSP_LLEVEL_INFO, "dx=%5d, dy=%5d, mov=%5d\n",
@@ -926,8 +1102,7 @@ wsp_intr_callback(struct usb_xfer *xfer,
 				if (sc->scr_mode == WSP_SCR_NONE &&
 				    abs(sc->dx_sum) + abs(sc->dy_sum) > tun.scr_hor_threshold)
 					sc->scr_mode = abs(sc->dx_sum) >
-					    abs(sc->dy_sum) * 3 ? WSP_SCR_HOR :
-					    WSP_SCR_VER;
+					    abs(sc->dy_sum) * 2 ? WSP_SCR_HOR : WSP_SCR_VER;
 				DPRINTFN(WSP_LLEVEL_INFO, "scr_mode=%5d, count=%d, dx_sum=%d, dy_sum=%d\n",
 				    sc->scr_mode, sc->intr_count, sc->dx_sum, sc->dy_sum);
 				if (sc->scr_mode == WSP_SCR_HOR)
@@ -935,8 +1110,7 @@ wsp_intr_callback(struct usb_xfer *xfer,
 				else
 					sc->dt_sum = 0;
 
-				dx = 0;
-				dy = 0;
+				dx = dy = 0;
 				if (sc->dz_count == 0)
 					dz = sc->dz_sum / tun.z_factor;
 				if (sc->scr_mode == WSP_SCR_HOR || 
@@ -944,15 +1118,12 @@ wsp_intr_callback(struct usb_xfer *xfer,
 				    abs(sc->pos_y[0] - sc->pos_y[1]) > MAX_DISTANCE)
 					dz = 0;
 			}
-			if (ntouch == 3) {
-				dx = 0;
-				dy = 0;
-				dz = 0;
-			}
+			if (ntouch == 3)
+				dx = dy = dz = 0;
 			if (sc->intr_count < WSP_TAP_MAX_COUNT &&
-			    abs(dx) < 3 && abs(dy) < 3 && abs(dz) < 3) {
+			    abs(dx) < 3 && abs(dy) < 3 && abs(dz) < 3)
 				dx = dy = dz = 0;
-			} else
+			else
 				sc->intr_count = WSP_TAP_MAX_COUNT;
 			if (dx || dy || dz)
 				sc->sc_status.flags |= MOUSE_POSCHANGED;

Modified: stable/9/sys/dev/usb/usbdevs
==============================================================================
--- stable/9/sys/dev/usb/usbdevs	Thu Nov 19 10:00:17 2015	(r291065)
+++ stable/9/sys/dev/usb/usbdevs	Thu Nov 19 10:01:50 2015	(r291066)
@@ -1128,6 +1128,10 @@ product APPLE WELLSPRING7A_JIS	0x025b	Ap
 product APPLE WELLSPRING8_ANSI	0x0290	Apple Internal Keyboard/Trackpad
 product APPLE WELLSPRING8_ISO	0x0291	Apple Internal Keyboard/Trackpad
 product APPLE WELLSPRING8_JIS	0x0292	Apple Internal Keyboard/Trackpad
+/* MacbookPro12,1 */
+product APPLE WELLSPRING9_ANSI	0x0272	Apple Internal Keyboard/Trackpad
+product APPLE WELLSPRING9_ISO	0x0273	Apple Internal Keyboard/Trackpad
+product APPLE WELLSPRING9_JIS	0x0274	Apple Internal Keyboard/Trackpad
 product APPLE MOUSE		0x0301	Mouse M4848
 product APPLE OPTMOUSE		0x0302	Optical mouse
 product APPLE MIGHTYMOUSE	0x0304	Mighty Mouse



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201511191001.tAJA1oOi093424>