Skip to content

Commit a7d2964

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 61c7d97 commit a7d2964

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
@@ -573,25 +575,32 @@ struct tp_finger {
573575
} __attribute__((packed, aligned(2)));
574576

575577
/**
576-
* struct trackpad report
578+
* vendor trackpad report
577579
*
578-
* @report_id: reportid
579-
* @buttons: HID Usage Buttons 3 1-bit reports
580580
* @num_fingers: the number of fingers being reported in @fingers
581-
* @clicked: same as @buttons
581+
* @buttons: same as HID buttons
582582
*/
583583
struct tp_header {
584+
// HID vendor part, up to 1751 bytes
585+
u8 unknown[22];
586+
u8 num_fingers;
587+
u8 buttons;
588+
u8 unknown3[14];
589+
};
590+
591+
/**
592+
* standard HID mouse report
593+
*
594+
* @report_id: reportid
595+
* @buttons: HID Usage Buttons 3 1-bit reports
596+
*/
597+
struct tp_mouse_report {
584598
// HID mouse report
585599
u8 report_id;
586600
u8 buttons;
587601
u8 rel_x;
588602
u8 rel_y;
589603
u8 padding[4];
590-
// HID vendor part, up to 1751 bytes
591-
u8 unknown[22];
592-
u8 num_fingers;
593-
u8 clicked;
594-
u8 unknown3[14];
595604
};
596605

597606
static inline int le16_to_int(__le16 x)
@@ -621,7 +630,7 @@ static void report_finger_data(struct input_dev *input, int slot,
621630
input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
622631
}
623632

624-
static int magicmouse_raw_event_spi(struct hid_device *hdev,
633+
static int magicmouse_raw_event_mtp(struct hid_device *hdev,
625634
struct hid_report *report, u8 *data, int size)
626635
{
627636
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
@@ -638,9 +647,6 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
638647
// print_hex_dump_debug("appleft ev: ", DUMP_PREFIX_OFFSET, 16, 1, data,
639648
// size, false);
640649

641-
if (data[0] != TRACKPAD2_USB_REPORT_ID)
642-
return 0;
643-
644650
/* Expect 46 bytes of prefix, and N * 30 bytes of touch data. */
645651
if (size < hdr_sz || ((size - hdr_sz) % touch_sz) != 0)
646652
return 0;
@@ -679,12 +685,26 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
679685
}
680686

681687
input_mt_sync_frame(input);
682-
input_report_key(input, BTN_MOUSE, data[1] & 1);
688+
input_report_key(input, BTN_MOUSE, tp_hdr->buttons & 1);
683689

684690
input_sync(input);
685691
return 1;
686692
}
687693

694+
static int magicmouse_raw_event_spi(struct hid_device *hdev,
695+
struct hid_report *report, u8 *data, int size)
696+
{
697+
const size_t hdr_sz = sizeof(struct tp_mouse_report);
698+
699+
if (size < hdr_sz)
700+
return 0;
701+
702+
if (data[0] != TRACKPAD2_USB_REPORT_ID)
703+
return 0;
704+
705+
return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
706+
}
707+
688708
static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
689709
struct hid_usage *usage, __s32 value)
690710
{
@@ -1069,7 +1089,7 @@ static int magicmouse_probe(struct hid_device *hdev,
10691089
struct hid_report *report;
10701090
int ret;
10711091

1072-
if (id->bus == BUS_SPI && id->vendor == SPI_VENDOR_ID_APPLE &&
1092+
if ((id->bus == BUS_SPI || id->bus == BUS_HOST) && id->vendor == SPI_VENDOR_ID_APPLE &&
10731093
hdev->type != HID_TYPE_SPI_MOUSE)
10741094
return -ENODEV;
10751095

@@ -1081,7 +1101,10 @@ static int magicmouse_probe(struct hid_device *hdev,
10811101

10821102
// internal trackpad use a data format use input ops to avoid
10831103
// conflicts with the report ID.
1084-
if (id->vendor == SPI_VENDOR_ID_APPLE) {
1104+
if (id->bus == BUS_HOST) {
1105+
msc->input_ops.raw_event = magicmouse_raw_event_mtp;
1106+
msc->input_ops.setup_input = magicmouse_setup_input_spi;
1107+
} else if (id->bus == BUS_SPI) {
10851108
msc->input_ops.raw_event = magicmouse_raw_event_spi;
10861109
msc->input_ops.setup_input = magicmouse_setup_input_spi;
10871110

@@ -1138,8 +1161,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11381161
else /* USB_VENDOR_ID_APPLE */
11391162
report = hid_register_report(hdev, HID_INPUT_REPORT,
11401163
TRACKPAD2_USB_REPORT_ID, 0);
1141-
} else if (id->vendor == SPI_VENDOR_ID_APPLE) {
1142-
report = hid_register_report(hdev, HID_INPUT_REPORT, 2, 0);
1164+
} else if (id->bus == BUS_SPI) {
1165+
report = hid_register_report(hdev, HID_INPUT_REPORT, SPI_REPORT_ID, 0);
1166+
} else if (id->bus == BUS_HOST) {
1167+
report = hid_register_report(hdev, HID_INPUT_REPORT, MTP_REPORT_ID, 0);
11431168
} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
11441169
report = hid_register_report(hdev, HID_INPUT_REPORT,
11451170
TRACKPAD_REPORT_ID, 0);
@@ -1154,6 +1179,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11541179
}
11551180
report->size = 6;
11561181

1182+
/* MTP devices do not need the MT enable, this is handled by the MTP driver */
1183+
if (id->bus == BUS_HOST)
1184+
return 0;
1185+
11571186
/*
11581187
* Some devices repond with 'invalid report id' when feature
11591188
* report switching it into multitouch mode is sent to it.
@@ -1236,6 +1265,8 @@ static const struct hid_device_id magic_mice[] = {
12361265
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2), .driver_data = 0 },
12371266
{ HID_SPI_DEVICE(SPI_VENDOR_ID_APPLE, HID_ANY_ID),
12381267
.driver_data = 0 },
1268+
{ HID_DEVICE(BUS_HOST, HID_GROUP_ANY, HOST_VENDOR_ID_APPLE,
1269+
HID_ANY_ID), .driver_data = 0 },
12391270
{ }
12401271
};
12411272
MODULE_DEVICE_TABLE(hid, magic_mice);

0 commit comments

Comments
 (0)