1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2012 Huang Wen Hui
5 * Copyright (c) 2021 Vladimir Kondratyev <[email protected]>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/endian.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/sysctl.h>
38 #include <sys/systm.h>
39
40 #include <dev/evdev/input.h>
41 #include <dev/evdev/evdev.h>
42
43 #define HID_DEBUG_VAR bcm5974_debug
44 #include <dev/hid/hid.h>
45 #include <dev/hid/hidbus.h>
46 #include <dev/hid/hidquirk.h>
47
48 #include <dev/usb/usb.h>
49 #include <dev/usb/usbdi.h>
50 #include <dev/usb/usbhid.h>
51 #include <dev/usb/usb_ioctl.h>
52
53 #include "usbdevs.h"
54
55 #define BCM5974_BUFFER_MAX (246 * 2) /* 2 Type4 SPI frames */
56 #define BCM5974_TLC_PAGE HUP_GENERIC_DESKTOP
57 #define BCM5974_TLC_USAGE HUG_MOUSE
58
59 /* magic to switch device from HID (default) mode into raw */
60 /* Type1 & Type2 trackpads */
61 #define BCM5974_USB_IFACE_INDEX 0
62 #define BCM5974_USB_REPORT_LEN 8
63 #define BCM5974_USB_REPORT_ID 0
64 #define BCM5974_USB_MODE_RAW 0x01
65 #define BCM5974_USB_MODE_HID 0x08
66 /* Type4 trackpads */
67 #define BCM5974_HID_REPORT_LEN 2
68 #define BCM5974_HID_REPORT_ID 2
69 #define BCM5974_HID_MODE_RAW 0x01
70 #define BCM5974_HID_MODE_HID 0x00
71
72 /* Tunables */
73 static SYSCTL_NODE(_hw_hid, OID_AUTO, bcm5974, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
74 "HID wellspring touchpad");
75
76 #ifdef HID_DEBUG
77 enum wsp_log_level {
78 BCM5974_LLEVEL_DISABLED = 0,
79 BCM5974_LLEVEL_ERROR,
80 BCM5974_LLEVEL_DEBUG, /* for troubleshooting */
81 BCM5974_LLEVEL_INFO, /* for diagnostics */
82 };
83 /* the default is to only log errors */
84 static int bcm5974_debug = BCM5974_LLEVEL_ERROR;
85
86 SYSCTL_INT(_hw_hid_bcm5974, OID_AUTO, debug, CTLFLAG_RWTUN,
87 &bcm5974_debug, BCM5974_LLEVEL_ERROR, "BCM5974 debug level");
88 #endif /* HID_DEBUG */
89
90 /*
91 * Some tables, structures, definitions and constant values for the
92 * touchpad protocol has been copied from Linux's
93 * "drivers/input/mouse/bcm5974.c" which has the following copyright
94 * holders under GPLv2. All device specific code in this driver has
95 * been written from scratch. The decoding algorithm is based on
96 * output from FreeBSD's usbdump.
97 *
98 * Copyright (C) 2008 Henrik Rydberg ([email protected])
99 * Copyright (C) 2008 Scott Shawcroft ([email protected])
100 * Copyright (C) 2001-2004 Greg Kroah-Hartman ([email protected])
101 * Copyright (C) 2005 Johannes Berg ([email protected])
102 * Copyright (C) 2005 Stelian Pop ([email protected])
103 * Copyright (C) 2005 Frank Arnold ([email protected])
104 * Copyright (C) 2005 Peter Osterlund ([email protected])
105 * Copyright (C) 2005 Michael Hanselmann ([email protected])
106 * Copyright (C) 2006 Nicolas Boichat ([email protected])
107 */
108
109 /* trackpad header types */
110 enum tp_type {
111 TYPE1, /* plain trackpad */
112 TYPE2, /* button integrated in trackpad */
113 TYPE3, /* additional header fields since June 2013 */
114 TYPE4, /* additional header field for pressure data */
115 TYPE_MT2U, /* Magic Trackpad 2 USB */
116 TYPE_CNT
117 };
118
119 /* list of device capability bits */
120 #define HAS_INTEGRATED_BUTTON 1
121 #define USES_COMPACT_REPORT 2
122
123 struct tp_type_params {
124 uint8_t caps; /* device capability bitmask */
125 uint8_t button; /* offset to button data */
126 uint8_t offset; /* offset to trackpad finger data */
127 uint8_t delta; /* offset from header to finger struct */
128 } const static tp[TYPE_CNT] = {
129 [TYPE1] = {
130 .caps = 0,
131 .button = 0,
132 .offset = 13 * 2,
133 .delta = 0,
134 },
135 [TYPE2] = {
136 .caps = HAS_INTEGRATED_BUTTON,
137 .button = 15,
138 .offset = 15 * 2,
139 .delta = 0,
140 },
141 [TYPE3] = {
142 .caps = HAS_INTEGRATED_BUTTON,
143 .button = 23,
144 .offset = 19 * 2,
145 .delta = 0,
146 },
147 [TYPE4] = {
148 .caps = HAS_INTEGRATED_BUTTON,
149 .button = 31,
150 .offset = 23 * 2,
151 .delta = 2,
152 },
153 [TYPE_MT2U] = {
154 .caps = HAS_INTEGRATED_BUTTON | USES_COMPACT_REPORT,
155 .button = 1,
156 .offset = 12,
157 .delta = 0,
158 },
159 };
160
161 /* trackpad finger structure - compact version for external "Magic" devices */
162 struct tp_finger_compact {
163 uint32_t coords; /* not struct directly due to endian conversion */
164 uint8_t touch_major;
165 uint8_t touch_minor;
166 uint8_t size;
167 uint8_t pressure;
168 uint8_t id_ori;
169 } __packed;
170
171 _Static_assert((sizeof(struct tp_finger_compact) == 9), "tp_finger struct size must be 9");
172
173 /* trackpad finger structure - little endian */
174 struct tp_finger {
175 uint16_t origin; /* zero when switching track finger */
176 uint16_t abs_x; /* absolute x coodinate */
177 uint16_t abs_y; /* absolute y coodinate */
178 uint16_t rel_x; /* relative x coodinate */
179 uint16_t rel_y; /* relative y coodinate */
180 uint16_t tool_major; /* tool area, major axis */
181 uint16_t tool_minor; /* tool area, minor axis */
182 uint16_t orientation; /* 16384 when point, else 15 bit angle */
183 uint16_t touch_major; /* touch area, major axis */
184 uint16_t touch_minor; /* touch area, minor axis */
185 uint16_t unused[2]; /* zeros */
186 uint16_t pressure; /* pressure on forcetouch touchpad */
187 uint16_t multi; /* one finger: varies, more fingers:
188 * constant */
189 } __packed;
190
191 #define BCM5974_LE2H(x) ((int32_t)(int16_t)le16toh(x))
192
193 /* trackpad finger data size, empirically at least ten fingers */
194 #define MAX_FINGERS MAX_MT_SLOTS
195
196 #define MAX_FINGER_ORIENTATION 16384
197
198 enum {
199 BCM5974_FLAG_WELLSPRING1,
200 BCM5974_FLAG_WELLSPRING2,
201 BCM5974_FLAG_WELLSPRING3,
202 BCM5974_FLAG_WELLSPRING4,
203 BCM5974_FLAG_WELLSPRING4A,
204 BCM5974_FLAG_WELLSPRING5,
205 BCM5974_FLAG_WELLSPRING6A,
206 BCM5974_FLAG_WELLSPRING6,
207 BCM5974_FLAG_WELLSPRING5A,
208 BCM5974_FLAG_WELLSPRING7,
209 BCM5974_FLAG_WELLSPRING7A,
210 BCM5974_FLAG_WELLSPRING8,
211 BCM5974_FLAG_WELLSPRING9_MODEL3,
212 BCM5974_FLAG_WELLSPRING9_MODEL4,
213 #define BCM5974_FLAG_WELLSPRING9_MODEL_SPI BCM5974_FLAG_WELLSPRING9_MODEL4
214 BCM5974_FLAG_WELLSPRING9_MODEL5,
215 BCM5974_FLAG_WELLSPRING9_MODEL6,
216 BCM5974_FLAG_MAGIC_TRACKPAD2_USB,
217 BCM5974_FLAG_MAX,
218 };
219
220 /* device-specific parameters */
221 struct bcm5974_axis {
222 int snratio; /* signal-to-noise ratio */
223 int min; /* device minimum reading */
224 int max; /* device maximum reading */
225 int size; /* physical size, mm */
226 };
227
228 /* device-specific configuration */
229 struct bcm5974_dev_params {
230 const struct tp_type_params* tp;
231 struct bcm5974_axis p; /* finger pressure limits */
232 struct bcm5974_axis w; /* finger width limits */
233 struct bcm5974_axis x; /* horizontal limits */
234 struct bcm5974_axis y; /* vertical limits */
235 struct bcm5974_axis o; /* orientation limits */
236 };
237
238 /* logical signal quality */
239 #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */
240 #define SN_WIDTH 25 /* width signal-to-noise ratio */
241 #define SN_COORD 250 /* coordinate signal-to-noise ratio */
242 #define SN_ORIENT 10 /* orientation signal-to-noise ratio */
243
244 static const struct bcm5974_dev_params bcm5974_dev_params[BCM5974_FLAG_MAX] = {
245 [BCM5974_FLAG_WELLSPRING1] = {
246 .tp = tp + TYPE1,
247 .p = { SN_PRESSURE, 0, 256, 0 },
248 .w = { SN_WIDTH, 0, 2048, 0 },
249 .x = { SN_COORD, -4824, 5342, 105 },
250 .y = { SN_COORD, -172, 5820, 75 },
251 .o = { SN_ORIENT,
252 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
253 },
254 [BCM5974_FLAG_WELLSPRING2] = {
255 .tp = tp + TYPE1,
256 .p = { SN_PRESSURE, 0, 256, 0 },
257 .w = { SN_WIDTH, 0, 2048, 0 },
258 .x = { SN_COORD, -4824, 4824, 105 },
259 .y = { SN_COORD, -172, 4290, 75 },
260 .o = { SN_ORIENT,
261 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
262 },
263 [BCM5974_FLAG_WELLSPRING3] = {
264 .tp = tp + TYPE2,
265 .p = { SN_PRESSURE, 0, 300, 0 },
266 .w = { SN_WIDTH, 0, 2048, 0 },
267 .x = { SN_COORD, -4460, 5166, 105 },
268 .y = { SN_COORD, -75, 6700, 75 },
269 .o = { SN_ORIENT,
270 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
271 },
272 [BCM5974_FLAG_WELLSPRING4] = {
273 .tp = tp + TYPE2,
274 .p = { SN_PRESSURE, 0, 300, 0 },
275 .w = { SN_WIDTH, 0, 2048, 0 },
276 .x = { SN_COORD, -4620, 5140, 105 },
277 .y = { SN_COORD, -150, 6600, 75 },
278 .o = { SN_ORIENT,
279 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
280 },
281 [BCM5974_FLAG_WELLSPRING4A] = {
282 .tp = tp + TYPE2,
283 .p = { SN_PRESSURE, 0, 300, 0 },
284 .w = { SN_WIDTH, 0, 2048, 0 },
285 .x = { SN_COORD, -4616, 5112, 105 },
286 .y = { SN_COORD, -142, 5234, 75 },
287 .o = { SN_ORIENT,
288 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
289 },
290 [BCM5974_FLAG_WELLSPRING5] = {
291 .tp = tp + TYPE2,
292 .p = { SN_PRESSURE, 0, 300, 0 },
293 .w = { SN_WIDTH, 0, 2048, 0 },
294 .x = { SN_COORD, -4415, 5050, 105 },
295 .y = { SN_COORD, -55, 6680, 75 },
296 .o = { SN_ORIENT,
297 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
298 },
299 [BCM5974_FLAG_WELLSPRING6] = {
300 .tp = tp + TYPE2,
301 .p = { SN_PRESSURE, 0, 300, 0 },
302 .w = { SN_WIDTH, 0, 2048, 0 },
303 .x = { SN_COORD, -4620, 5140, 105 },
304 .y = { SN_COORD, -150, 6600, 75 },
305 .o = { SN_ORIENT,
306 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
307 },
308 [BCM5974_FLAG_WELLSPRING5A] = {
309 .tp = tp + TYPE2,
310 .p = { SN_PRESSURE, 0, 300, 0 },
311 .w = { SN_WIDTH, 0, 2048, 0 },
312 .x = { SN_COORD, -4750, 5280, 105 },
313 .y = { SN_COORD, -150, 6730, 75 },
314 .o = { SN_ORIENT,
315 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
316 },
317 [BCM5974_FLAG_WELLSPRING6A] = {
318 .tp = tp + TYPE2,
319 .p = { SN_PRESSURE, 0, 300, 0 },
320 .w = { SN_WIDTH, 0, 2048, 0 },
321 .x = { SN_COORD, -4620, 5140, 105 },
322 .y = { SN_COORD, -150, 6600, 75 },
323 .o = { SN_ORIENT,
324 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
325 },
326 [BCM5974_FLAG_WELLSPRING7] = {
327 .tp = tp + TYPE2,
328 .p = { SN_PRESSURE, 0, 300, 0 },
329 .w = { SN_WIDTH, 0, 2048, 0 },
330 .x = { SN_COORD, -4750, 5280, 105 },
331 .y = { SN_COORD, -150, 6730, 75 },
332 .o = { SN_ORIENT,
333 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
334 },
335 [BCM5974_FLAG_WELLSPRING7A] = {
336 .tp = tp + TYPE2,
337 .p = { SN_PRESSURE, 0, 300, 0 },
338 .w = { SN_WIDTH, 0, 2048, 0 },
339 .x = { SN_COORD, -4750, 5280, 105 },
340 .y = { SN_COORD, -150, 6730, 75 },
341 .o = { SN_ORIENT,
342 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
343 },
344 [BCM5974_FLAG_WELLSPRING8] = {
345 .tp = tp + TYPE3,
346 .p = { SN_PRESSURE, 0, 300, 0 },
347 .w = { SN_WIDTH, 0, 2048, 0 },
348 .x = { SN_COORD, -4620, 5140, 105 },
349 .y = { SN_COORD, -150, 6600, 75 },
350 .o = { SN_ORIENT,
351 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
352 },
353 /*
354 * NOTE: Actually force-sensitive. Pressure has a "size" equal to the max
355 * so that the "resolution" is 1 (i.e. values will be interpreted as grams).
356 * No scientific measurements have been done :) but a really hard press
357 * results in a value around 3500 on model 4.
358 */
359 [BCM5974_FLAG_WELLSPRING9_MODEL3] = {
360 .tp = tp + TYPE4,
361 .p = { SN_PRESSURE, 0, 4096, 4096 },
362 .w = { SN_WIDTH, 0, 2048, 0 },
363 .x = { SN_COORD, -4828, 5345, 105 },
364 .y = { SN_COORD, -203, 6803, 75 },
365 .o = { SN_ORIENT,
366 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
367 },
368 [BCM5974_FLAG_WELLSPRING9_MODEL4] = {
369 .tp = tp + TYPE4,
370 .p = { SN_PRESSURE, 0, 4096, 4096 },
371 .w = { SN_WIDTH, 0, 2048, 0 },
372 .x = { SN_COORD, -5087, 5579, 105 },
373 .y = { SN_COORD, -182, 6089, 75 },
374 .o = { SN_ORIENT,
375 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
376 },
377 [BCM5974_FLAG_WELLSPRING9_MODEL5] = {
378 .tp = tp + TYPE4,
379 .p = { SN_PRESSURE, 0, 4096, 4096 },
380 .w = { SN_WIDTH, 0, 2048, 0 },
381 .x = { SN_COORD, -6243, 6749, 105 },
382 .y = { SN_COORD, -170, 7685, 75 },
383 .o = { SN_ORIENT,
384 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
385 },
386 [BCM5974_FLAG_WELLSPRING9_MODEL6] = {
387 .tp = tp + TYPE4,
388 .p = { SN_PRESSURE, 0, 4096, 4096 },
389 .w = { SN_WIDTH, 0, 2048, 0 },
390 .x = { SN_COORD, -7456, 7976, 105 },
391 .y = { SN_COORD, -163, 9283, 75 },
392 .o = { SN_ORIENT,
393 -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
394 },
395 [BCM5974_FLAG_MAGIC_TRACKPAD2_USB] = {
396 .tp = tp + TYPE_MT2U,
397 .p = { SN_PRESSURE, 0, 256, 256 },
398 .w = { SN_WIDTH, 0, 2048, 0 },
399 .x = { SN_COORD, -3678, 3934, 48 },
400 .y = { SN_COORD, -2478, 2587, 44 },
401 .o = { SN_ORIENT, -3, 4, 0 },
402 },
403 };
404
405 #define BCM5974_DEV(v,p,i) { \
406 HID_BVPI(BUS_USB, USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i), \
407 HID_TLC(BCM5974_TLC_PAGE, BCM5974_TLC_USAGE), \
408 }
409
410 #define APPLE_HID "APP000D"
411 #define BCM5974_DEV_SPI(hid, i) { \
412 HID_BUS(BUS_SPI), HID_PNP(hid), HID_DRIVER_INFO(i), \
413 HID_TLC(BCM5974_TLC_PAGE, BCM5974_TLC_USAGE), \
414 }
415
416 static const struct hid_device_id bcm5974_devs[] = {
417 /* MacbookAir1.1 */
418 BCM5974_DEV(APPLE, WELLSPRING_ANSI, BCM5974_FLAG_WELLSPRING1),
419 BCM5974_DEV(APPLE, WELLSPRING_ISO, BCM5974_FLAG_WELLSPRING1),
420 BCM5974_DEV(APPLE, WELLSPRING_JIS, BCM5974_FLAG_WELLSPRING1),
421
422 /* MacbookProPenryn, aka wellspring2 */
423 BCM5974_DEV(APPLE, WELLSPRING2_ANSI, BCM5974_FLAG_WELLSPRING2),
424 BCM5974_DEV(APPLE, WELLSPRING2_ISO, BCM5974_FLAG_WELLSPRING2),
425 BCM5974_DEV(APPLE, WELLSPRING2_JIS, BCM5974_FLAG_WELLSPRING2),
426
427 /* Macbook5,1 (unibody), aka wellspring3 */
428 BCM5974_DEV(APPLE, WELLSPRING3_ANSI, BCM5974_FLAG_WELLSPRING3),
429 BCM5974_DEV(APPLE, WELLSPRING3_ISO, BCM5974_FLAG_WELLSPRING3),
430 BCM5974_DEV(APPLE, WELLSPRING3_JIS, BCM5974_FLAG_WELLSPRING3),
431
432 /* MacbookAir3,2 (unibody), aka wellspring4 */
433 BCM5974_DEV(APPLE, WELLSPRING4_ANSI, BCM5974_FLAG_WELLSPRING4),
434 BCM5974_DEV(APPLE, WELLSPRING4_ISO, BCM5974_FLAG_WELLSPRING4),
435 BCM5974_DEV(APPLE, WELLSPRING4_JIS, BCM5974_FLAG_WELLSPRING4),
436
437 /* MacbookAir3,1 (unibody), aka wellspring4 */
438 BCM5974_DEV(APPLE, WELLSPRING4A_ANSI, BCM5974_FLAG_WELLSPRING4A),
439 BCM5974_DEV(APPLE, WELLSPRING4A_ISO, BCM5974_FLAG_WELLSPRING4A),
440 BCM5974_DEV(APPLE, WELLSPRING4A_JIS, BCM5974_FLAG_WELLSPRING4A),
441
442 /* Macbook8 (unibody, March 2011) */
443 BCM5974_DEV(APPLE, WELLSPRING5_ANSI, BCM5974_FLAG_WELLSPRING5),
444 BCM5974_DEV(APPLE, WELLSPRING5_ISO, BCM5974_FLAG_WELLSPRING5),
445 BCM5974_DEV(APPLE, WELLSPRING5_JIS, BCM5974_FLAG_WELLSPRING5),
446
447 /* MacbookAir4,1 (unibody, July 2011) */
448 BCM5974_DEV(APPLE, WELLSPRING6A_ANSI, BCM5974_FLAG_WELLSPRING6A),
449 BCM5974_DEV(APPLE, WELLSPRING6A_ISO, BCM5974_FLAG_WELLSPRING6A),
450 BCM5974_DEV(APPLE, WELLSPRING6A_JIS, BCM5974_FLAG_WELLSPRING6A),
451
452 /* MacbookAir4,2 (unibody, July 2011) */
453 BCM5974_DEV(APPLE, WELLSPRING6_ANSI, BCM5974_FLAG_WELLSPRING6),
454 BCM5974_DEV(APPLE, WELLSPRING6_ISO, BCM5974_FLAG_WELLSPRING6),
455 BCM5974_DEV(APPLE, WELLSPRING6_JIS, BCM5974_FLAG_WELLSPRING6),
456
457 /* Macbook8,2 (unibody) */
458 BCM5974_DEV(APPLE, WELLSPRING5A_ANSI, BCM5974_FLAG_WELLSPRING5A),
459 BCM5974_DEV(APPLE, WELLSPRING5A_ISO, BCM5974_FLAG_WELLSPRING5A),
460 BCM5974_DEV(APPLE, WELLSPRING5A_JIS, BCM5974_FLAG_WELLSPRING5A),
461
462 /* MacbookPro10,1 (unibody, June 2012) */
463 /* MacbookPro11,1-3 (unibody, June 2013) */
464 BCM5974_DEV(APPLE, WELLSPRING7_ANSI, BCM5974_FLAG_WELLSPRING7),
465 BCM5974_DEV(APPLE, WELLSPRING7_ISO, BCM5974_FLAG_WELLSPRING7),
466 BCM5974_DEV(APPLE, WELLSPRING7_JIS, BCM5974_FLAG_WELLSPRING7),
467
468 /* MacbookPro10,2 (unibody, October 2012) */
469 BCM5974_DEV(APPLE, WELLSPRING7A_ANSI, BCM5974_FLAG_WELLSPRING7A),
470 BCM5974_DEV(APPLE, WELLSPRING7A_ISO, BCM5974_FLAG_WELLSPRING7A),
471 BCM5974_DEV(APPLE, WELLSPRING7A_JIS, BCM5974_FLAG_WELLSPRING7A),
472
473 /* MacbookAir6,2 (unibody, June 2013) */
474 BCM5974_DEV(APPLE, WELLSPRING8_ANSI, BCM5974_FLAG_WELLSPRING8),
475 BCM5974_DEV(APPLE, WELLSPRING8_ISO, BCM5974_FLAG_WELLSPRING8),
476 BCM5974_DEV(APPLE, WELLSPRING8_JIS, BCM5974_FLAG_WELLSPRING8),
477
478 /* MacbookPro12,1 MacbookPro11,4 */
479 BCM5974_DEV(APPLE, WELLSPRING9_ANSI, BCM5974_FLAG_WELLSPRING9_MODEL3),
480 BCM5974_DEV(APPLE, WELLSPRING9_ISO, BCM5974_FLAG_WELLSPRING9_MODEL3),
481 BCM5974_DEV(APPLE, WELLSPRING9_JIS, BCM5974_FLAG_WELLSPRING9_MODEL3),
482
483 /* Generic SPI device */
484 BCM5974_DEV_SPI(APPLE_HID, BCM5974_FLAG_WELLSPRING9_MODEL_SPI),
485
486 /* External "Magic" devices */
487 BCM5974_DEV(APPLE, MAGIC_TRACKPAD2, BCM5974_FLAG_MAGIC_TRACKPAD2_USB),
488 };
489
490 #define BCM5974_WELLSPRING9_RDESC_SIZE 110
491 #define BCM5974_WELLSPRING9_MODEL_OFFSET 106
492
493 struct bcm5974_softc {
494 device_t sc_dev;
495 struct evdev_dev *sc_evdev;
496 /* device configuration */
497 const struct bcm5974_dev_params *sc_params;
498 bool sc_saved_mode;
499 };
500
501 static const uint8_t bcm5974_rdesc[] = {
502 0x05, BCM5974_TLC_PAGE, /* Usage Page (BCM5974_TLC_PAGE) */
503 0x09, BCM5974_TLC_USAGE,/* Usage (BCM5974_TLC_USAGE) */
504 0xA1, 0x01, /* Collection (Application) */
505 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */
506 0x09, 0x01, /* Usage (0x01) */
507 0x15, 0x00, /* Logical Minimum (0) */
508 0x26, 0xFF, 0x00, /* Logical Maximum (255) */
509 0x75, 0x08, /* Report Size (8) */
510 0x96, /* Report Count (BCM5974_BUFFER_MAX) */
511 BCM5974_BUFFER_MAX & 0xFF,
512 BCM5974_BUFFER_MAX >> 8 & 0xFF,
513 0x81, 0x02, /* Input (Data,Var,Abs) */
514 0xC0, /* End Collection */
515 };
516
517 /*
518 * function prototypes
519 */
520 static evdev_open_t bcm5974_ev_open;
521 static evdev_close_t bcm5974_ev_close;
522 static const struct evdev_methods bcm5974_evdev_methods = {
523 .ev_open = &bcm5974_ev_open,
524 .ev_close = &bcm5974_ev_close,
525 };
526 static hid_intr_t bcm5974_intr;
527
528 /* Device methods. */
529 static device_identify_t bcm5974_identify;
530 static device_probe_t bcm5974_probe;
531 static device_attach_t bcm5974_attach;
532 static device_detach_t bcm5974_detach;
533
534 /*
535 * Type1 and Type2 touchpads use keyboard USB interface to switch from HID to
536 * RAW mode. Although it is possible to extend hkbd driver to support such a
537 * mode change requests, it's not wanted due to cross device tree dependencies.
538 * So, find lowest common denominator (struct usb_device of grandparent usbhid
539 * driver) of touchpad and keyboard drivers and issue direct USB requests.
540 */
541 static int
bcm5974_set_device_mode_usb(struct bcm5974_softc * sc,bool on)542 bcm5974_set_device_mode_usb(struct bcm5974_softc *sc, bool on)
543 {
544 uint8_t mode_bytes[BCM5974_USB_REPORT_LEN];
545 struct usb_ctl_request ucr;
546 int err;
547
548 ucr.ucr_request.bmRequestType = UT_READ_CLASS_INTERFACE;
549 ucr.ucr_request.bRequest = UR_GET_REPORT;
550 USETW2(ucr.ucr_request.wValue,
551 UHID_FEATURE_REPORT, BCM5974_USB_REPORT_ID);
552 ucr.ucr_request.wIndex[0] = BCM5974_USB_IFACE_INDEX;
553 ucr.ucr_request.wIndex[1] = 0;
554 USETW(ucr.ucr_request.wLength, BCM5974_USB_REPORT_LEN);
555 ucr.ucr_data = mode_bytes;
556
557 err = hid_ioctl(sc->sc_dev, USB_REQUEST, (uintptr_t)&ucr);
558 if (err != 0) {
559 DPRINTF("Failed to read device mode (%d)\n", err);
560 return (EIO);
561 }
562 #if 0
563 /*
564 * XXX Need to wait at least 250ms for hardware to get
565 * ready. The device mode handling appears to be handled
566 * asynchronously and we should not issue these commands too
567 * quickly.
568 */
569 pause("WHW", hz / 4);
570 #endif
571 mode_bytes[0] = on ? BCM5974_USB_MODE_RAW : BCM5974_USB_MODE_HID;
572 ucr.ucr_request.bmRequestType = UT_WRITE_CLASS_INTERFACE;
573 ucr.ucr_request.bRequest = UR_SET_REPORT;
574
575 err = hid_ioctl(sc->sc_dev, USB_REQUEST, (uintptr_t)&ucr);
576 if (err != 0) {
577 DPRINTF("Failed to write device mode (%d)\n", err);
578 return (EIO);
579 }
580
581 return (0);
582 }
583
584 static int
bcm5974_set_device_mode_hid(struct bcm5974_softc * sc,bool on)585 bcm5974_set_device_mode_hid(struct bcm5974_softc *sc, bool on)
586 {
587 uint8_t mode_bytes[BCM5974_HID_REPORT_LEN] = {
588 BCM5974_HID_REPORT_ID,
589 on ? BCM5974_HID_MODE_RAW : BCM5974_HID_MODE_HID,
590 };
591 #if 0
592 int err;
593
594 err = hid_get_report(sc->sc_dev, mode_bytes, BCM5974_HID_REPORT_LEN,
595 NULL, HID_FEATURE_REPORT, BCM5974_HID_REPORT_ID);
596 if (err != 0) {
597 DPRINTF("Failed to read device mode (%d)\n", err);
598 return (err);
599 }
600 /*
601 * XXX Need to wait at least 250ms for hardware to get
602 * ready. The device mode handling appears to be handled
603 * asynchronously and we should not issue these commands too
604 * quickly.
605 */
606 pause("WHW", hz / 4);
607 mode_bytes[1] = on ? BCM5974_HID_MODE_RAW : BCM5974_HID_MODE_HID;
608 #endif
609 return (hid_set_report(sc->sc_dev, mode_bytes, BCM5974_HID_REPORT_LEN,
610 HID_FEATURE_REPORT, BCM5974_HID_REPORT_ID));
611 }
612
613 static int
bcm5974_set_device_mode(struct bcm5974_softc * sc,bool on)614 bcm5974_set_device_mode(struct bcm5974_softc *sc, bool on)
615 {
616 int err = 0;
617
618 switch (sc->sc_params->tp - tp) {
619 case TYPE1:
620 case TYPE2:
621 err = bcm5974_set_device_mode_usb(sc, on);
622 break;
623 case TYPE3: /* Type 3 does not require a mode switch */
624 break;
625 case TYPE4:
626 case TYPE_MT2U:
627 err = bcm5974_set_device_mode_hid(sc, on);
628 break;
629 default:
630 KASSERT(0 == 1, ("Unknown trackpad type"));
631 }
632
633 if (!err)
634 sc->sc_saved_mode = on;
635
636 return (err);
637 }
638
639 static uintptr_t
bcm5974_get_wsp9_model(device_t dev)640 bcm5974_get_wsp9_model(device_t dev)
641 {
642 const struct hid_device_info *hw = hid_get_device_info(dev);
643 static uint8_t rdesc[BCM5974_WELLSPRING9_RDESC_SIZE];
644 uint8_t model_byte = 0;
645
646 bus_topo_assert();
647
648 if (hw->rdescsize == sizeof(rdesc) &&
649 hid_get_rdesc(dev, rdesc, sizeof(rdesc)) == 0) {
650 model_byte = rdesc[BCM5974_WELLSPRING9_MODEL_OFFSET];
651 switch (model_byte) {
652 case 3:
653 /* MacbookPro12,1 MacbookPro11,4 */
654 return (BCM5974_FLAG_WELLSPRING9_MODEL3);
655 case 4:
656 /* Macbook8,1 Macbook9,1 Macbook10,1 */
657 return (BCM5974_FLAG_WELLSPRING9_MODEL4);
658 case 5:
659 /*
660 * MacbookPro13,1 MacbookPro13,2
661 * MacbookPro14,1 MacbookPro14,2
662 */
663 return (BCM5974_FLAG_WELLSPRING9_MODEL5);
664 case 6:
665 /* MacbookPro13,3 MacbookPro14,3 */
666 return (BCM5974_FLAG_WELLSPRING9_MODEL6);
667 }
668 }
669
670 device_printf(dev, "Unexpected trackpad descriptor len=%u model_byte="
671 "%u, not extracting model\n", hw->rdescsize, model_byte);
672
673 /* Fallback for unknown SPI versions */
674 return (BCM5974_FLAG_WELLSPRING9_MODEL_SPI);
675 }
676
677 static void
bcm5974_identify(driver_t * driver,device_t parent)678 bcm5974_identify(driver_t *driver, device_t parent)
679 {
680 void *d_ptr;
681 hid_size_t d_len;
682
683 /*
684 * The bcm5974 touchpad has no stable RAW mode TLC in its report
685 * descriptor. So replace existing HID mode mouse TLC with dummy one
686 * to set proper transport layer buffer sizes, make driver probe
687 * simpler and prevent unwanted hms driver attachment.
688 */
689 if (HIDBUS_LOOKUP_ID(parent, bcm5974_devs) != NULL &&
690 hid_get_report_descr(parent, &d_ptr, &d_len) == 0 &&
691 hid_is_mouse(d_ptr, d_len))
692 hid_set_report_descr(parent, bcm5974_rdesc,
693 sizeof(bcm5974_rdesc));
694 }
695
696 static int
bcm5974_probe(device_t dev)697 bcm5974_probe(device_t dev)
698 {
699 int err;
700
701 err = HIDBUS_LOOKUP_DRIVER_INFO(dev, bcm5974_devs);
702 if (err != 0)
703 return (err);
704
705 hidbus_set_desc(dev, "Touchpad");
706
707 return (BUS_PROBE_DEFAULT);
708 }
709
710 static int
bcm5974_attach(device_t dev)711 bcm5974_attach(device_t dev)
712 {
713 struct bcm5974_softc *sc = device_get_softc(dev);
714 const struct hid_device_info *hw = hid_get_device_info(dev);
715 uintptr_t drv_info;
716 int err;
717
718 DPRINTFN(BCM5974_LLEVEL_INFO, "sc=%p\n", sc);
719
720 sc->sc_dev = dev;
721
722 /* get device specific configuration */
723 drv_info = hidbus_get_driver_info(dev);
724 if (drv_info == BCM5974_FLAG_WELLSPRING9_MODEL_SPI)
725 drv_info = bcm5974_get_wsp9_model(dev);
726 sc->sc_params = bcm5974_dev_params + drv_info;
727
728 sc->sc_evdev = evdev_alloc();
729 evdev_set_name(sc->sc_evdev, device_get_desc(dev));
730 evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
731 evdev_set_id(sc->sc_evdev, hw->idBus, hw->idVendor, hw->idProduct,
732 hw->idVersion);
733 evdev_set_serial(sc->sc_evdev, hw->serial);
734 evdev_set_methods(sc->sc_evdev, sc, &bcm5974_evdev_methods);
735 evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
736 evdev_support_event(sc->sc_evdev, EV_SYN);
737 evdev_support_event(sc->sc_evdev, EV_ABS);
738 evdev_support_event(sc->sc_evdev, EV_KEY);
739 evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */
740
741 #define BCM5974_ABS(evdev, code, param) \
742 evdev_support_abs((evdev), (code), (param).min, (param).max, \
743 ((param).max - (param).min) / (param).snratio, 0, \
744 (param).size != 0 ? ((param).max - (param).min) / (param).size : 0);
745
746 /* finger position */
747 BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x);
748 BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y);
749 /* finger pressure */
750 BCM5974_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p);
751 /* finger touch area */
752 BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
753 BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
754 /* finger approach area */
755 if ((sc->sc_params->tp->caps & USES_COMPACT_REPORT) == 0) {
756 BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
757 BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
758 }
759 /* finger orientation */
760 BCM5974_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
761 /* button properties */
762 evdev_support_key(sc->sc_evdev, BTN_LEFT);
763 if ((sc->sc_params->tp->caps & HAS_INTEGRATED_BUTTON) != 0)
764 evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
765 /* Enable automatic touch assignment for type B MT protocol */
766 evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
767 0, MAX_FINGERS - 1, 0, 0, 0);
768 evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
769 -1, MAX_FINGERS - 1, 0, 0, 0);
770 if ((sc->sc_params->tp->caps & USES_COMPACT_REPORT) == 0)
771 evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
772 evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
773 /* Synaptics compatibility events */
774 evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
775
776 err = evdev_register(sc->sc_evdev);
777 if (err)
778 goto detach;
779
780 hidbus_set_intr(dev, bcm5974_intr, sc);
781
782 return (0);
783
784 detach:
785 bcm5974_detach(dev);
786 return (ENOMEM);
787 }
788
789 static int
bcm5974_detach(device_t dev)790 bcm5974_detach(device_t dev)
791 {
792 struct bcm5974_softc *sc = device_get_softc(dev);
793
794 evdev_free(sc->sc_evdev);
795
796 return (0);
797 }
798
799 static int
bcm5974_resume(device_t dev)800 bcm5974_resume(device_t dev)
801 {
802 struct bcm5974_softc *sc = device_get_softc(dev);
803
804 bcm5974_set_device_mode(sc, sc->sc_saved_mode);
805
806 return (0);
807 }
808
809 static void
bcm5974_intr(void * context,void * data,hid_size_t len)810 bcm5974_intr(void *context, void *data, hid_size_t len)
811 {
812 struct bcm5974_softc *sc = context;
813 const struct bcm5974_dev_params *params = sc->sc_params;
814 union evdev_mt_slot slot_data;
815 struct tp_finger *f;
816 struct tp_finger_compact *fc;
817 int coords;
818 int ntouch; /* the finger number in touch */
819 int ibt; /* button status */
820 int i;
821 int slot;
822 uint8_t fsize = sizeof(struct tp_finger) + params->tp->delta;
823
824 if ((params->tp->caps & USES_COMPACT_REPORT) != 0)
825 fsize = sizeof(struct tp_finger_compact) + params->tp->delta;
826
827 if ((len < params->tp->offset + fsize) ||
828 ((len - params->tp->offset) % fsize) != 0) {
829 DPRINTFN(BCM5974_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
830 len, sc->tp_data[0], sc->tp_data[1]);
831 return;
832 }
833
834 ibt = ((uint8_t *)data)[params->tp->button];
835 ntouch = (len - params->tp->offset) / fsize;
836
837 for (i = 0, slot = 0; i != ntouch; i++) {
838 if ((params->tp->caps & USES_COMPACT_REPORT) != 0) {
839 fc = (struct tp_finger_compact *)(((uint8_t *)data) +
840 params->tp->offset + params->tp->delta + i * fsize);
841 coords = (int)le32toh(fc->coords);
842 DPRINTFN(BCM5974_LLEVEL_INFO,
843 "[%d]ibt=%d, taps=%d, x=%5d, y=%5d, state=%4d, "
844 "tchmaj=%4d, tchmin=%4d, size=%4d, pressure=%4d, "
845 "ot=%4x, id=%4x\n",
846 i, ibt, ntouch, coords << 19 >> 19,
847 coords << 6 >> 19, (u_int)coords >> 30,
848 fc->touch_major, fc->touch_minor, fc->size,
849 fc->pressure, fc->id_ori >> 5, fc->id_ori & 0x0f);
850 if (fc->touch_major == 0)
851 continue;
852 slot_data = (union evdev_mt_slot) {
853 .id = fc->id_ori & 0x0f,
854 .x = coords << 19 >> 19,
855 .y = params->y.min + params->y.max -
856 ((coords << 6) >> 19),
857 .p = fc->pressure,
858 .maj = fc->touch_major << 2,
859 .min = fc->touch_minor << 2,
860 .ori = (int)(fc->id_ori >> 5) - 4,
861 };
862 evdev_mt_push_slot(sc->sc_evdev, slot, &slot_data);
863 slot++;
864 continue;
865 }
866 f = (struct tp_finger *)(((uint8_t *)data) +
867 params->tp->offset + params->tp->delta + i * fsize);
868 DPRINTFN(BCM5974_LLEVEL_INFO,
869 "[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
870 "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
871 "tchmaj=%4d, tchmin=%4d, pressure=%4d, m=%4x\n",
872 i, ibt, ntouch, BCM5974_LE2H(f->origin),
873 BCM5974_LE2H(f->abs_x), BCM5974_LE2H(f->abs_y),
874 BCM5974_LE2H(f->rel_x), BCM5974_LE2H(f->rel_y),
875 BCM5974_LE2H(f->tool_major), BCM5974_LE2H(f->tool_minor),
876 BCM5974_LE2H(f->orientation), BCM5974_LE2H(f->touch_major),
877 BCM5974_LE2H(f->touch_minor), BCM5974_LE2H(f->pressure),
878 BCM5974_LE2H(f->multi));
879
880 if (BCM5974_LE2H(f->touch_major) == 0)
881 continue;
882 slot_data = (union evdev_mt_slot) {
883 .id = slot,
884 .x = BCM5974_LE2H(f->abs_x),
885 .y = params->y.min + params->y.max -
886 BCM5974_LE2H(f->abs_y),
887 .p = BCM5974_LE2H(f->pressure),
888 .maj = BCM5974_LE2H(f->touch_major) << 1,
889 .min = BCM5974_LE2H(f->touch_minor) << 1,
890 .w_maj = BCM5974_LE2H(f->tool_major) << 1,
891 .w_min = BCM5974_LE2H(f->tool_minor) << 1,
892 .ori = params->o.max - BCM5974_LE2H(f->orientation),
893 };
894 evdev_mt_push_slot(sc->sc_evdev, slot, &slot_data);
895 slot++;
896 }
897
898 evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
899 evdev_sync(sc->sc_evdev);
900 }
901
902 static int
bcm5974_ev_open(struct evdev_dev * evdev)903 bcm5974_ev_open(struct evdev_dev *evdev)
904 {
905 struct bcm5974_softc *sc = evdev_get_softc(evdev);
906 int err;
907
908 /*
909 * By default the touchpad behaves like a HID device, sending
910 * packets with reportID = 8. Such reports contain only
911 * limited information. They encode movement deltas and button
912 * events, but do not include data from the pressure
913 * sensors. The device input mode can be switched from HID
914 * reports to raw sensor data using vendor-specific USB
915 * control commands:
916 */
917 err = bcm5974_set_device_mode(sc, true);
918 if (err != 0) {
919 DPRINTF("failed to set mode to RAW MODE (%d)\n", err);
920 return (err);
921 }
922
923 return (hid_intr_start(sc->sc_dev));
924 }
925
926 static int
bcm5974_ev_close(struct evdev_dev * evdev)927 bcm5974_ev_close(struct evdev_dev *evdev)
928 {
929 struct bcm5974_softc *sc = evdev_get_softc(evdev);
930 int err;
931
932 err = hid_intr_stop(sc->sc_dev);
933 if (err != 0)
934 return (err);
935
936 /*
937 * During re-enumeration of the device we need to force the
938 * device back into HID mode before switching it to RAW
939 * mode. Else the device does not work like expected.
940 */
941 err = bcm5974_set_device_mode(sc, false);
942 if (err != 0)
943 DPRINTF("Failed to set mode to HID MODE (%d)\n", err);
944
945 return (err);
946 }
947
948 static device_method_t bcm5974_methods[] = {
949 /* Device interface */
950 DEVMETHOD(device_identify, bcm5974_identify),
951 DEVMETHOD(device_probe, bcm5974_probe),
952 DEVMETHOD(device_attach, bcm5974_attach),
953 DEVMETHOD(device_detach, bcm5974_detach),
954 DEVMETHOD(device_resume, bcm5974_resume),
955 DEVMETHOD_END
956 };
957
958 static driver_t bcm5974_driver = {
959 .name = "bcm5974",
960 .methods = bcm5974_methods,
961 .size = sizeof(struct bcm5974_softc)
962 };
963
964 DRIVER_MODULE(bcm5974, hidbus, bcm5974_driver, NULL, NULL);
965 MODULE_DEPEND(bcm5974, hidbus, 1, 1, 1);
966 MODULE_DEPEND(bcm5974, hid, 1, 1, 1);
967 MODULE_DEPEND(bcm5974, evdev, 1, 1, 1);
968 MODULE_VERSION(bcm5974, 1);
969 HID_PNP_INFO(bcm5974_devs);
970