Skip to content

Commit 1ec5d60

Browse files
Wyborski0day robot
authored andcommitted
input: mouse: bcm5974: Add driver for Apple Magic Trackpad 2
Added support for Apple Magic Trackpad 2 in bcm5974 (MacBook Tochpad) driver. The Magic Trackpad 2 needs to be switched into the finger-reporting-mode, just like the other macbook touchpads as well. But the format is different to the ones before. The Header is 12 Bytes long and each reported finger is additional 9 Bytes. The data order is as well different. The driver currently only supports USB. One option would be to integrate bluetooth support into the bcm driver or to move the driver to the hid-magicmouse which supports bluetooth. I integrated the driver into the bcm and not the magicmouse driver, because this way i was able to compare the outcome with the macbook touchpad as i dont own a magicmouse or a magictrackpad. The patch has been tested by several people with a dkms: https://github.com/robbi5/magictrackpad2-dkms torvalds#332 Signed-off-by: Marek Wyborski <[email protected]>
1 parent 6593813 commit 1ec5d60

File tree

4 files changed

+117
-11
lines changed

4 files changed

+117
-11
lines changed

drivers/hid/hid-apple.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ static const struct hid_device_id apple_devices[] = {
554554
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
555555
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
556556
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
557+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD2),
558+
.driver_data = APPLE_HAS_FN },
557559
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
558560
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
559561
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),

drivers/hid/hid-core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,6 +1842,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
18421842
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) },
18431843
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) },
18441844
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) },
1845+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) },
18451846
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
18461847
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
18471848
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -2576,6 +2577,7 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
25762577
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) },
25772578
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) },
25782579
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) },
2580+
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) },
25792581
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
25802582
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
25812583
{ }

drivers/hid/hid-ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
8787
#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
8888
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e
89+
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 0x0265
8990
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
9091
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f
9192
#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214

drivers/input/mouse/bcm5974.c

Lines changed: 112 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* Copyright (C) 2005 Peter Osterlund ([email protected])
1717
* Copyright (C) 2005 Michael Hanselmann ([email protected])
1818
* Copyright (C) 2006 Nicolas Boichat ([email protected])
19+
* Copyright (C) 2016 Marek Wyborski ([email protected])
1920
*
2021
* This program is free software; you can redistribute it and/or modify
2122
* it under the terms of the GNU General Public License as published by
@@ -96,6 +97,8 @@
9697
#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272
9798
#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273
9899
#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274
100+
/* MagicTrackpad2 (2015) */
101+
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 0x0265
99102

100103
#define BCM5974_DEVICE(prod) { \
101104
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
@@ -161,6 +164,8 @@ static const struct usb_device_id bcm5974_table[] = {
161164
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
162165
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
163166
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
167+
/* MagicTrackpad2 */
168+
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_MAGICTRACKPAD2),
164169
/* Terminating entry */
165170
{}
166171
};
@@ -190,20 +195,23 @@ enum tp_type {
190195
TYPE1, /* plain trackpad */
191196
TYPE2, /* button integrated in trackpad */
192197
TYPE3, /* additional header fields since June 2013 */
193-
TYPE4 /* additional header field for pressure data */
198+
TYPE4, /* additional header field for pressure data */
199+
TYPE5 /* format for magic trackpad 2 */
194200
};
195201

196202
/* trackpad finger data offsets, le16-aligned */
197203
#define HEADER_TYPE1 (13 * sizeof(__le16))
198204
#define HEADER_TYPE2 (15 * sizeof(__le16))
199205
#define HEADER_TYPE3 (19 * sizeof(__le16))
200206
#define HEADER_TYPE4 (23 * sizeof(__le16))
207+
#define HEADER_TYPE5 ( 6 * sizeof(__le16))
201208

202209
/* trackpad button data offsets */
203210
#define BUTTON_TYPE1 0
204211
#define BUTTON_TYPE2 15
205212
#define BUTTON_TYPE3 23
206213
#define BUTTON_TYPE4 31
214+
#define BUTTON_TYPE5 1
207215

