Download raw body.
Help with backport support of Apple MagicTracpad 2
Dear tech@,
I need help with backporting support of Apple MagicTracpad 2.
As a base implementation I've used code from FreeBSD [1] which seems quite
trivial.
Anyway, a naive reimplementation doesn't work. When I attach the device I
have inside dmesg:
uhidev0 at uhub0 port 1 configuration 1 interface 0 "Apple Inc. Magic Trackpad" rev 2.00/8.60 addr 4
uhidev0: iclass 3/0, 224 report ids
uhid0 at uhidev0 reportid 144: input=2, output=0, feature=0
uhid1 at uhidev0 reportid 154: input=1, output=0, feature=0
uhid2 at uhidev0 reportid 224: input=4, output=0, feature=0
ubcmtp0 at uhub0 port 1 configuration 1 interface 1 "Apple Inc. Magic Trackpad" rev 2.00/8.60 addr 4
ubcmtp0: attached to 0x5ac/0x265 type 5
wsmouse4 at ubcmtp0
ubcmtp0: ubcmtp_raw_mode: failed to toggle raw mode
ubcmtp0: failed to enter raw mode
attach error=1
uhidev1 at uhub0 port 1 configuration 1 interface 3 "Apple Inc. Magic Trackpad" rev 2.00/8.60 addr 4
uhidev1: iclass 3/0, 192 report ids
uhid3 at uhidev1 reportid 192: input=107, output=0, feature=0
uhid0 detached
uhid1 detached
uhid2 detached
uhidev0 detached
wsmouse4 detached
ubcmtp0 detached
uhid3 detached
uhidev1 detached
that means that it can't enter into raw mode.
So, I deffently had missed something.
Footnotes:
[1] https://github.com/freebsd/freebsd-src/commit/ef8397c28e981e0115d435aabcf57cee7ea5f5ee
--
wbr, Kirill
diff --git sys/dev/usb/ubcmtp.c sys/dev/usb/ubcmtp.c
index fd53f52281b..a502c87a39c 100644
--- sys/dev/usb/ubcmtp.c
+++ sys/dev/usb/ubcmtp.c
@@ -78,9 +78,32 @@ struct ubcmtp_finger {
uint16_t multi;
} __packed __attribute((aligned(2)));
+struct ubcmtp_finger_compact {
+ uint32_t coords;
+ 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 __attribute((aligned(2)));
+
+union ubcmtp_finger_compact_coords {
+ uint32_t num;
+ struct {
+ signed int x: 13;
+ signed int y: 13;
+ signed int _unknown: 4;
+ signed int state: 2;
+ } __packed __attribute((aligned(2)));
+};
+
#define UBCMTP_MAX_FINGERS 16
#define UBCMTP_ALL_FINGER_SIZE (UBCMTP_MAX_FINGERS * sizeof(struct ubcmtp_finger))
+#define UBCMTP_COMPACT_FINGER_SIZE (UBCMTP_MAX_FINGERS * sizeof(struct ubcmtp_finger_compact))
+
#define UBCMTP_TYPE1 1
#define UBCMTP_TYPE1_TPOFF (13 * sizeof(uint16_t))
#define UBCMTP_TYPE1_TPLEN UBCMTP_TYPE1_TPOFF + UBCMTP_ALL_FINGER_SIZE
@@ -106,6 +129,13 @@ struct ubcmtp_finger {
#define UBCMTP_TYPE4_BTOFF 31
#define UBCMTP_TYPE4_FINGERPAD (1 * sizeof(uint16_t))
+// TODO: ???
+#define UBCMTP_TYPE_MT2U 5
+#define UBCMTP_TYPE_MT2U_TPOFF 12
+#define UBCMTP_TYPE_MT2U_TPLEN UBCMTP_TYPE_MT2U_TPOFF + UBCMTP_COMPACT_FINGER_SIZE
+#define UBCMTP_TYPE_MT2U_TPIFACE 2
+#define UBCMTP_TYPE_MT2U_BTOFF 1
+
#define UBCMTP_FINGER_ORIENT 16384
#define UBCMTP_SN_PRESSURE 45
#define UBCMTP_SN_WIDTH 25
@@ -307,6 +337,18 @@ static const struct ubcmtp_dev ubcmtp_devices[] = {
{ UBCMTP_SN_COORD, -203, 6803 },
{ UBCMTP_SN_ORIENT, -UBCMTP_FINGER_ORIENT, UBCMTP_FINGER_ORIENT },
},
+ {
+ USB_VENDOR_APPLE,
+ USB_PRODUCT_APPLE_MAGIC_TRACKPAD2,
+ USB_PRODUCT_APPLE_MAGIC_TRACKPAD2,
+ USB_PRODUCT_APPLE_MAGIC_TRACKPAD2,
+ UBCMTP_TYPE_MT2U,
+ { UBCMTP_SN_PRESSURE, 0, 256 },
+ { UBCMTP_SN_WIDTH, 0, 2048 },
+ { UBCMTP_SN_COORD, -3678, 3934 },
+ { UBCMTP_SN_COORD, -2478, 2587 },
+ { UBCMTP_SN_ORIENT, -UBCMTP_FINGER_ORIENT, UBCMTP_FINGER_ORIENT },
+ },
};
static struct wsmouse_param ubcmtp_wsmousecfg[] = {
@@ -481,6 +523,13 @@ ubcmtp_attach(struct device *parent, struct device *self, void *aux)
sc->tp_fingerpad = UBCMTP_TYPE4_FINGERPAD;
usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE4_TPIFACE);
break;
+
+ case UBCMTP_TYPE_MT2U:
+ sc->tp_maxlen = UBCMTP_TYPE_MT2U_TPLEN;
+ sc->tp_offset = UBCMTP_TYPE_MT2U_TPOFF;
+ sc->sc_tp_iface = uaa->ifaces[UBCMTP_TYPE_MT2U_TPIFACE];
+ usbd_claim_iface(sc->sc_udev, UBCMTP_TYPE_MT2U_TPIFACE);
+ break;
}
a.accessops = &ubcmtp_accessops;
@@ -531,7 +580,9 @@ ubcmtp_configure(struct ubcmtp_softc *sc)
hw->y_min = sc->dev_type->l_y.min;
hw->y_max = sc->dev_type->l_y.max;
hw->mt_slots = UBCMTP_MAX_FINGERS;
- hw->flags = WSMOUSEHW_MT_TRACKING;
+ // TODO: ???
+ if (sc->dev_type->type != UBCMTP_TYPE_MT2U)
+ hw->flags = WSMOUSEHW_MT_TRACKING;
return wsmouse_configure(sc->sc_wsmousedev,
ubcmtp_wsmousecfg, nitems(ubcmtp_wsmousecfg));
@@ -651,6 +702,12 @@ ubcmtp_raw_mode(struct ubcmtp_softc *sc, int enable)
if (sc->dev_type->type == UBCMTP_TYPE3)
return (0);
+ if (sc->dev_type->type == UBCMTP_TYPE_MT2U) {
+ buf[0] = 2;
+ goto bypass_read;
+ }
+
r.bRequest = UR_GET_REPORT;
r.bmRequestType = UT_READ_CLASS_INTERFACE;
if (sc->dev_type->type < UBCMTP_TYPE4) {
@@ -670,6 +727,7 @@ ubcmtp_raw_mode(struct ubcmtp_softc *sc, int enable)
return (err);
}
+bypass_read:
/* toggle magic byte and write everything back */
if (sc->dev_type->type < UBCMTP_TYPE4)
buf[0] = (enable ? UBCMTP_WELLSPRING_MODE_RAW :
@@ -779,6 +837,8 @@ ubcmtp_tp_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
{
struct ubcmtp_softc *sc = priv;
struct ubcmtp_finger *finger;
+ struct ubcmtp_finger_compact *compact_finger;
+ union ubcmtp_finger_compact_coords compact_finger_coords;
u_int32_t pktlen;
int off, s, btn, contacts = 0;
@@ -802,6 +862,28 @@ ubcmtp_tp_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
return;
contacts = 0;
+
+ /* Magic Trackpad 2 has so-called compact report */
+ if (sc->dev_type->type == UBCMTP_TYPE_MT2U) {
+ for (off = sc->tp_offset; off < pktlen;
+ off += (sizeof(struct ubcmtp_finger_compact) + sc->tp_fingerpad)) {
+ compact_finger = (struct ubcmtp_finger_compact *)(sc->tp_pkt + off);
+
+ if (letoh32(compact_finger->touch_major) == 0)
+ continue; /* finger lifted */
+
+ compact_finger_coords.num = letoh32(compact_finger->coords);
+
+ sc->frame[contacts].x = compact_finger_coords.x;
+ sc->frame[contacts].y = sc->dev_type->l_y.min
+ + sc->dev_type->l_y.max- compact_finger_coords.y;
+ sc->frame[contacts].pressure = DEFAULT_PRESSURE;
+ contacts++;
+ }
+
+ goto done;
+ }
+
for (off = sc->tp_offset; off < pktlen;
off += (sizeof(struct ubcmtp_finger) + sc->tp_fingerpad)) {
finger = (struct ubcmtp_finger *)(sc->tp_pkt + off);
@@ -815,6 +897,8 @@ ubcmtp_tp_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
contacts++;
}
+done:
+
btn = sc->btn;
if (sc->dev_type->type == UBCMTP_TYPE2)
sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE2_BTOFF]));
@@ -822,6 +906,8 @@ ubcmtp_tp_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE3_BTOFF]));
else if (sc->dev_type->type == UBCMTP_TYPE4)
sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE4_BTOFF]));
+ else if (sc->dev_type->type == UBCMTP_TYPE_MT2U)
+ sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE_MT2U_BTOFF]));
if (contacts || sc->contacts || sc->btn != btn) {
sc->contacts = contacts;
diff --git sys/dev/usb/usbdevs sys/dev/usb/usbdevs
index 40346863f84..20ccd15b7c3 100644
--- sys/dev/usb/usbdevs
+++ sys/dev/usb/usbdevs
@@ -998,6 +998,7 @@ product APPLE WELLSPRING7A_JIS 0x025b Keyboard/Trackpad
product APPLE WELLSPRING7_ANSI 0x0262 Keyboard/Trackpad
product APPLE WELLSPRING7_ISO 0x0263 Keyboard/Trackpad
product APPLE WELLSPRING7_JIS 0x0264 Keyboard/Trackpad
+product APPLE MAGIC_TRACKPAD2 0x0265 Apple Magic Trackpad 2
product APPLE WELLSPRING9_ANSI 0x0272 Keyboard/Trackpad
product APPLE WELLSPRING9_ISO 0x0273 Keyboard/Trackpad
product APPLE WELLSPRING9_JIS 0x0274 Keyboard/Trackpad
diff --git sys/dev/usb/usbdevs.h sys/dev/usb/usbdevs.h
index 9a7e68f213b..1b0eaa35cc3 100644
--- sys/dev/usb/usbdevs.h
+++ sys/dev/usb/usbdevs.h
@@ -1005,6 +1005,7 @@
#define USB_PRODUCT_APPLE_WELLSPRING7_ANSI 0x0262 /* Keyboard/Trackpad */
#define USB_PRODUCT_APPLE_WELLSPRING7_ISO 0x0263 /* Keyboard/Trackpad */
#define USB_PRODUCT_APPLE_WELLSPRING7_JIS 0x0264 /* Keyboard/Trackpad */
+#define USB_PRODUCT_APPLE_MAGIC_TRACKPAD2 0x0265 /* Apple Magic Trackpad 2 */
#define USB_PRODUCT_APPLE_WELLSPRING9_ANSI 0x0272 /* Keyboard/Trackpad */
#define USB_PRODUCT_APPLE_WELLSPRING9_ISO 0x0273 /* Keyboard/Trackpad */
#define USB_PRODUCT_APPLE_WELLSPRING9_JIS 0x0274 /* Keyboard/Trackpad */
diff --git sys/dev/usb/usbdevs_data.h sys/dev/usb/usbdevs_data.h
index 3cf210c7e8d..93ee045aa03 100644
--- sys/dev/usb/usbdevs_data.h
+++ sys/dev/usb/usbdevs_data.h
@@ -901,6 +901,10 @@ const struct usb_known_product usb_known_products[] = {
USB_VENDOR_APPLE, USB_PRODUCT_APPLE_WELLSPRING7_JIS,
"Keyboard/Trackpad",
},
+ {
+ USB_VENDOR_APPLE, USB_PRODUCT_APPLE_MAGIC_TRACKPAD2,
+ "Apple Magic Trackpad 2",
+ },
{
USB_VENDOR_APPLE, USB_PRODUCT_APPLE_WELLSPRING9_ANSI,
"Keyboard/Trackpad",
Help with backport support of Apple MagicTracpad 2