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