Skip to content

Commit c45d7d4

Browse files
committed
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 <[email protected]>
1 parent 04624f1 commit c45d7d4

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
@@ -570,25 +572,32 @@ struct tp_finger {
570572
} __attribute__((packed, aligned(2)));
571573

572574
/**
573-
* struct trackpad report
575+
* vendor trackpad report
574576
*
575-
* @report_id: reportid
576-
* @buttons: HID Usage Buttons 3 1-bit reports
577577
* @num_fingers: the number of fingers being reported in @fingers
578-
* @clicked: same as @buttons
578+
* @buttons: same as HID buttons
579579
*/
580580
struct tp_header {
581+
// HID vendor part, up to 1751 bytes
582+
u8 unknown[22];
583+
u8 num_fingers;
584+
u8 buttons;
585+
u8 unknown3[14];
586+
};
587+
588+
/**
589+
* standard HID mouse report
590+
*
591+
* @report_id: reportid
592+
* @buttons: HID Usage Buttons 3 1-bit reports
593+
*/
594+
struct tp_mouse_report {
581595
// HID mouse report
582596
u8 report_id;
583597
u8 buttons;
584598
u8 rel_x;
585599
u8 rel_y;
586600
u8 padding[4];
587-
// HID vendor part, up to 1751 bytes
588-
u8 unknown[22];
589-
u8 num_fingers;
590-
u8 clicked;
591-
u8 unknown3[14];
592601
};
593602

594603
static inline int le16_to_int(__le16 x)
@@ -618,7 +627,7 @@ static void report_finger_data(struct input_dev *input, int slot,
618627
input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
619628
}
620629

621-
static int magicmouse_raw_event_spi(struct hid_device *hdev,
630+
static int magicmouse_raw_event_mtp(struct hid_device *hdev,
622631
struct hid_report *report, u8 *data, int size)
623632
{
624633
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
@@ -635,9 +644,6 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
635644
// print_hex_dump_debug("appleft ev: ", DUMP_PREFIX_OFFSET, 16, 1, data,
636645
// size, false);
637646

638-
if (data[0] != TRACKPAD2_USB_REPORT_ID)
639-
return 0;
640-
641647
/* Expect 46 bytes of prefix, and N * 30 bytes of touch data. */
642648
if (size < hdr_sz || ((size - hdr_sz) % touch_sz) != 0)
643649
return 0;
@@ -676,12 +682,26 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
676682
}
677683

678684
input_mt_sync_frame(input);
679-
input_report_key(input, BTN_MOUSE, data[1] & 1);
685+
input_report_key(input, BTN_MOUSE, tp_hdr->buttons & 1);
680686

681687
input_sync(input);
682688
return 1;
683689
}
684690

691+
static int magicmouse_raw_event_spi(struct hid_device *hdev,
692+
struct hid_report *report, u8 *data, int size)
693+
{
694+
const size_t hdr_sz = sizeof(struct tp_mouse_report);
695+
696+
if (size < hdr_sz)
697+
return 0;
698+
699+
if (data[0] != TRACKPAD2_USB_REPORT_ID)
700+
return 0;
701+
702+
return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
703+
}
704+
685705
static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
686706
struct hid_usage *usage, __s32 value)
687707
{
@@ -1066,7 +1086,7 @@ static int magicmouse_probe(struct hid_device *hdev,
10661086
struct hid_report *report;
10671087
int ret;
10681088

1069-
if (id->bus == BUS_SPI && id->vendor == SPI_VENDOR_ID_APPLE &&
1089+
if ((id->bus == BUS_SPI || id->bus == BUS_HOST) && id->vendor == SPI_VENDOR_ID_APPLE &&
10701090
hdev->type != HID_TYPE_SPI_MOUSE)
10711091
return -ENODEV;
10721092

@@ -1078,7 +1098,10 @@ static int magicmouse_probe(struct hid_device *hdev,
10781098

10791099
// internal trackpad use a data format use input ops to avoid
10801100
// conflicts with the report ID.
1081-
if (id->vendor == SPI_VENDOR_ID_APPLE) {
1101+
if (id->bus == BUS_HOST) {
1102+
msc->input_ops.raw_event = magicmouse_raw_event_mtp;
1103+
msc->input_ops.setup_input = magicmouse_setup_input_spi;
1104+
} else if (id->bus == BUS_SPI) {
10821105
msc->input_ops.raw_event = magicmouse_raw_event_spi;
10831106
msc->input_ops.setup_input = magicmouse_setup_input_spi;
10841107

@@ -1135,8 +1158,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11351158
else /* USB_VENDOR_ID_APPLE */
11361159
report = hid_register_report(hdev, HID_INPUT_REPORT,
11371160
TRACKPAD2_USB_REPORT_ID, 0);
1138-
} else if (id->vendor == SPI_VENDOR_ID_APPLE) {
1139-
report = hid_register_report(hdev, HID_INPUT_REPORT, 2, 0);
1161+
} else if (id->bus == BUS_SPI) {
1162+
report = hid_register_report(hdev, HID_INPUT_REPORT, SPI_REPORT_ID, 0);
1163+
} else if (id->bus == BUS_HOST) {
1164+
report = hid_register_report(hdev, HID_INPUT_REPORT, MTP_REPORT_ID, 0);
11401165
} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
11411166
report = hid_register_report(hdev, HID_INPUT_REPORT,
11421167
TRACKPAD_REPORT_ID, 0);
@@ -1151,6 +1176,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11511176
}
11521177
report->size = 6;
11531178

1179+
/* MTP devices do not need the MT enable, this is handled by the MTP driver */
1180+
if (id->bus == BUS_HOST)
1181+
return 0;
1182+
11541183
/*
11551184
* Some devices repond with 'invalid report id' when feature
11561185
* report switching it into multitouch mode is sent to it.
@@ -1233,6 +1262,8 @@ static const struct hid_device_id magic_mice[] = {
12331262
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2), .driver_data = 0 },
12341263
{ HID_SPI_DEVICE(SPI_VENDOR_ID_APPLE, HID_ANY_ID),
12351264
.driver_data = 0 },
1265+
{ HID_DEVICE(BUS_HOST, HID_GROUP_ANY, HOST_VENDOR_ID_APPLE,
1266+
HID_ANY_ID), .driver_data = 0 },
12361267
{ }
12371268
};
12381269
MODULE_DEVICE_TABLE(hid, magic_mice);

0 commit comments

Comments
 (0)