Skip to content

Commit f47a12f

Browse files
AdityaGarg8jannau
authored andcommitted
HID: magicmouse: Add support for trackpads found on T2 Macs
This patch adds support for trackpads found on Macs with the T2 Security Chip. The touch report format differs from other trackpads. It is the same format as type 4 in bcm5974.c Signed-off-by: Aditya Garg <gargaditya08@live.com>
1 parent fb1c12d commit f47a12f

1 file changed

Lines changed: 273 additions & 19 deletions

File tree

drivers/hid/hid-magicmouse.c

Lines changed: 273 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,105 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
118118
#define TRACKPAD2_RES_Y \
119119
((TRACKPAD2_MAX_Y - TRACKPAD2_MIN_Y) / (TRACKPAD2_DIMENSION_Y / 100))
120120

121+
#define J140K_TP_DIMENSION_X (float)12100
122+
#define J140K_TP_MIN_X -5318
123+
#define J140K_TP_MAX_X 5787
124+
#define J140K_TP_RES_X \
125+
((J140K_TP_MAX_X - J140K_TP_MIN_X) / (J140K_TP_DIMENSION_X / 100))
126+
#define J140K_TP_DIMENSION_Y (float)8200
127+
#define J140K_TP_MIN_Y -157
128+
#define J140K_TP_MAX_Y 7102
129+
#define J140K_TP_RES_Y \
130+
((J140K_TP_MAX_Y - J140K_TP_MIN_Y) / (J140K_TP_DIMENSION_Y / 100))
131+
132+
#define J132_TP_DIMENSION_X (float)13500
133+
#define J132_TP_MIN_X -6243
134+
#define J132_TP_MAX_X 6749
135+
#define J132_TP_RES_X \
136+
((J132_TP_MAX_X - J132_TP_MIN_X) / (J132_TP_DIMENSION_X / 100))
137+
#define J132_TP_DIMENSION_Y (float)8400
138+
#define J132_TP_MIN_Y -170
139+
#define J132_TP_MAX_Y 7685
140+
#define J132_TP_RES_Y \
141+
((J132_TP_MAX_Y - J132_TP_MIN_Y) / (J132_TP_DIMENSION_Y / 100))
142+
143+
#define J680_TP_DIMENSION_X (float)16000
144+
#define J680_TP_MIN_X -7456
145+
#define J680_TP_MAX_X 7976
146+
#define J680_TP_RES_X \
147+
((J680_TP_MAX_X - J680_TP_MIN_X) / (J680_TP_DIMENSION_X / 100))
148+
#define J680_TP_DIMENSION_Y (float)10000
149+
#define J680_TP_MIN_Y -163
150+
#define J680_TP_MAX_Y 9283
151+
#define J680_TP_RES_Y \
152+
((J680_TP_MAX_Y - J680_TP_MIN_Y) / (J680_TP_DIMENSION_Y / 100))
153+
154+
#define J680_ALT_TP_DIMENSION_X (float)16000
155+
#define J680_ALT_TP_MIN_X -7456
156+
#define J680_ALT_TP_MAX_X 7976
157+
#define J680_ALT_TP_RES_X \
158+
((J680_ALT_TP_MAX_X - J680_ALT_TP_MIN_X) / (J680_ALT_TP_DIMENSION_X / 100))
159+
#define J680_ALT_TP_DIMENSION_Y (float)10000
160+
#define J680_ALT_TP_MIN_Y -163
161+
#define J680_ALT_TP_MAX_Y 9283
162+
#define J680_ALT_TP_RES_Y \
163+
((J680_ALT_TP_MAX_Y - J680_ALT_TP_MIN_Y) / (J680_ALT_TP_DIMENSION_Y / 100))
164+
165+
#define J213_TP_DIMENSION_X (float)13500
166+
#define J213_TP_MIN_X -6243
167+
#define J213_TP_MAX_X 6749
168+
#define J213_TP_RES_X \
169+
((J213_TP_MAX_X - J213_TP_MIN_X) / (J213_TP_DIMENSION_X / 100))
170+
#define J213_TP_DIMENSION_Y (float)8400
171+
#define J213_TP_MIN_Y -170
172+
#define J213_TP_MAX_Y 7685
173+
#define J213_TP_RES_Y \
174+
((J213_TP_MAX_Y - J213_TP_MIN_Y) / (J213_TP_DIMENSION_Y / 100))
175+
176+
#define J214K_TP_DIMENSION_X (float)13200
177+
#define J214K_TP_MIN_X -6046
178+
#define J214K_TP_MAX_X 6536
179+
#define J214K_TP_RES_X \
180+
((J214K_TP_MAX_X - J214K_TP_MIN_X) / (J214K_TP_DIMENSION_X / 100))
181+
#define J214K_TP_DIMENSION_Y (float)8200
182+
#define J214K_TP_MIN_Y -164
183+
#define J214K_TP_MAX_Y 7439
184+
#define J214K_TP_RES_Y \
185+
((J214K_TP_MAX_Y - J214K_TP_MIN_Y) / (J214K_TP_DIMENSION_Y / 100))
186+
187+
#define J223_TP_DIMENSION_X (float)13200
188+
#define J223_TP_MIN_X -6046
189+
#define J223_TP_MAX_X 6536
190+
#define J223_TP_RES_X \
191+
((J223_TP_MAX_X - J223_TP_MIN_X) / (J223_TP_DIMENSION_X / 100))
192+
#define J223_TP_DIMENSION_Y (float)8200
193+
#define J223_TP_MIN_Y -164
194+
#define J223_TP_MAX_Y 7439
195+
#define J223_TP_RES_Y \
196+
((J223_TP_MAX_Y - J223_TP_MIN_Y) / (J223_TP_DIMENSION_Y / 100))
197+
198+
#define J230K_TP_DIMENSION_X (float)12100
199+
#define J230K_TP_MIN_X -5318
200+
#define J230K_TP_MAX_X 5787
201+
#define J230K_TP_RES_X \
202+
((J230K_TP_MAX_X - J230K_TP_MIN_X) / (J230K_TP_DIMENSION_X / 100))
203+
#define J230K_TP_DIMENSION_Y (float)8200
204+
#define J230K_TP_MIN_Y -157
205+
#define J230K_TP_MAX_Y 7102
206+
#define J230K_TP_RES_Y \
207+
((J230K_TP_MAX_Y - J230K_TP_MIN_Y) / (J230K_TP_DIMENSION_Y / 100))
208+
209+
#define J152F_TP_DIMENSION_X (float)16000
210+
#define J152F_TP_MIN_X -7456
211+
#define J152F_TP_MAX_X 7976
212+
#define J152F_TP_RES_X \
213+
((J152F_TP_MAX_X - J152F_TP_MIN_X) / (J152F_TP_DIMENSION_X / 100))
214+
#define J152F_TP_DIMENSION_Y (float)10000
215+
#define J152F_TP_MIN_Y -163
216+
#define J152F_TP_MAX_Y 9283
217+
#define J152F_TP_RES_Y \
218+
((J152F_TP_MAX_Y - J152F_TP_MIN_Y) / (J152F_TP_DIMENSION_Y / 100))
219+
121220
/* These are fallback values, since the real values will be queried from the device. */
122221
#define J314_TP_DIMENSION_X (float)13000
123222
#define J314_TP_MIN_X -5900
@@ -130,7 +229,11 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
130229
#define J314_TP_RES_Y \
131230
((J314_TP_MAX_Y - J314_TP_MIN_Y) / (J314_TP_DIMENSION_Y / 100))
132231

