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