208216
/* list of device capability bits */
209217
#define HAS_INTEGRATED_BUTTON 1
@@ -213,18 +221,21 @@ enum tp_type {
213221
#define FSIZE_TYPE2 (14 * sizeof(__le16))
214222
#define FSIZE_TYPE3 (14 * sizeof(__le16))
215223
#define FSIZE_TYPE4 (15 * sizeof(__le16))
224+
#define FSIZE_TYPE5 (9)
216225

217226
/* offset from header to finger struct */
218227
#define DELTA_TYPE1 (0 * sizeof(__le16))
219228
#define DELTA_TYPE2 (0 * sizeof(__le16))
220229
#define DELTA_TYPE3 (0 * sizeof(__le16))
221230
#define DELTA_TYPE4 (1 * sizeof(__le16))
231+
#define DELTA_TYPE5 (0 * sizeof(__le16))
222232

223233
/* usb control message mode switch data */
224234
#define USBMSG_TYPE1 8, 0x300, 0, 0, 0x1, 0x8
225235
#define USBMSG_TYPE2 8, 0x300, 0, 0, 0x1, 0x8
226236
#define USBMSG_TYPE3 8, 0x300, 0, 0, 0x1, 0x8
227237
#define USBMSG_TYPE4 2, 0x302, 2, 1, 0x1, 0x0
238+
#define USBMSG_TYPE5 2, 0x302, 1, 1, 0x1, 0x0
228239

229240
/* Wellspring initialization constants */
230241
#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
@@ -247,6 +258,18 @@ struct tp_finger {
247258
__le16 multi; /* one finger: varies, more fingers: constant */
248259
} __attribute__((packed,aligned(2)));
249260

261+
/* trackpad finger structure for type5 (magic trackpad), le16-aligned */
262+
struct tp_finger_type5 {
263+
u8 abs_x; /* absolute x coodinate */
264+
u8 abs_x_y; /* absolute x,y coodinate */
265+
u8 abs_y[2]; /* absolute y coodinate */
266+
u8 touch_major; /* touch area, major axis */
267+
u8 touch_minor; /* touch area, minor axis */
268+
u8 size; /* tool area, size */
269+
u8 pressure; /* pressure on forcetouch touchpad */
270+
u8 orientation_origin; /* orientation and id */
271+
} __attribute__((packed,aligned(2)));
272+
250273
/* trackpad finger data size, empirically at least ten fingers */
251274
#define MAX_FINGERS 16
252275
#define MAX_FINGER_ORIENTATION 16384
@@ -497,6 +520,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
497520
{ SN_COORD, -203, 6803 },
498521
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
499522
},
523+
{
524+
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2,
525+
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2,
526+
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2,
527+
HAS_INTEGRATED_BUTTON,
528+
0, sizeof(struct bt_data),
529+
0x83, DATAFORMAT(TYPE5),
530+
{ SN_PRESSURE, 0, 300 },
531+
{ SN_WIDTH, 0, 2048 },
532+
{ SN_COORD, -3678, 3934 },
533+
{ SN_COORD, -2479, 2586 },
534+
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
535+
},
500536
{}
501537
};
502538

@@ -539,9 +575,13 @@ static void setup_events_to_report(struct input_dev *input_dev,
539575
/* finger touch area */
540576
set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w);
541577
set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w);
578+
542579
/* finger approach area */
543-
set_abs(input_dev, ABS_MT_WIDTH_MAJOR, &cfg->w);
544-
set_abs(input_dev, ABS_MT_WIDTH_MINOR, &cfg->w);
580+
if (cfg->tp_type != TYPE5) {
581+
set_abs(input_dev, ABS_MT_WIDTH_MAJOR, &cfg->w);
582+
set_abs(input_dev, ABS_MT_WIDTH_MINOR, &cfg->w);
583+
}
584+
545585
/* finger orientation */
546586
set_abs(input_dev, ABS_MT_ORIENTATION, &cfg->o);
547587
/* finger position */
@@ -596,6 +636,23 @@ static void report_finger_data(struct input_dev *input, int slot,
596636
input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
597637
}
598638

