The branch stable/13 has been updated by hselasky:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f560d0ead1266dd33bdfa4ce803e70b87c285cfe

commit f560d0ead1266dd33bdfa4ce803e70b87c285cfe
Author:     Val Packett <v...@packett.cool>
AuthorDate: 2023-04-25 09:20:53 +0000
Commit:     Hans Petter Selasky <hsela...@freebsd.org>
CommitDate: 2023-04-30 06:56:17 +0000

    bcm5974(4): add Magic Trackpad 2 (USB only) support
    
    The MT2 uses a compact report format, but otherwise is similar in many
    ways to the internal trackpads, it even uses the same mode switching
    commands.
    
    Reviewed by:    wulf
    Differential revision:  https://reviews.freebsd.org/D34437
    
    (cherry picked from commit ef8397c28e981e0115d435aabcf57cee7ea5f5ee)
---
 sys/dev/hid/bcm5974.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++--
 sys/dev/usb/usbdevs   |  1 +
 2 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/sys/dev/hid/bcm5974.c b/sys/dev/hid/bcm5974.c
index d92c1c5c43b5..223ed01e8312 100644
--- a/sys/dev/hid/bcm5974.c
+++ b/sys/dev/hid/bcm5974.c
@@ -114,11 +114,13 @@ enum tp_type {
        TYPE2,                  /* button integrated in trackpad */
        TYPE3,                  /* additional header fields since June 2013 */
        TYPE4,                  /* additional header field for pressure data */
+       TYPE_MT2U,                      /* Magic Trackpad 2 USB */
        TYPE_CNT
 };
 
 /* list of device capability bits */
 #define        HAS_INTEGRATED_BUTTON   1