133-
#define J314_TP_MAX_FINGER_ORIENTATION 16384
232+
#define T2_TOUCHPAD_ENTRY(model) \
233+
{ USB_DEVICE_ID_APPLE_WELLSPRINGT2_##model, model##_TP_MIN_X, model##_TP_MIN_Y, \
234+
model##_TP_MAX_X, model##_TP_MAX_Y, model##_TP_RES_X, model##_TP_RES_Y }
235+
236+
#define INTERNAL_TP_MAX_FINGER_ORIENTATION 16384
134237

135238
struct magicmouse_input_ops {
136239
int (*raw_event)(struct hid_device *hdev,
@@ -733,7 +836,7 @@ static void report_finger_data(struct input_dev *input, int slot,
733836
input_report_abs(input, ABS_MT_WIDTH_MINOR,
734837
le16_to_int(f->tool_minor) << 1);
735838
input_report_abs(input, ABS_MT_ORIENTATION,
736-
J314_TP_MAX_FINGER_ORIENTATION - le16_to_int(f->orientation));
839+
INTERNAL_TP_MAX_FINGER_ORIENTATION - le16_to_int(f->orientation));
737840
input_report_abs(input, ABS_MT_PRESSURE, le16_to_int(f->pressure));
738841
input_report_abs(input, ABS_MT_POSITION_X, pos->x);
739842
input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
@@ -821,6 +924,20 @@ static int magicmouse_raw_event_spi(struct hid_device *hdev,
821924
return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
822925
}
823926

927+
static int magicmouse_raw_event_t2(struct hid_device *hdev,
928+
struct hid_report *report, u8 *data, int size)
929+
{
930+
const size_t hdr_sz = sizeof(struct tp_mouse_report);
931+
932+
if (!size)
933+
return 0;
934+
935+
if (data[0] != TRACKPAD2_USB_REPORT_ID || size < hdr_sz)
936+
return 0;
937+
938+
return magicmouse_raw_event_mtp(hdev, report, data + hdr_sz, size - hdr_sz);
939+
}
940+
824941
static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
825942
struct hid_usage *usage, __s32 value)
826943
{
@@ -1018,8 +1135,32 @@ static int magicmouse_setup_input_usb(struct input_dev *input,
10181135
return 0;
10191136
}
10201137

1021-
static int magicmouse_setup_input_mtp(struct input_dev *input,
1022-
struct hid_device *hdev)
1138+
struct magicmouse_t2_properties {
1139+
u32 id;
1140+
int min_x;
1141+
int min_y;
1142+
int max_x;
1143+
int max_y;
1144+
int res_x;
1145+
int res_y;
1146+
};
1147+
1148+
static const struct magicmouse_t2_properties magicmouse_t2_configs[] = {
1149+
T2_TOUCHPAD_ENTRY(J140K),
1150+
T2_TOUCHPAD_ENTRY(J132),
1151+
T2_TOUCHPAD_ENTRY(J680),
1152+
T2_TOUCHPAD_ENTRY(J680_ALT),
1153+
T2_TOUCHPAD_ENTRY(J213),
1154+
T2_TOUCHPAD_ENTRY(J214K),
1155+
T2_TOUCHPAD_ENTRY(J223),
1156+
T2_TOUCHPAD_ENTRY(J230K),
1157+
T2_TOUCHPAD_ENTRY(J152F),
1158+
};
1159+
1160+
static int magicmouse_setup_input_int_tpd(struct input_dev *input,
1161+
struct hid_device *hdev, int min_x, int min_y,
1162+
int max_x, int max_y, int res_x, int res_y,
1163+
bool query_dimensions)
10231164
{
10241165
int error;
10251166
int mt_flags = 0;
@@ -1060,19 +1201,17 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
10601201
input_abs_set_res(input, ABS_MT_PRESSURE, 1);
10611202

10621203
/* finger orientation */
1063-
input_set_abs_params(input, ABS_MT_ORIENTATION, -J314_TP_MAX_FINGER_ORIENTATION,
1064-
J314_TP_MAX_FINGER_ORIENTATION, 0, 0);
1204+
input_set_abs_params(input, ABS_MT_ORIENTATION, -INTERNAL_TP_MAX_FINGER_ORIENTATION,
1205+
INTERNAL_TP_MAX_FINGER_ORIENTATION, 0, 0);
10651206

10661207
/* finger position */
1067-
input_set_abs_params(input, ABS_MT_POSITION_X, J314_TP_MIN_X, J314_TP_MAX_X,
1068-
0, 0);
1208+
input_set_abs_params(input, ABS_MT_POSITION_X, min_x, max_x, 0, 0);
10691209
/* Y axis is inverted */
1070-
input_set_abs_params(input, ABS_MT_POSITION_Y, -J314_TP_MAX_Y, -J314_TP_MIN_Y,
1071-
0, 0);
1210+
input_set_abs_params(input, ABS_MT_POSITION_Y, -max_y, -min_y, 0, 0);
10721211

10731212
/* X/Y resolution */
1074-
input_abs_set_res(input, ABS_MT_POSITION_X, J314_TP_RES_X);
1075-
input_abs_set_res(input, ABS_MT_POSITION_Y, J314_TP_RES_Y);
1213+
input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
1214+
input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
10761215

10771216
input_set_events_per_packet(input, 60);
10781217

@@ -1099,15 +1238,55 @@ static int magicmouse_setup_input_mtp(struct input_dev *input,
10991238
*/
11001239
input->open = magicmouse_open;
11011240
input->close = magicmouse_close;
1102-
msc->query_dimensions = true;
1241+
msc->query_dimensions = query_dimensions;
1242+
1243+
return 0;
1244+
}
1245+
1246+
static int magicmouse_setup_input_mtp(struct input_dev *input,
1247+
struct hid_device *hdev)
1248+
{
1249+
int ret = magicmouse_setup_input_int_tpd(input, hdev, J314_TP_MIN_X,
1250+
J314_TP_MIN_Y, J314_TP_MAX_X,
1251+
J314_TP_MAX_Y, J314_TP_RES_X,
1252+
J314_TP_RES_Y, true);
1253+
if (ret)
1254+
return ret;
11031255

11041256
return 0;
11051257
}
11061258

11071259
static int magicmouse_setup_input_spi(struct input_dev *input,
11081260
struct hid_device *hdev)
11091261
{
1110-
int ret = magicmouse_setup_input_mtp(input, hdev);
1262+
int ret = magicmouse_setup_input_int_tpd(input, hdev, J314_TP_MIN_X,
1263+
J314_TP_MIN_Y, J314_TP_MAX_X,
1264+
J314_TP_MAX_Y, J314_TP_RES_X,
1265+
J314_TP_RES_Y, true);
1266+
if (ret)
1267+
return ret;
1268+
1269+
return 0;
1270+
}
1271+
1272+
static int magicmouse_setup_input_t2(struct input_dev *input,
1273+
struct hid_device *hdev)
1274+
{
1275+
int min_x, min_y, max_x, max_y, res_x, res_y;
1276+
1277+
for (size_t i = 0; i < ARRAY_SIZE(magicmouse_t2_configs); i++) {
1278+
if (magicmouse_t2_configs[i].id == hdev->product) {
1279+
min_x = magicmouse_t2_configs[i].min_x;
1280+
min_y = magicmouse_t2_configs[i].min_y;
1281+
max_x = magicmouse_t2_configs[i].max_x;
1282+
max_y = magicmouse_t2_configs[i].max_y;
1283+
res_x = magicmouse_t2_configs[i].res_x;
1284+
res_y = magicmouse_t2_configs[i].res_y;
1285+
}
1286+
}
1287+
1288+
int ret = magicmouse_setup_input_int_tpd(input, hdev, min_x, min_y,
1289+
max_x, max_y, res_x, res_y, false);
11111290
if (ret)
11121291
return ret;
11131292

@@ -1180,6 +1359,18 @@ static int magicmouse_enable_multitouch(struct hid_device *hdev)
11801359
feature = feature_mt_trackpad2_usb;
11811360
}
11821361
break;
1362+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
1363+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
1364+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
1365+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
1366+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
1367+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
1368+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
1369+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
1370+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
1371+
feature_size = sizeof(feature_mt_trackpad2_usb);
1372+
feature = feature_mt_trackpad2_usb;
1373+
break;
11831374
case USB_DEVICE_ID_APPLE_MAGICMOUSE2:
11841375
case USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC:
11851376
feature_size = sizeof(feature_mt_mouse2);
@@ -1276,6 +1467,21 @@ static int magicmouse_probe(struct hid_device *hdev,
12761467
hdev->type != HID_TYPE_SPI_MOUSE)
12771468
return -ENODEV;
12781469

1470+
switch (id->product) {
1471+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
1472+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
1473+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
1474+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
1475+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
1476+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
1477+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
1478+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
1479+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
1480+
if (hdev->type != HID_TYPE_USBMOUSE)
1481+
return -ENODEV;
1482+
break;
1483+
}
1484+
12791485
msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
12801486
if (msc == NULL) {
12811487
hid_err(hdev, "can't alloc magicmouse descriptor\n");
@@ -1284,15 +1490,33 @@ static int magicmouse_probe(struct hid_device *hdev,
12841490

12851491
// internal trackpad use a data format use input ops to avoid
12861492
// conflicts with the report ID.
1287-
if (id->bus == BUS_HOST) {
1493+
switch (id->bus) {
1494+
case BUS_HOST:
12881495
msc->input_ops.raw_event = magicmouse_raw_event_mtp;
12891496
msc->input_ops.setup_input = magicmouse_setup_input_mtp;
1290-
} else if (id->bus == BUS_SPI) {
1497+
break;
1498+
case BUS_SPI:
12911499
msc->input_ops.raw_event = magicmouse_raw_event_spi;
12921500
msc->input_ops.setup_input = magicmouse_setup_input_spi;
1293-
} else {
1294-
msc->input_ops.raw_event = magicmouse_raw_event_usb;
1295-
msc->input_ops.setup_input = magicmouse_setup_input_usb;
1501+
break;
1502+
default:
1503+
switch (id->product) {
1504+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
1505+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
1506+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
1507+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
1508+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
1509+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
1510+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
1511+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
1512+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
1513+
msc->input_ops.raw_event = magicmouse_raw_event_t2;
1514+
msc->input_ops.setup_input = magicmouse_setup_input_t2;
1515+
break;
1516+
default:
1517+
msc->input_ops.raw_event = magicmouse_raw_event_usb;
1518+
msc->input_ops.setup_input = magicmouse_setup_input_usb;
1519+
}
12961520
}
12971521

12981522
msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
@@ -1353,6 +1577,18 @@ static int magicmouse_probe(struct hid_device *hdev,
13531577
TRACKPAD2_USB_REPORT_ID, 0);
13541578
}
13551579
break;
1580+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K:
1581+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132:
1582+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680:
1583+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT:
1584+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213:
1585+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K:
1586+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223:
1587+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K:
1588+
case USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F:
1589+
report = hid_register_report(hdev, HID_INPUT_REPORT,
1590+
TRACKPAD2_USB_REPORT_ID, 0);
1591+
break;
13561592
default:
13571593
switch (id->bus) {
13581594
case BUS_HOST:
@@ -1461,6 +1697,24 @@ static const struct hid_device_id magic_mice[] = {
14611697
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
14621698
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
14631699
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
1700+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1701+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K), .driver_data = 0 },
1702+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1703+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132), .driver_data = 0 },
1704+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1705+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680), .driver_data = 0 },
1706+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1707+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680_ALT), .driver_data = 0 },
1708+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1709+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213), .driver_data = 0 },
1710+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1711+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K), .driver_data = 0 },
1712+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1713+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223), .driver_data = 0 },
1714+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1715+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K), .driver_data = 0 },
1716+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1717+
USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F), .driver_data = 0 },
14641718
{ HID_SPI_DEVICE(SPI_VENDOR_ID_APPLE, HID_ANY_ID),
14651719
.driver_data = 0 },
14661720
{ HID_DEVICE(BUS_HOST, HID_GROUP_ANY, HOST_VENDOR_ID_APPLE,

0 commit comments

Comments
 (0)