Skip to content

Commit 7a2353a

Browse files
marcanjannau
authored andcommitted
hid: magicmouse: Add MTP multi-touch device support
Apple M2 devices expose the multi-touch device over the HID over DockChannel transport, which we represent as the HOST bus type. The report format is the same, except the legacy mouse header is gone and there is no enable request needed. Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent dcd9c92 commit 7a2353a

1 file changed

Lines changed: 49 additions & 18 deletions

File tree

drivers/hid/hid-magicmouse.c

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
5959
#define MOUSE_REPORT_ID 0x29
6060
#define MOUSE2_REPORT_ID 0x12
6161
#define DOUBLE_REPORT_ID 0xf7
62+
#define SPI_REPORT_ID 0x02
63+
#define MTP_REPORT_ID 0x75
6264
#define USB_BATTERY_TIMEOUT_MS 60000
6365

6466
#define MAX_CONTACTS 16
@@ -584,25 +586,32 @@ struct tp_finger {
584586
} __attribute__((packed, aligned(2)));
585587

586588
/**
587-
* struct trackpad report
589+
* vendor trackpad report
588590
*
589-
* @report_id: reportid
590-
* @buttons: HID Usage Buttons 3 1-bit reports
591591
* @num_fingers: the number of fingers being reported in @fingers
592-
* @clicked: same as @buttons
592+
* @buttons: same as HID buttons
593593
*/
594594
struct tp_header {
595+
// HID vendor part, up to 1751 bytes
596+
u8 unknown[22];
597+
u8 num_fingers;
598+
u8 buttons;
599+
u8 unknown3[14];
600+
};
601+
602+
/**
603+
* standard HID mouse report
604+
*
605+
* @report_id: reportid
606+
* @buttons: HID Usage Buttons 3 1-bit reports
607+
*/
608+
struct tp_mouse_report {
595609
// HID mouse report
596610
u8 report_id;
597611
u8 buttons;
598612
u8 rel_x;
599613
u8 rel_y;
600614
u8 padding[4];
601-
// HID vendor part, up to 1751 bytes
602-
u8 unknown[22];
603-
u8 num_fingers;
604-
u8 clicked;
605-
u8 unknown3[14];
606615
};
607616

608617
static inline int le16_to_int(__le16 x)
@@ -632,7 +641,7 @@ static void report_finger_data(struct input_dev *input, int slot,
632641
input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
633642
}
634643

635-
static int magicmouse_raw_event_spi(struct hid_device *hdev,
644+
static int magicmouse_raw_event_mtp(struct hid_device *hdev,
636645
struct hid_report *report, u8 *data, int size)
637646
{
638647
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
@@ -649,9 +658,6 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
649658
// print_hex_dump_debug("appleft ev: ", DUMP_PREFIX_OFFSET, 16, 1, data,
650659
// size, false);
651660

652-
if (data[0] != TRACKPAD2_USB_REPORT_ID)
653-
return 0;
654-
655661
/* Expect 46 bytes of prefix, and N * 30 bytes of touch data. */
656662
if (size < hdr_sz || ((size - hdr_sz) % touch_sz) != 0)
657663
return 0;
@@ -690,12 +696,26 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
690696
}
691697

692698
input_mt_sync_frame(input);
693-
input_report_key(input, BTN_MOUSE, data[1] & 1);
699+
input_report_key(input, BTN_MOUSE, tp_hdr->buttons & 1);
694700

695701
input_sync(input);
696702
return 1;
697703
}
698704

705+
static int magicmouse_raw_event_spi(struct hid_device *hdev,
706+
struct hid_report *report, u8 *data, int size)
707+
{
708+
const size_t hdr_sz = sizeof(struct tp_mouse_report);
709+
710+
if (size < hdr_sz)
711+
return 0;
712+
713+
if (data[0] != TRACKPAD2_USB_REPORT_ID)
714+
return 0;
715+
716+
return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
717+
}
718+
699719
static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
700720
struct hid_usage *usage, __s32 value)
701721
{
@@ -1089,7 +1109,7 @@ static int magicmouse_probe(struct hid_device *hdev,
10891109
struct hid_report *report;
10901110
int ret;
10911111

1092-
if (id->bus == BUS_SPI && id->vendor == SPI_VENDOR_ID_APPLE &&
1112+
if ((id->bus == BUS_SPI || id->bus == BUS_HOST) && id->vendor == SPI_VENDOR_ID_APPLE &&
10931113
hdev->type != HID_TYPE_SPI_MOUSE)
10941114
return -ENODEV;
10951115

@@ -1101,7 +1121,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11011121

11021122
// internal trackpad use a data format use input ops to avoid
11031123
// conflicts with the report ID.
1104-
if (id->vendor == SPI_VENDOR_ID_APPLE) {
1124+
if (id->bus == BUS_HOST) {
1125+
msc->input_ops.raw_event = magicmouse_raw_event_mtp;
1126+
msc->input_ops.setup_input = magicmouse_setup_input_spi;
1127+
} else if (id->bus == BUS_SPI) {
11051128
msc->input_ops.raw_event = magicmouse_raw_event_spi;
11061129
msc->input_ops.setup_input = magicmouse_setup_input_spi;
11071130

@@ -1161,8 +1184,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11611184
else /* USB_VENDOR_ID_APPLE */
11621185
report = hid_register_report(hdev, HID_INPUT_REPORT,
11631186
TRACKPAD2_USB_REPORT_ID, 0);
1164-
} else if (id->vendor == SPI_VENDOR_ID_APPLE) {
1165-
report = hid_register_report(hdev, HID_INPUT_REPORT, 2, 0);
1187+
} else if (id->bus == BUS_SPI) {
1188+
report = hid_register_report(hdev, HID_INPUT_REPORT, SPI_REPORT_ID, 0);
1189+
} else if (id->bus == BUS_HOST) {
1190+
report = hid_register_report(hdev, HID_INPUT_REPORT, MTP_REPORT_ID, 0);
11661191
} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
11671192
report = hid_register_report(hdev, HID_INPUT_REPORT,
11681193
TRACKPAD_REPORT_ID, 0);
@@ -1177,6 +1202,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11771202
}
11781203
report->size = 6;
11791204

1205+
/* MTP devices do not need the MT enable, this is handled by the MTP driver */
1206+
if (id->bus == BUS_HOST)
1207+
return 0;
1208+
11801209
/*
11811210
* Some devices repond with 'invalid report id' when feature
11821211
* report switching it into multitouch mode is sent to it.
@@ -1264,6 +1293,8 @@ static const struct hid_device_id magic_mice[] = {
12641293
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
12651294
{ HID_SPI_DEVICE(SPI_VENDOR_ID_APPLE, HID_ANY_ID),
12661295
.driver_data = 0 },
1296+
{ HID_DEVICE(BUS_HOST, HID_GROUP_ANY, HOST_VENDOR_ID_APPLE,
1297+
HID_ANY_ID), .driver_data = 0 },
12671298
{ }
12681299
};
12691300
MODULE_DEVICE_TABLE(hid, magic_mice);

0 commit comments

Comments
 (0)