639+
static void report_finger_data_type5(struct input_dev *input, int slot,
640+
const struct input_mt_pos *pos,
641+
const struct tp_finger_type5 *f)
642+
{
643+
input_mt_slot(input, slot);
644+
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
645+
646+
input_report_abs(input, ABS_MT_TOUCH_MAJOR,
647+
raw2int(f->touch_major) << 2);
648+
input_report_abs(input, ABS_MT_TOUCH_MINOR,
649+
raw2int(f->touch_minor) << 2);
650+
input_report_abs(input, ABS_MT_ORIENTATION,
651+
MAX_FINGER_ORIENTATION - ((f->orientation_origin & 0xf0) << 6));
652+
input_report_abs(input, ABS_MT_POSITION_X, pos->x << 1);
653+
input_report_abs(input, ABS_MT_POSITION_Y, pos->y << 1);
654+
}
655+
599656
static void report_synaptics_data(struct input_dev *input,
600657
const struct bcm5974_config *cfg,
601658
const struct tp_finger *f, int raw_n)
@@ -615,11 +672,31 @@ static void report_synaptics_data(struct input_dev *input,
615672
input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
616673
}
617674

675+
static void report_synaptics_data_type5(struct input_dev *input,
676+
const struct bcm5974_config *cfg,
677+
const struct tp_finger_type5 *f, int raw_n)
678+
{
679+
int abs_p = 0, abs_w = 0;
680+
681+
if (raw_n) {
682+
int p = f->pressure;
683+
int w = f->size;
684+
if (p && w) {
685+
abs_p = p;
686+
abs_w = w;
687+
}
688+
}
689+
690+
input_report_abs(input, ABS_PRESSURE, abs_p);
691+
input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
692+
}
693+
618694
/* report trackpad data as logical trackpad state */
619695
static int report_tp_state(struct bcm5974 *dev, int size)
620696
{
621697
const struct bcm5974_config *c = &dev->cfg;
622698
const struct tp_finger *f;
699+
const struct tp_finger_type5 *f_type5;
623700
struct input_dev *input = dev->input;
624701
int raw_n, i, n = 0;
625702

@@ -629,23 +706,47 @@ static int report_tp_state(struct bcm5974 *dev, int size)
629706
raw_n = (size - c->tp_header) / c->tp_fsize;
630707

631708
for (i = 0; i < raw_n; i++) {
709+
632710
f = get_tp_finger(dev, i);
633-
if (raw2int(f->touch_major) == 0)
634-
continue;
635-
dev->pos[n].x = raw2int(f->abs_x);
636-
dev->pos[n].y = c->y.min + c->y.max - raw2int(f->abs_y);
711+
712+
if (c->tp_type != TYPE5) {
713+
if (raw2int(f->touch_major) == 0)
714+
continue;
715+
dev->pos[n].x = raw2int(f->abs_x);
716+
dev->pos[n].y = c->y.min + c->y.max - raw2int(f->abs_y);
717+
}
718+
else {
719+
u16 tmp_x;
720+
u32 tmp_y;
721+
f_type5 = (const struct tp_finger_type5*) f;
722+
if (f_type5->pressure == 0)
723+
continue;
724+
tmp_x = le16_to_cpu(*((__le16*)f_type5)) & 0x1fff;
725+
dev->pos[n].x = (s16) (tmp_x << 3) >> 3;
726+
tmp_y = (s32) le32_to_cpu(*((__le32*)f_type5));
727+
dev->pos[n].y = -(s32) (tmp_y << 6) >> 19;
728+
}
637729
dev->index[n++] = f;
638730
}
639731

640732
input_mt_assign_slots(input, dev->slots, dev->pos, n, 0);
641733

642-
for (i = 0; i < n; i++)
643-
report_finger_data(input, dev->slots[i],
644-
&dev->pos[i], dev->index[i]);
734+
for (i = 0; i < n; i++) {
735+
if (c->tp_type != TYPE5)
736+
report_finger_data(input, dev->slots[i],
737+
&dev->pos[i], dev->index[i]);
738+
else
739+
report_finger_data_type5(input, dev->slots[i], &dev->pos[i],
740+
(const struct tp_finger_type5 *) dev->index[i]);
741+
}
645742

646743
input_mt_sync_frame(input);
647744

648-
report_synaptics_data(input, c, get_tp_finger(dev, 0), raw_n);
745+
if (c->tp_type != TYPE5)
746+
report_synaptics_data(input, c, get_tp_finger(dev, 0), raw_n);
747+
else
748+
report_synaptics_data_type5(input, c,
749+
(const struct tp_finger_type5*) get_tp_finger(dev, 0), raw_n);
649750

650751
/* later types report button events via integrated button only */
651752
if (c->caps & HAS_INTEGRATED_BUTTON) {

0 commit comments

Comments
 (0)