Author: hselasky
Date: Tue Nov 10 09:27:52 2015
New Revision: 290639
URL: https://svnweb.freebsd.org/changeset/base/290639

Log:
  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
  MFC after:    1 week

Modified:
  head/sys/dev/usb/input/wsp.c
  head/sys/dev/usb/usbdevs

Modified: head/sys/dev/usb/input/wsp.c
==============================================================================
--- head/sys/dev/usb/input/wsp.c        Tue Nov 10 08:39:07 2015        
(r290638)
+++ head/sys/dev/usb/input/wsp.c        Tue Nov 10 09:27:52 2015        
(r290639)
@@ -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_RWTUN,
     &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: head/sys/dev/usb/usbdevs
==============================================================================
--- head/sys/dev/usb/usbdevs    Tue Nov 10 08:39:07 2015        (r290638)
+++ head/sys/dev/usb/usbdevs    Tue Nov 10 09:27:52 2015        (r290639)
@@ -1131,6 +1131,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
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to