Type 4 devices like the MacBookPro12,1 have extra padding in between 
each chunk of finger data that needs to be skipped, otherwise the 
offset will be wrong and each additional finger will read as static 
coordinates.  This must have been overlooked when it was added to 
the driver in 2015 since the first finger of data always read 
properly.

Also, we can now pass in the actual pressure data instead of having 
to use a constant value just to make the synaptics driver happy 
since we now have wstpad.  The per-type min/max pressure values can 
also be passed in when calling wsmouse_configure.

Tested on the 2015 MacBook Pro.  Tests on other Apple devices would 
be appreciated.


Index: sys/dev/usb/ubcmtp.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ubcmtp.c,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 ubcmtp.c
--- sys/dev/usb/ubcmtp.c        30 Jul 2018 15:56:30 -0000      1.18
+++ sys/dev/usb/ubcmtp.c        16 Aug 2018 02:42:11 -0000
@@ -118,6 +118,7 @@ struct ubcmtp_finger {
 #define UBCMTP_TYPE4_TPLEN     UBCMTP_TYPE4_TPOFF + UBCMTP_ALL_FINGER_SIZE
 #define UBCMTP_TYPE4_TPIFACE   2
 #define UBCMTP_TYPE4_BTOFF     31
+#define UBCMTP_TYPE4_FINGERPAD (1 * sizeof(uint16_t))
 
 #define UBCMTP_FINGER_ORIENT   16384
 #define UBCMTP_SN_PRESSURE     45
@@ -128,9 +129,6 @@ struct ubcmtp_finger {
 /* Identify clickpads in ubcmtp_configure. */
 #define IS_CLICKPAD(ubcmtp_type) (ubcmtp_type != UBCMTP_TYPE1)
 
-/* Use a constant, synaptics-compatible pressure value for now. */
-#define DEFAULT_PRESSURE       40
-
 struct ubcmtp_limit {
        int limit;
        int min;
@@ -337,6 +335,7 @@ struct ubcmtp_softc {
        int                     sc_tp_epaddr;   /* endpoint addr */
        int                     tp_maxlen;      /* max size of tp data */
        int                     tp_offset;      /* finger offset into data */
+       int                     tp_fingerpad;   /* padding between finger data 
*/
        uint8_t                 *tp_pkt;
 
        int                     bt_ifacenum;    /* button interface number */
@@ -425,6 +424,7 @@ ubcmtp_attach(struct device *parent, str
 
        sc->sc_udev = uaa->device;
        sc->sc_status = 0;
+       sc->tp_fingerpad = 0;
 
        if ((udd = usbd_get_device_descriptor(dev)) == NULL) {
                printf("ubcmtp: failed getting device descriptor\n");
@@ -478,6 +478,7 @@ ubcmtp_attach(struct device *parent, str
                sc->tp_maxlen = UBCMTP_TYPE4_TPLEN;
                sc->tp_offset = UBCMTP_TYPE4_TPOFF;
                sc->tp_ifacenum = UBCMTP_TYPE4_TPIFACE;
+               sc->tp_fingerpad = UBCMTP_TYPE4_FINGERPAD;
                break;
        }
 
@@ -520,6 +521,10 @@ int
 ubcmtp_configure(struct ubcmtp_softc *sc)
 {
        struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev);
+       struct wsmouse_param params[] = {
+               { WSMOUSECFG_PRESSURE_LO, sc->dev_type->l_pressure.min },
+               { WSMOUSECFG_PRESSURE_HI, sc->dev_type->l_pressure.max },
+       };
 
        hw->type = WSMOUSE_TYPE_TOUCHPAD;
        hw->hw_type = (IS_CLICKPAD(sc->dev_type->type)
@@ -531,7 +536,7 @@ ubcmtp_configure(struct ubcmtp_softc *sc
        hw->mt_slots = UBCMTP_MAX_FINGERS;
        hw->flags = WSMOUSEHW_MT_TRACKING;
 
-       return wsmouse_configure(sc->sc_wsmousedev, NULL, 0);
+       return wsmouse_configure(sc->sc_wsmousedev, params, 0);
 }
 
 int
@@ -793,9 +798,9 @@ void
 ubcmtp_tp_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
 {
        struct ubcmtp_softc *sc = priv;
-       struct ubcmtp_finger *pkt;
+       struct ubcmtp_finger *finger;
        u_int32_t pktlen;
-       int i, s, btn, contacts, fingers;
+       int off, s, btn, contacts = 0;
 
        if (usbd_is_dying(sc->sc_udev) || !(sc->sc_status & UBCMTP_ENABLED))
                return;
@@ -816,16 +821,19 @@ ubcmtp_tp_intr(struct usbd_xfer *xfer, v
        if (sc->tp_pkt == NULL || pktlen < sc->tp_offset)
                return;
 
-       pkt = (struct ubcmtp_finger *)(sc->tp_pkt + sc->tp_offset);
-       fingers = (pktlen - sc->tp_offset) / sizeof(struct ubcmtp_finger);
-
        contacts = 0;
-       for (i = 0; i < fingers; i++) {
-               if ((int16_t)letoh16(pkt[i].touch_major) == 0)
+       for (off = sc->tp_offset; off < pktlen;
+           off += (sizeof(struct ubcmtp_finger) + sc->tp_fingerpad)) {
+               finger = (struct ubcmtp_finger *)(sc->tp_pkt + off);
+
+               if ((int16_t)letoh16(finger->touch_major) == 0)
                        continue; /* finger lifted */
-               sc->frame[contacts].x = (int16_t)letoh16(pkt[i].abs_x);
-               sc->frame[contacts].y = (int16_t)letoh16(pkt[i].abs_y);
-               sc->frame[contacts].pressure = DEFAULT_PRESSURE;
+
+               sc->frame[contacts].x = (int16_t)letoh16(finger->abs_x);
+               sc->frame[contacts].y = (int16_t)letoh16(finger->abs_y);
+               sc->frame[contacts].pressure =
+                   (int16_t)letoh16(finger->pressure);
+
                contacts++;
        }
 

Reply via email to