Skip to content

Commit 6c77775

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 4f34280 commit 6c77775

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
@@ -60,6 +60,8 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
6060
#define MOUSE_REPORT_ID 0x29
6161
#define MOUSE2_REPORT_ID 0x12
6262
#define DOUBLE_REPORT_ID 0xf7
63+
#define SPI_REPORT_ID 0x02
64+
#define MTP_REPORT_ID 0x75
6365
#define USB_BATTERY_TIMEOUT_MS 60000
6466

6567
#define MAX_CONTACTS 16
@@ -585,25 +587,32 @@ struct tp_finger {
585587
} __attribute__((packed, aligned(2)));
586588

587589
/**
588-
* struct trackpad report
590+
* vendor trackpad report
589591
*
590-
* @report_id: reportid
591-
* @buttons: HID Usage Buttons 3 1-bit reports
592592
* @num_fingers: the number of fingers being reported in @fingers
593-
* @clicked: same as @buttons
593+
* @buttons: same as HID buttons
594594
*/
595595
struct tp_header {
596+
// HID vendor part, up to 1751 bytes
597+
u8 unknown[22];
598+
u8 num_fingers;
599+
u8 buttons;
600+
u8 unknown3[14];
601+
};
602+
603+
/**
604+
* standard HID mouse report
605+
*
606+
* @report_id: reportid
607+
* @buttons: HID Usage Buttons 3 1-bit reports
608+
*/
609+
struct tp_mouse_report {
596610
// HID mouse report
597611
u8 report_id;
598612
u8 buttons;
599613
u8 rel_x;
600614
u8 rel_y;
601615
u8 padding[4];
602-
// HID vendor part, up to 1751 bytes
603-
u8 unknown[22];
604-
u8 num_fingers;
605-
u8 clicked;
606-
u8 unknown3[14];
607616
};
608617

609618
static inline int le16_to_int(__le16 x)
@@ -633,7 +642,7 @@ static void report_finger_data(struct input_dev *input, int slot,
633642
input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
634643
}
635644

636-
static int magicmouse_raw_event_spi(struct hid_device *hdev,
645+
static int magicmouse_raw_event_mtp(struct hid_device *hdev,
637646
struct hid_report *report, u8 *data, int size)
638647
{
639648
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
@@ -650,9 +659,6 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
650659
// print_hex_dump_debug("appleft ev: ", DUMP_PREFIX_OFFSET, 16, 1, data,
651660
// size, false);
652661

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

693699
input_mt_sync_frame(input);
694-
input_report_key(input, BTN_MOUSE, data[1] & 1);
700+
input_report_key(input, BTN_MOUSE, tp_hdr->buttons & 1);
695701

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

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

1096-
if (id->bus == BUS_SPI && id->vendor == SPI_VENDOR_ID_APPLE &&
1116+
if ((id->bus == BUS_SPI || id->bus == BUS_HOST) && id->vendor == SPI_VENDOR_ID_APPLE &&
10971117
hdev->type != HID_TYPE_SPI_MOUSE)
10981118
return -ENODEV;
10991119

@@ -1105,7 +1125,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11051125

11061126
// internal trackpad use a data format use input ops to avoid
11071127
// conflicts with the report ID.
1108-
if (id->vendor == SPI_VENDOR_ID_APPLE) {
1128+
if (id->bus == BUS_HOST) {
1129+
msc->input_ops.raw_event = magicmouse_raw_event_mtp;
1130+
msc->input_ops.setup_input = magicmouse_setup_input_spi;
1131+
} else if (id->bus == BUS_SPI) {
11091132
msc->input_ops.raw_event = magicmouse_raw_event_spi;
11101133
msc->input_ops.setup_input = magicmouse_setup_input_spi;
11111134

@@ -1165,8 +1188,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11651188
else /* USB_VENDOR_ID_APPLE */
11661189
report = hid_register_report(hdev, HID_INPUT_REPORT,
11671190
TRACKPAD2_USB_REPORT_ID, 0);
1168-
} else if (id->vendor == SPI_VENDOR_ID_APPLE) {
1169-
report = hid_register_report(hdev, HID_INPUT_REPORT, 2, 0);
1191+
} else if (id->bus == BUS_SPI) {
1192+
report = hid_register_report(hdev, HID_INPUT_REPORT, SPI_REPORT_ID, 0);
1193+
} else if (id->bus == BUS_HOST) {
1194+
report = hid_register_report(hdev, HID_INPUT_REPORT, MTP_REPORT_ID, 0);
11701195
} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
11711196
report = hid_register_report(hdev, HID_INPUT_REPORT,
11721197
TRACKPAD_REPORT_ID, 0);
@@ -1181,6 +1206,10 @@ static int magicmouse_probe(struct hid_device *hdev,
11811206
}
11821207
report->size = 6;
11831208

1209+
/* MTP devices do not need the MT enable, this is handled by the MTP driver */
1210+
if (id->bus == BUS_HOST)
1211+
return 0;
1212+
11841213
/*
11851214
* Some devices repond with 'invalid report id' when feature
11861215
* report switching it into multitouch mode is sent to it.
@@ -1268,6 +1297,8 @@ static const struct hid_device_id magic_mice[] = {
12681297
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
12691298
{ HID_SPI_DEVICE(SPI_VENDOR_ID_APPLE, HID_ANY_ID),
12701299
.driver_data = 0 },
1300+
{ HID_DEVICE(BUS_HOST, HID_GROUP_ANY, HOST_VENDOR_ID_APPLE,
1301+
HID_ANY_ID), .driver_data = 0 },
12711302
{ }
12721303
};
12731304
MODULE_DEVICE_TABLE(hid, magic_mice);

0 commit comments

Comments
 (0)