+#define        USES_COMPACT_REPORT     2
 
 struct tp_type_params {
        uint8_t caps;           /* device capability bitmask */
@@ -150,6 +152,36 @@ struct tp_type_params {
                .offset = 23 * 2,
                .delta = 2,
        },
+       [TYPE_MT2U] = {
+               .caps = HAS_INTEGRATED_BUTTON | USES_COMPACT_REPORT,
+               .button = 1,
+               .offset = 12,
+               .delta = 0,
+       },
+};
+
+/* trackpad finger structure - compact version for external "Magic" devices */
+struct tp_finger_compact {
+       uint32_t coords; /* not struct directly due to endian conversion */
+       uint8_t touch_major;
+       uint8_t touch_minor;
+       uint8_t size;
+       uint8_t pressure;
+       unsigned int orientation: 3;
+       unsigned int _unknown1: 1;
+       unsigned int id: 4;
+} __packed;
+
+_Static_assert((sizeof(struct tp_finger_compact) == 9), "tp_finger struct size 
must be 9");
+
+union tp_finger_compact_coords {
+       uint32_t num;
+       struct {
+               signed int x: 13;
+               signed int y: 13;
+               signed int _unknown: 4;
+               signed int state: 2;
+       } __packed;
 };
 
 /* trackpad finger structure - little endian */
@@ -189,6 +221,7 @@ enum {
        BCM5974_FLAG_WELLSPRING7A,
        BCM5974_FLAG_WELLSPRING8,
        BCM5974_FLAG_WELLSPRING9,
+       BCM5974_FLAG_MAGIC_TRACKPAD2_USB,
        BCM5974_FLAG_MAX,
 };
 
@@ -334,6 +367,15 @@ static const struct bcm5974_dev_params 
bcm5974_dev_params[BCM5974_FLAG_MAX] = {
                .o = { SN_ORIENT,
                    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
        },
+       [BCM5974_FLAG_MAGIC_TRACKPAD2_USB] = {
+               .tp = tp + TYPE_MT2U,
+               .p = { SN_PRESSURE, 0, 256, 256 },
+               .w = { SN_WIDTH, 0, 2048, 0 },
+               .x = { SN_COORD, -3678, 3934, 48 },
+               .y = { SN_COORD, -2478, 2587, 44 },
+               .o = { SN_ORIENT,
+                   -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
+       },
 };
 
 #define        BCM5974_DEV(v,p,i)      {                                       
\
@@ -407,6 +449,9 @@ static const struct hid_device_id bcm5974_devs[] = {
        BCM5974_DEV(APPLE, WELLSPRING9_ANSI, BCM5974_FLAG_WELLSPRING9),
        BCM5974_DEV(APPLE, WELLSPRING9_ISO, BCM5974_FLAG_WELLSPRING9),
        BCM5974_DEV(APPLE, WELLSPRING9_JIS, BCM5974_FLAG_WELLSPRING9),
+
+       /* External "Magic" devices */
+       BCM5974_DEV(APPLE, MAGIC_TRACKPAD2, BCM5974_FLAG_MAGIC_TRACKPAD2_USB),
 };
 
 struct bcm5974_softc {
@@ -541,6 +586,7 @@ bcm5974_set_device_mode(struct bcm5974_softc *sc, bool on)
        case TYPE3:     /* Type 3 does not require a mode switch */
                break;
        case TYPE4:
+       case TYPE_MT2U:
                err = bcm5974_set_device_mode_hid(sc, on);
                break;
        default:
@@ -624,8 +670,10 @@ bcm5974_attach(device_t dev)
        BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
        BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
        /* finger approach area */
-       BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
-       BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
+       if ((sc->sc_params->tp->caps & USES_COMPACT_REPORT) == 0) {
+               BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
+               BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
+       }
        /* finger orientation */
        BCM5974_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
        /* button properties */
@@ -637,7 +685,8 @@ bcm5974_attach(device_t dev)
            0, MAX_FINGERS - 1, 0, 0, 0);
        evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
            -1, MAX_FINGERS - 1, 0, 0, 0);
-       evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
+       if ((sc->sc_params->tp->caps & USES_COMPACT_REPORT) == 0)
+               evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
        evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
        /* Synaptics compatibility events */
        evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
@@ -672,12 +721,17 @@ bcm5974_intr(void *context, void *data, hid_size_t len)
        const struct bcm5974_dev_params *params = sc->sc_params;
        union evdev_mt_slot slot_data;
        struct tp_finger *f;
+       struct tp_finger_compact *fc;
+       union tp_finger_compact_coords coords;
        int ntouch;                     /* the finger number in touch */
        int ibt;                        /* button status */
        int i;
        int slot;
        uint8_t fsize = sizeof(struct tp_finger) + params->tp->delta;
 
+       if ((params->tp->caps & USES_COMPACT_REPORT) != 0)
+               fsize = sizeof(struct tp_finger_compact) + params->tp->delta;
+
        if ((len < params->tp->offset + fsize) ||
            ((len - params->tp->offset) % fsize) != 0) {
                DPRINTFN(BCM5974_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
@@ -689,6 +743,32 @@ bcm5974_intr(void *context, void *data, hid_size_t len)
        ntouch = (len - params->tp->offset) / fsize;
 
        for (i = 0, slot = 0; i != ntouch; i++) {
+               if ((params->tp->caps & USES_COMPACT_REPORT) != 0) {
+                       fc = (struct tp_finger_compact *)(((uint8_t *)data) +
+                            params->tp->offset + params->tp->delta + i * 
fsize);
+                       coords.num = le32toh(fc->coords);
+                       DPRINTFN(BCM5974_LLEVEL_INFO,
+                           "[%d]ibt=%d, taps=%d, x=%5d, y=%5d, state=%4d, "
+                           "tchmaj=%4d, tchmin=%4d, size=%4d, pressure=%4d, "
+                           "ot=%4x, id=%4x\n",
+                           i, ibt, ntouch, coords.x, coords.y,
+                           fc->state, fc->touch_major, fc->touch_minor, 
fc->size,
+                           fc->pressure, fc->orientation, fc->id);
+                       if (fc->touch_major == 0)
+                               continue;
+                       slot_data = (union evdev_mt_slot) {
+                               .id = fc->id,
+                               .x = coords.x,
+                               .y = params->y.min + params->y.max - coords.y,
+                               .p = fc->pressure,
+                               .maj = fc->touch_major << 2,
+                               .min = fc->touch_minor << 2,
+                               .ori = -fc->orientation,
+                       };
+                       evdev_mt_push_slot(sc->sc_evdev, slot, &slot_data);
+                       slot++;
+                       continue;
+               }
                f = (struct tp_finger *)(((uint8_t *)data) +
                    params->tp->offset + params->tp->delta + i * fsize);
                DPRINTFN(BCM5974_LLEVEL_INFO,
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 0368ec25e6e1..fb282568935f 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -1193,6 +1193,7 @@ product APPLE WELLSPRING8_JIS     0x0292  Apple Internal 
Keyboard/Trackpad
 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 MAGIC_TRACKPAD2  0x0265  Apple Magic Trackpad 2
 product APPLE MOUSE            0x0301  Mouse M4848
 product APPLE OPTMOUSE         0x0302  Optical mouse
 product APPLE MIGHTYMOUSE      0x0304  Mighty Mouse

Reply via email to