1 /* $NetBSD: btmagic.c,v 1.20 2021/04/24 23:36:53 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Iain Hibbert. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Lennart Augustsson (lennart@augustsson.net) at 12 * Carlstedt Research & Technology. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 /*- 36 * Copyright (c) 2006 Itronix Inc. 37 * All rights reserved. 38 * 39 * Written by Iain Hibbert for Itronix Inc. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. The name of Itronix Inc. may not be used to endorse 50 * or promote products derived from this software without specific 51 * prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 57 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 58 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 59 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 60 * ON ANY THEORY OF LIABILITY, WHETHER IN 61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 63 * POSSIBILITY OF SUCH DAMAGE. 64 */ 65 66 67 /***************************************************************************** 68 * 69 * Apple Bluetooth Magic Mouse driver 70 * 71 * The Apple Magic Mouse is a HID device but it doesn't provide a proper HID 72 * descriptor, and requires extra initializations to enable the proprietary 73 * touch reports. We match against the vendor-id and product-id and provide 74 * our own Bluetooth connection handling as the bthidev driver does not cater 75 * for such complications. 76 * 77 * This driver interprets the touch reports only as far as emulating a 78 * middle mouse button and providing horizontal and vertical scroll action. 79 * Full gesture support would be more complicated and is left as an exercise 80 * for the reader. 81 * 82 * Credit for decoding the proprietary touch reports goes to Michael Poole 83 * who wrote the Linux hid-magicmouse input driver. 84 * 85 *****************************************************************************/ 86 87 #include <sys/cdefs.h> 88 __KERNEL_RCSID(0, "$NetBSD: btmagic.c,v 1.20 2021/04/24 23:36:53 thorpej Exp $"); 89 90 #include <sys/param.h> 91 #include <sys/conf.h> 92 #include <sys/device.h> 93 #include <sys/fcntl.h> 94 #include <sys/kernel.h> 95 #include <sys/malloc.h> 96 #include <sys/mbuf.h> 97 #include <sys/proc.h> 98 #include <sys/socketvar.h> 99 #include <sys/systm.h> 100 #include <sys/sysctl.h> 101 102 #include <prop/proplib.h> 103 104 #include <netbt/bluetooth.h> 105 #include <netbt/l2cap.h> 106 107 #include <dev/bluetooth/btdev.h> 108 #include <dev/bluetooth/bthid.h> 109 #include <dev/bluetooth/bthidev.h> 110 111 #include <dev/hid/hid.h> 112 #include <dev/usb/usb.h> 113 #include <dev/usb/usbdevs.h> 114 115 #include <dev/wscons/wsconsio.h> 116 #include <dev/wscons/wsmousevar.h> 117 118 #undef DPRINTF 119 #ifdef BTMAGIC_DEBUG 120 #define DPRINTF(sc, ...) do { \ 121 printf("%s: ", device_xname((sc)->sc_dev)); \ 122 printf(__VA_ARGS__); \ 123 printf("\n"); \ 124 } while (/*CONSTCOND*/0) 125 #else 126 #define DPRINTF(...) (void)0 127 #endif 128 129 struct btmagic_softc { 130 bdaddr_t sc_laddr; /* local address */ 131 bdaddr_t sc_raddr; /* remote address */ 132 struct sockopt sc_mode; /* link mode */ 133 134 device_t sc_dev; 135 uint16_t sc_state; 136 uint16_t sc_flags; 137 138 callout_t sc_timeout; 139 140 /* control */ 141 struct l2cap_channel *sc_ctl; 142 struct l2cap_channel *sc_ctl_l; 143 144 /* interrupt */ 145 struct l2cap_channel *sc_int; 146 struct l2cap_channel *sc_int_l; 147 148 /* wsmouse child */ 149 device_t sc_wsmouse; 150 int sc_enabled; 151 152 /* config */ 153 int sc_resolution; /* for soft scaling */ 154 int sc_firm; /* firm touch threshold */ 155 int sc_dist; /* scroll distance threshold */ 156 int sc_scale; /* scroll descaling */ 157 struct sysctllog *sc_log; /* sysctl teardown log */ 158 159 /* remainders */ 160 int sc_rx; 161 int sc_ry; 162 int sc_rz; 163 int sc_rw; 164 165 /* previous touches */ 166 uint32_t sc_smask; /* active IDs */ 167 int sc_nfingers; /* number of active IDs */ 168 int sc_ax[16]; 169 int sc_ay[16]; 170 171 /* previous mouse buttons */ 172 int sc_mb_id; /* which ID selects the button */ 173 uint32_t sc_mb; 174 /* button emulation with tap */ 175 int sc_tapmb_id; /* which ID selects the button */ 176 struct timeval sc_taptime; 177 int sc_taptimeout; 178 callout_t sc_tapcallout; 179 }; 180 181 /* sc_flags */ 182 #define BTMAGIC_CONNECTING __BIT(0) /* we are connecting */ 183 #define BTMAGIC_ENABLED __BIT(1) /* touch reports enabled */ 184 185 /* sc_state */ 186 #define BTMAGIC_CLOSED 0 187 #define BTMAGIC_WAIT_CTL 1 188 #define BTMAGIC_WAIT_INT 2 189 #define BTMAGIC_OPEN 3 190 191 /* autoconf(9) glue */ 192 static int btmagic_match(device_t, cfdata_t, void *); 193 static void btmagic_attach(device_t, device_t, void *); 194 static int btmagic_detach(device_t, int); 195 static int btmagic_listen(struct btmagic_softc *); 196 static int btmagic_connect(struct btmagic_softc *); 197 static int btmagic_sysctl_resolution(SYSCTLFN_PROTO); 198 static int btmagic_sysctl_scale(SYSCTLFN_PROTO); 199 static int btmagic_tap(struct btmagic_softc *, int); 200 static int btmagic_sysctl_taptimeout(SYSCTLFN_PROTO); 201 202 CFATTACH_DECL_NEW(btmagic, sizeof(struct btmagic_softc), 203 btmagic_match, btmagic_attach, btmagic_detach, NULL); 204 205 /* wsmouse(4) accessops */ 206 static int btmagic_wsmouse_enable(void *); 207 static int btmagic_wsmouse_ioctl(void *, unsigned long, void *, int, struct lwp *); 208 static void btmagic_wsmouse_disable(void *); 209 210 static const struct wsmouse_accessops btmagic_wsmouse_accessops = { 211 btmagic_wsmouse_enable, 212 btmagic_wsmouse_ioctl, 213 btmagic_wsmouse_disable, 214 }; 215 216 /* bluetooth(9) protocol methods for L2CAP */ 217 static void btmagic_connecting(void *); 218 static void btmagic_ctl_connected(void *); 219 static void btmagic_int_connected(void *); 220 static void btmagic_ctl_disconnected(void *, int); 221 static void btmagic_int_disconnected(void *, int); 222 static void *btmagic_ctl_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); 223 static void *btmagic_int_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); 224 static void btmagic_complete(void *, int); 225 static void btmagic_linkmode(void *, int); 226 static void btmagic_input(void *, struct mbuf *); 227 static void btmagic_input_basic(struct btmagic_softc *, uint8_t *, size_t); 228 static void btmagic_input_magicm(struct btmagic_softc *, uint8_t *, size_t); 229 static void btmagic_input_magict(struct btmagic_softc *, uint8_t *, size_t); 230 static void btmagic_tapcallout(void *); 231 232 /* report types (data[1]) */ 233 #define BASIC_REPORT_ID 0x10 234 #define TRACKPAD_REPORT_ID 0x28 235 #define MOUSE_REPORT_ID 0x29 236 #define BATT_STAT_REPORT_ID 0x30 237 #define BATT_STRENGTH_REPORT_ID 0x47 238 #define SURFACE_REPORT_ID 0x61 239 240 static const struct btproto btmagic_ctl_proto = { 241 btmagic_connecting, 242 btmagic_ctl_connected, 243 btmagic_ctl_disconnected, 244 btmagic_ctl_newconn, 245 btmagic_complete, 246 btmagic_linkmode, 247 btmagic_input, 248 }; 249 250 static const struct btproto btmagic_int_proto = { 251 btmagic_connecting, 252 btmagic_int_connected, 253 btmagic_int_disconnected, 254 btmagic_int_newconn, 255 btmagic_complete, 256 btmagic_linkmode, 257 btmagic_input, 258 }; 259 260 /* btmagic internals */ 261 static void btmagic_timeout(void *); 262 static int btmagic_ctl_send(struct btmagic_softc *, const uint8_t *, size_t); 263 static void btmagic_enable(struct btmagic_softc *); 264 static void btmagic_check_battery(struct btmagic_softc *); 265 static int btmagic_scale(int, int *, int); 266 267 268 /***************************************************************************** 269 * 270 * Magic Mouse autoconf(9) routines 271 */ 272 273 static int 274 btmagic_match(device_t self, cfdata_t cfdata, void *aux) 275 { 276 uint16_t v, p; 277 278 if (prop_dictionary_get_uint16(aux, BTDEVvendor, &v) 279 && prop_dictionary_get_uint16(aux, BTDEVproduct, &p) 280 && v == USB_VENDOR_APPLE 281 && (p == USB_PRODUCT_APPLE_MAGICMOUSE || 282 p == USB_PRODUCT_APPLE_MAGICTRACKPAD)) 283 return 2; /* trump bthidev(4) */ 284 285 return 0; 286 } 287 288 static void 289 btmagic_attach(device_t parent, device_t self, void *aux) 290 { 291 struct btmagic_softc *sc = device_private(self); 292 struct wsmousedev_attach_args wsma; 293 const struct sysctlnode *node; 294 prop_object_t obj; 295 int err; 296 297 /* 298 * Init softc 299 */ 300 sc->sc_dev = self; 301 sc->sc_state = BTMAGIC_CLOSED; 302 sc->sc_mb_id = -1; 303 sc->sc_tapmb_id = -1; 304 callout_init(&sc->sc_timeout, 0); 305 callout_setfunc(&sc->sc_timeout, btmagic_timeout, sc); 306 callout_init(&sc->sc_tapcallout, 0); 307 callout_setfunc(&sc->sc_tapcallout, btmagic_tapcallout, sc); 308 sockopt_init(&sc->sc_mode, BTPROTO_L2CAP, SO_L2CAP_LM, 0); 309 310 /* 311 * extract config from proplist 312 */ 313 obj = prop_dictionary_get(aux, BTDEVladdr); 314 bdaddr_copy(&sc->sc_laddr, prop_data_value(obj)); 315 316 obj = prop_dictionary_get(aux, BTDEVraddr); 317 bdaddr_copy(&sc->sc_raddr, prop_data_value(obj)); 318 319 obj = prop_dictionary_get(aux, BTDEVmode); 320 if (prop_object_type(obj) == PROP_TYPE_STRING) { 321 if (prop_string_equals_string(obj, BTDEVauth)) 322 sockopt_setint(&sc->sc_mode, L2CAP_LM_AUTH); 323 else if (prop_string_equals_string(obj, BTDEVencrypt)) 324 sockopt_setint(&sc->sc_mode, L2CAP_LM_ENCRYPT); 325 else if (prop_string_equals_string(obj, BTDEVsecure)) 326 sockopt_setint(&sc->sc_mode, L2CAP_LM_SECURE); 327 else { 328 aprint_error(" unknown %s\n", BTDEVmode); 329 return; 330 } 331 332 aprint_verbose(" %s %s", BTDEVmode, 333 prop_string_value(obj)); 334 } else 335 sockopt_setint(&sc->sc_mode, 0); 336 337 aprint_normal(": 3 buttons, W and Z dirs\n"); 338 aprint_naive("\n"); 339 340 /* 341 * set defaults 342 */ 343 sc->sc_resolution = 650; 344 sc->sc_firm = 6; 345 sc->sc_dist = 130; 346 sc->sc_scale = 20; 347 sc->sc_taptimeout = 100; 348 349 sysctl_createv(&sc->sc_log, 0, NULL, &node, 350 0, 351 CTLTYPE_NODE, device_xname(self), 352 NULL, 353 NULL, 0, 354 NULL, 0, 355 CTL_HW, 356 CTL_CREATE, CTL_EOL); 357 358 if (node != NULL) { 359 sysctl_createv(&sc->sc_log, 0, NULL, NULL, 360 CTLFLAG_READWRITE, 361 CTLTYPE_INT, "soft_resolution", 362 NULL, 363 btmagic_sysctl_resolution, 0, 364 (void *)sc, 0, 365 CTL_HW, node->sysctl_num, 366 CTL_CREATE, CTL_EOL); 367 368 sysctl_createv(&sc->sc_log, 0, NULL, NULL, 369 CTLFLAG_READWRITE, 370 CTLTYPE_INT, "firm_touch_threshold", 371 NULL, 372 NULL, 0, 373 &sc->sc_firm, sizeof(sc->sc_firm), 374 CTL_HW, node->sysctl_num, 375 CTL_CREATE, CTL_EOL); 376 377 sysctl_createv(&sc->sc_log, 0, NULL, NULL, 378 CTLFLAG_READWRITE, 379 CTLTYPE_INT, "scroll_distance_threshold", 380 NULL, 381 NULL, 0, 382 &sc->sc_dist, sizeof(sc->sc_dist), 383 CTL_HW, node->sysctl_num, 384 CTL_CREATE, CTL_EOL); 385 386 sysctl_createv(&sc->sc_log, 0, NULL, NULL, 387 CTLFLAG_READWRITE, 388 CTLTYPE_INT, "scroll_downscale_factor", 389 NULL, 390 btmagic_sysctl_scale, 0, 391 (void *)sc, 0, 392 CTL_HW, node->sysctl_num, 393 CTL_CREATE, CTL_EOL); 394 sysctl_createv(&sc->sc_log, 0, NULL, NULL, 395 CTLFLAG_READWRITE, 396 CTLTYPE_INT, "taptimeout", 397 "timeout for tap detection in milliseconds", 398 btmagic_sysctl_taptimeout, 0, 399 (void *)sc, 0, 400 CTL_HW, node->sysctl_num, 401 CTL_CREATE, CTL_EOL); 402 } 403 404 /* 405 * attach the wsmouse 406 */ 407 wsma.accessops = &btmagic_wsmouse_accessops; 408 wsma.accesscookie = self; 409 sc->sc_wsmouse = config_found(self, &wsma, wsmousedevprint, CFARG_EOL); 410 if (sc->sc_wsmouse == NULL) { 411 aprint_error_dev(self, "failed to attach wsmouse\n"); 412 return; 413 } 414 415 pmf_device_register(self, NULL, NULL); 416 417 /* 418 * start bluetooth connections 419 */ 420 mutex_enter(bt_lock); 421 if ((err = btmagic_listen(sc)) != 0) 422 aprint_error_dev(self, "failed to listen (%d)\n", err); 423 btmagic_connect(sc); 424 mutex_exit(bt_lock); 425 } 426 427 static int 428 btmagic_detach(device_t self, int flags) 429 { 430 struct btmagic_softc *sc = device_private(self); 431 int err = 0; 432 433 mutex_enter(bt_lock); 434 435 /* release interrupt listen */ 436 if (sc->sc_int_l != NULL) { 437 l2cap_detach_pcb(&sc->sc_int_l); 438 sc->sc_int_l = NULL; 439 } 440 441 /* release control listen */ 442 if (sc->sc_ctl_l != NULL) { 443 l2cap_detach_pcb(&sc->sc_ctl_l); 444 sc->sc_ctl_l = NULL; 445 } 446 447 /* close interrupt channel */ 448 if (sc->sc_int != NULL) { 449 l2cap_disconnect_pcb(sc->sc_int, 0); 450 l2cap_detach_pcb(&sc->sc_int); 451 sc->sc_int = NULL; 452 } 453 454 /* close control channel */ 455 if (sc->sc_ctl != NULL) { 456 l2cap_disconnect_pcb(sc->sc_ctl, 0); 457 l2cap_detach_pcb(&sc->sc_ctl); 458 sc->sc_ctl = NULL; 459 } 460 461 callout_halt(&sc->sc_tapcallout, bt_lock); 462 callout_destroy(&sc->sc_tapcallout); 463 callout_halt(&sc->sc_timeout, bt_lock); 464 callout_destroy(&sc->sc_timeout); 465 466 mutex_exit(bt_lock); 467 468 pmf_device_deregister(self); 469 470 sockopt_destroy(&sc->sc_mode); 471 472 sysctl_teardown(&sc->sc_log); 473 474 if (sc->sc_wsmouse != NULL) { 475 err = config_detach(sc->sc_wsmouse, flags); 476 sc->sc_wsmouse = NULL; 477 } 478 479 return err; 480 } 481 482 /* 483 * listen for our device 484 * 485 * bt_lock is held 486 */ 487 static int 488 btmagic_listen(struct btmagic_softc *sc) 489 { 490 struct sockaddr_bt sa; 491 int err; 492 493 memset(&sa, 0, sizeof(sa)); 494 sa.bt_len = sizeof(sa); 495 sa.bt_family = AF_BLUETOOTH; 496 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); 497 498 /* 499 * Listen on control PSM 500 */ 501 err = l2cap_attach_pcb(&sc->sc_ctl_l, &btmagic_ctl_proto, sc); 502 if (err) 503 return err; 504 505 err = l2cap_setopt(sc->sc_ctl_l, &sc->sc_mode); 506 if (err) 507 return err; 508 509 sa.bt_psm = L2CAP_PSM_HID_CNTL; 510 err = l2cap_bind_pcb(sc->sc_ctl_l, &sa); 511 if (err) 512 return err; 513 514 err = l2cap_listen_pcb(sc->sc_ctl_l); 515 if (err) 516 return err; 517 518 /* 519 * Listen on interrupt PSM 520 */ 521 err = l2cap_attach_pcb(&sc->sc_int_l, &btmagic_int_proto, sc); 522 if (err) 523 return err; 524 525 err = l2cap_setopt(sc->sc_int_l, &sc->sc_mode); 526 if (err) 527 return err; 528 529 sa.bt_psm = L2CAP_PSM_HID_INTR; 530 err = l2cap_bind_pcb(sc->sc_int_l, &sa); 531 if (err) 532 return err; 533 534 err = l2cap_listen_pcb(sc->sc_int_l); 535 if (err) 536 return err; 537 538 sc->sc_state = BTMAGIC_WAIT_CTL; 539 return 0; 540 } 541 542 /* 543 * start connecting to our device 544 * 545 * bt_lock is held 546 */ 547 static int 548 btmagic_connect(struct btmagic_softc *sc) 549 { 550 struct sockaddr_bt sa; 551 int err; 552 553 memset(&sa, 0, sizeof(sa)); 554 sa.bt_len = sizeof(sa); 555 sa.bt_family = AF_BLUETOOTH; 556 557 err = l2cap_attach_pcb(&sc->sc_ctl, &btmagic_ctl_proto, sc); 558 if (err) { 559 printf("%s: l2cap_attach failed (%d)\n", 560 device_xname(sc->sc_dev), err); 561 return err; 562 } 563 564 err = l2cap_setopt(sc->sc_ctl, &sc->sc_mode); 565 if (err) { 566 printf("%s: l2cap_setopt failed (%d)\n", 567 device_xname(sc->sc_dev), err); 568 return err; 569 } 570 571 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); 572 err = l2cap_bind_pcb(sc->sc_ctl, &sa); 573 if (err) { 574 printf("%s: l2cap_bind_pcb failed (%d)\n", 575 device_xname(sc->sc_dev), err); 576 return err; 577 } 578 579 sa.bt_psm = L2CAP_PSM_HID_CNTL; 580 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr); 581 err = l2cap_connect_pcb(sc->sc_ctl, &sa); 582 if (err) { 583 printf("%s: l2cap_connect_pcb failed (%d)\n", 584 device_xname(sc->sc_dev), err); 585 return err; 586 } 587 588 SET(sc->sc_flags, BTMAGIC_CONNECTING); 589 sc->sc_state = BTMAGIC_WAIT_CTL; 590 return 0; 591 } 592 593 /* validate soft_resolution */ 594 static int 595 btmagic_sysctl_resolution(SYSCTLFN_ARGS) 596 { 597 struct sysctlnode node; 598 struct btmagic_softc *sc; 599 int t, error; 600 601 node = *rnode; 602 sc = node.sysctl_data; 603 604 t = sc->sc_resolution; 605 node.sysctl_data = &t; 606 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 607 if (error || newp == NULL) 608 return error; 609 610 if (t < 100 || t > 4000 || (t / sc->sc_scale) == 0) 611 return EINVAL; 612 613 sc->sc_resolution = t; 614 DPRINTF(sc, "sc_resolution = %u", t); 615 return 0; 616 } 617 618 /* validate scroll_downscale_factor */ 619 static int 620 btmagic_sysctl_scale(SYSCTLFN_ARGS) 621 { 622 struct sysctlnode node; 623 struct btmagic_softc *sc; 624 int t, error; 625 626 node = *rnode; 627 sc = node.sysctl_data; 628 629 t = sc->sc_scale; 630 node.sysctl_data = &t; 631 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 632 if (error || newp == NULL) 633 return error; 634 635 if (t < 1 || t > 40 || (sc->sc_resolution / t) == 0) 636 return EINVAL; 637 638 sc->sc_scale = t; 639 DPRINTF(sc, "sc_scale = %u", t); 640 return 0; 641 } 642 643 /* validate tap timeout */ 644 static int 645 btmagic_sysctl_taptimeout(SYSCTLFN_ARGS) 646 { 647 struct sysctlnode node; 648 struct btmagic_softc *sc; 649 int t, error; 650 651 node = *rnode; 652 sc = node.sysctl_data; 653 654 t = sc->sc_taptimeout; 655 node.sysctl_data = &t; 656 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 657 if (error || newp == NULL) 658 return error; 659 660 if (t < uimax(1000 / hz, 1) || t > 999) 661 return EINVAL; 662 663 sc->sc_taptimeout = t; 664 DPRINTF(sc, "taptimeout = %u", t); 665 return 0; 666 } 667 668 /***************************************************************************** 669 * 670 * wsmouse(4) accessops 671 */ 672 673 static int 674 btmagic_wsmouse_enable(void *self) 675 { 676 struct btmagic_softc *sc = device_private(self); 677 678 if (sc->sc_enabled) 679 return EBUSY; 680 681 sc->sc_enabled = 1; 682 DPRINTF(sc, "enable"); 683 return 0; 684 } 685 686 static int 687 btmagic_wsmouse_ioctl(void *self, unsigned long cmd, void *data, 688 int flag, struct lwp *l) 689 { 690 /* struct btmagic_softc *sc = device_private(self); */ 691 int err; 692 693 switch (cmd) { 694 case WSMOUSEIO_GTYPE: 695 *(uint *)data = WSMOUSE_TYPE_BLUETOOTH; 696 err = 0; 697 break; 698 699 default: 700 err = EPASSTHROUGH; 701 break; 702 } 703 704 return err; 705 } 706 707 static void 708 btmagic_wsmouse_disable(void *self) 709 { 710 struct btmagic_softc *sc = device_private(self); 711 712 DPRINTF(sc, "disable"); 713 sc->sc_enabled = 0; 714 } 715 716 717 /***************************************************************************** 718 * 719 * setup routines 720 */ 721 722 static void 723 btmagic_timeout(void *arg) 724 { 725 struct btmagic_softc *sc = arg; 726 727 mutex_enter(bt_lock); 728 callout_ack(&sc->sc_timeout); 729 730 switch (sc->sc_state) { 731 case BTMAGIC_CLOSED: 732 if (sc->sc_int != NULL) { 733 l2cap_disconnect_pcb(sc->sc_int, 0); 734 break; 735 } 736 737 if (sc->sc_ctl != NULL) { 738 l2cap_disconnect_pcb(sc->sc_ctl, 0); 739 break; 740 } 741 break; 742 743 case BTMAGIC_OPEN: 744 if (!ISSET(sc->sc_flags, BTMAGIC_ENABLED)) { 745 btmagic_enable(sc); 746 break; 747 } 748 749 btmagic_check_battery(sc); 750 break; 751 752 case BTMAGIC_WAIT_CTL: 753 case BTMAGIC_WAIT_INT: 754 default: 755 break; 756 } 757 mutex_exit(bt_lock); 758 } 759 760 /* 761 * Send report on control channel 762 * 763 * bt_lock is held 764 */ 765 static int 766 btmagic_ctl_send(struct btmagic_softc *sc, const uint8_t *data, size_t len) 767 { 768 struct mbuf *m; 769 770 if (len > MLEN) 771 return EINVAL; 772 773 m = m_gethdr(M_DONTWAIT, MT_DATA); 774 if (m == NULL) 775 return ENOMEM; 776 777 #ifdef BTMAGIC_DEBUG 778 printf("%s: send", device_xname(sc->sc_dev)); 779 for (size_t i = 0; i < len; i++) 780 printf(" 0x%02x", data[i]); 781 printf("\n"); 782 #endif 783 784 memcpy(mtod(m, uint8_t *), data, len); 785 m->m_pkthdr.len = m->m_len = len; 786 return l2cap_send_pcb(sc->sc_ctl, m); 787 } 788 789 /* 790 * Enable touch reports by sending the following report 791 * 792 * SET_REPORT(FEATURE, 0xd7) = 0x01 793 * 794 * bt_lock is held 795 */ 796 static void 797 btmagic_enable(struct btmagic_softc *sc) 798 { 799 static const uint8_t rep[] = { 0x53, 0xd7, 0x01 }; 800 801 if (btmagic_ctl_send(sc, rep, sizeof(rep)) != 0) { 802 printf("%s: cannot enable touch reports\n", 803 device_xname(sc->sc_dev)); 804 805 return; 806 } 807 808 SET(sc->sc_flags, BTMAGIC_ENABLED); 809 } 810 811 /* 812 * Request the battery level by sending the following report 813 * 814 * GET_REPORT(FEATURE, 0x47) 815 * 816 * bt_lock is held 817 */ 818 static void 819 btmagic_check_battery(struct btmagic_softc *sc) 820 { 821 static const uint8_t rep[] = { 0x43, 0x47 }; 822 823 if (btmagic_ctl_send(sc, rep, sizeof(rep)) != 0) 824 printf("%s: cannot request battery level\n", 825 device_xname(sc->sc_dev)); 826 } 827 828 /* 829 * the Magic Mouse has a base resolution of 1300dpi which is rather flighty. We 830 * scale the output to the requested resolution, taking care to account for the 831 * remainders to prevent loss of small deltas. 832 */ 833 static int 834 btmagic_scale(int delta, int *remainder, int resolution) 835 { 836 int new; 837 838 delta += *remainder; 839 new = delta * resolution / 1300; 840 *remainder = delta - new * 1300 / resolution; 841 return new; 842 } 843 844 845 /***************************************************************************** 846 * 847 * bluetooth(9) callback methods for L2CAP 848 * 849 * All these are called from Bluetooth Protocol code, holding bt_lock. 850 */ 851 852 static void 853 btmagic_connecting(void *arg) 854 { 855 856 /* dont care */ 857 } 858 859 static void 860 btmagic_ctl_connected(void *arg) 861 { 862 struct sockaddr_bt sa; 863 struct btmagic_softc *sc = arg; 864 int err; 865 866 if (sc->sc_state != BTMAGIC_WAIT_CTL) 867 return; 868 869 KASSERT(sc->sc_ctl != NULL); 870 KASSERT(sc->sc_int == NULL); 871 872 if (ISSET(sc->sc_flags, BTMAGIC_CONNECTING)) { 873 /* initiate connect on interrupt PSM */ 874 err = l2cap_attach_pcb(&sc->sc_int, &btmagic_int_proto, sc); 875 if (err) 876 goto fail; 877 878 err = l2cap_setopt(sc->sc_int, &sc->sc_mode); 879 if (err) 880 goto fail; 881 882 memset(&sa, 0, sizeof(sa)); 883 sa.bt_len = sizeof(sa); 884 sa.bt_family = AF_BLUETOOTH; 885 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); 886 887 err = l2cap_bind_pcb(sc->sc_int, &sa); 888 if (err) 889 goto fail; 890 891 sa.bt_psm = L2CAP_PSM_HID_INTR; 892 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr); 893 err = l2cap_connect_pcb(sc->sc_int, &sa); 894 if (err) 895 goto fail; 896 } 897 898 sc->sc_state = BTMAGIC_WAIT_INT; 899 return; 900 901 fail: 902 l2cap_detach_pcb(&sc->sc_ctl); 903 sc->sc_ctl = NULL; 904 905 printf("%s: connect failed (%d)\n", device_xname(sc->sc_dev), err); 906 } 907 908 static void 909 btmagic_int_connected(void *arg) 910 { 911 struct btmagic_softc *sc = arg; 912 913 if (sc->sc_state != BTMAGIC_WAIT_INT) 914 return; 915 916 KASSERT(sc->sc_ctl != NULL); 917 KASSERT(sc->sc_int != NULL); 918 919 printf("%s: connected\n", device_xname(sc->sc_dev)); 920 CLR(sc->sc_flags, BTMAGIC_CONNECTING); 921 sc->sc_state = BTMAGIC_OPEN; 922 923 /* trigger the setup */ 924 CLR(sc->sc_flags, BTMAGIC_ENABLED); 925 callout_schedule(&sc->sc_timeout, hz); 926 } 927 928 /* 929 * Disconnected 930 * 931 * Depending on our state, this could mean several things, but essentially 932 * we are lost. If both channels are closed, schedule another connection. 933 */ 934 static void 935 btmagic_ctl_disconnected(void *arg, int err) 936 { 937 struct btmagic_softc *sc = arg; 938 939 if (sc->sc_ctl != NULL) { 940 l2cap_detach_pcb(&sc->sc_ctl); 941 sc->sc_ctl = NULL; 942 } 943 944 if (sc->sc_int == NULL) { 945 printf("%s: disconnected (%d)\n", device_xname(sc->sc_dev), err); 946 CLR(sc->sc_flags, BTMAGIC_CONNECTING); 947 sc->sc_state = BTMAGIC_WAIT_CTL; 948 } else { 949 /* 950 * The interrupt channel should have been closed first, 951 * but its potentially unsafe to detach that from here. 952 * Give them a second to do the right thing or let the 953 * callout handle it. 954 */ 955 sc->sc_state = BTMAGIC_CLOSED; 956 callout_schedule(&sc->sc_timeout, hz); 957 } 958 } 959 960 static void 961 btmagic_int_disconnected(void *arg, int err) 962 { 963 struct btmagic_softc *sc = arg; 964 965 if (sc->sc_int != NULL) { 966 l2cap_detach_pcb(&sc->sc_int); 967 sc->sc_int = NULL; 968 } 969 970 if (sc->sc_ctl == NULL) { 971 printf("%s: disconnected (%d)\n", device_xname(sc->sc_dev), err); 972 CLR(sc->sc_flags, BTMAGIC_CONNECTING); 973 sc->sc_state = BTMAGIC_WAIT_CTL; 974 } else { 975 /* 976 * The control channel should be closing also, allow 977 * them a chance to do that before we force it. 978 */ 979 sc->sc_state = BTMAGIC_CLOSED; 980 callout_schedule(&sc->sc_timeout, hz); 981 } 982 } 983 984 /* 985 * New Connections 986 * 987 * We give a new L2CAP handle back if this matches the BDADDR we are 988 * listening for and we are in the right state. btmagic_connected will 989 * be called when the connection is open, so nothing else to do here 990 */ 991 static void * 992 btmagic_ctl_newconn(void *arg, struct sockaddr_bt *laddr, 993 struct sockaddr_bt *raddr) 994 { 995 struct btmagic_softc *sc = arg; 996 997 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0) 998 return NULL; 999 1000 if (sc->sc_state != BTMAGIC_WAIT_CTL 1001 || ISSET(sc->sc_flags, BTMAGIC_CONNECTING) 1002 || sc->sc_ctl != NULL 1003 || sc->sc_int != NULL) { 1004 DPRINTF(sc, "reject ctl newconn %s%s%s%s", 1005 (sc->sc_state == BTMAGIC_WAIT_CTL) ? " (WAITING)": "", 1006 ISSET(sc->sc_flags, BTMAGIC_CONNECTING) ? " (CONNECTING)" : "", 1007 (sc->sc_ctl != NULL) ? " (GOT CONTROL)" : "", 1008 (sc->sc_int != NULL) ? " (GOT INTERRUPT)" : ""); 1009 1010 return NULL; 1011 } 1012 1013 l2cap_attach_pcb(&sc->sc_ctl, &btmagic_ctl_proto, sc); 1014 return sc->sc_ctl; 1015 } 1016 1017 static void * 1018 btmagic_int_newconn(void *arg, struct sockaddr_bt *laddr, 1019 struct sockaddr_bt *raddr) 1020 { 1021 struct btmagic_softc *sc = arg; 1022 1023 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0) 1024 return NULL; 1025 1026 if (sc->sc_state != BTMAGIC_WAIT_INT 1027 || ISSET(sc->sc_flags, BTMAGIC_CONNECTING) 1028 || sc->sc_ctl == NULL 1029 || sc->sc_int != NULL) { 1030 DPRINTF(sc, "reject int newconn %s%s%s%s", 1031 (sc->sc_state == BTMAGIC_WAIT_INT) ? " (WAITING)": "", 1032 ISSET(sc->sc_flags, BTMAGIC_CONNECTING) ? " (CONNECTING)" : "", 1033 (sc->sc_ctl == NULL) ? " (NO CONTROL)" : "", 1034 (sc->sc_int != NULL) ? " (GOT INTERRUPT)" : ""); 1035 1036 return NULL; 1037 } 1038 1039 l2cap_attach_pcb(&sc->sc_int, &btmagic_int_proto, sc); 1040 return sc->sc_int; 1041 } 1042 1043 static void 1044 btmagic_complete(void *arg, int count) 1045 { 1046 1047 /* dont care */ 1048 } 1049 1050 static void 1051 btmagic_linkmode(void *arg, int new) 1052 { 1053 struct btmagic_softc *sc = arg; 1054 int mode; 1055 1056 (void)sockopt_getint(&sc->sc_mode, &mode); 1057 1058 if (ISSET(mode, L2CAP_LM_AUTH) && !ISSET(new, L2CAP_LM_AUTH)) 1059 printf("%s: auth failed\n", device_xname(sc->sc_dev)); 1060 else if (ISSET(mode, L2CAP_LM_ENCRYPT) && !ISSET(new, L2CAP_LM_ENCRYPT)) 1061 printf("%s: encrypt off\n", device_xname(sc->sc_dev)); 1062 else if (ISSET(mode, L2CAP_LM_SECURE) && !ISSET(new, L2CAP_LM_SECURE)) 1063 printf("%s: insecure\n", device_xname(sc->sc_dev)); 1064 else 1065 return; 1066 1067 if (sc->sc_int != NULL) 1068 l2cap_disconnect_pcb(sc->sc_int, 0); 1069 1070 if (sc->sc_ctl != NULL) 1071 l2cap_disconnect_pcb(sc->sc_ctl, 0); 1072 } 1073 1074 /* 1075 * Receive transaction from the mouse. We don't differentiate between 1076 * interrupt and control channel here, there is no need. 1077 */ 1078 static void 1079 btmagic_input(void *arg, struct mbuf *m) 1080 { 1081 struct btmagic_softc *sc = arg; 1082 uint8_t *data; 1083 size_t len; 1084 1085 if (sc->sc_state != BTMAGIC_OPEN 1086 || sc->sc_wsmouse == NULL 1087 || sc->sc_enabled == 0) 1088 goto release; 1089 1090 if (m->m_pkthdr.len > m->m_len) 1091 printf("%s: truncating input\n", device_xname(sc->sc_dev)); 1092 1093 data = mtod(m, uint8_t *); 1094 len = m->m_len; 1095 1096 if (len < 1) 1097 goto release; 1098 1099 switch (BTHID_TYPE(data[0])) { 1100 case BTHID_HANDSHAKE: 1101 DPRINTF(sc, "Handshake: 0x%x", BTHID_HANDSHAKE_PARAM(data[0])); 1102 callout_schedule(&sc->sc_timeout, hz); 1103 break; 1104 1105 case BTHID_DATA: 1106 if (len < 2) 1107 break; 1108 1109 switch (data[1]) { 1110 case BASIC_REPORT_ID: /* Basic mouse (input) */ 1111 btmagic_input_basic(sc, data + 2, len - 2); 1112 break; 1113 1114 case TRACKPAD_REPORT_ID: /* Magic trackpad (input) */ 1115 btmagic_input_magict(sc, data + 2, len - 2); 1116 break; 1117 1118 case MOUSE_REPORT_ID: /* Magic touch (input) */ 1119 btmagic_input_magicm(sc, data + 2, len - 2); 1120 break; 1121 1122 case BATT_STAT_REPORT_ID: /* Battery status (input) */ 1123 if (len != 3) 1124 break; 1125 1126 printf("%s: Battery ", device_xname(sc->sc_dev)); 1127 switch (data[2]) { 1128 case 0: printf("Ok\n"); break; 1129 case 1: printf("Warning\n"); break; 1130 case 2: printf("Critical\n"); break; 1131 default: printf("0x%02x\n", data[2]); break; 1132 } 1133 break; 1134 1135 case BATT_STRENGTH_REPORT_ID: /* Battery strength (feature) */ 1136 if (len != 3) 1137 break; 1138 1139 printf("%s: Battery %d%%\n", device_xname(sc->sc_dev), 1140 data[2]); 1141 break; 1142 1143 case SURFACE_REPORT_ID: /* Surface detection (input) */ 1144 if (len != 3) 1145 break; 1146 1147 DPRINTF(sc, "Mouse %s", 1148 (data[2] == 0 ? "lowered" : "raised")); 1149 break; 1150 1151 case 0x60: /* unknown (input) */ 1152 case 0xf0: /* unknown (feature) */ 1153 case 0xf1: /* unknown (feature) */ 1154 default: 1155 #if BTMAGIC_DEBUG 1156 printf("%s: recv", device_xname(sc->sc_dev)); 1157 for (size_t i = 0; i < len; i++) 1158 printf(" 0x%02x", data[i]); 1159 printf("\n"); 1160 #endif 1161 break; 1162 } 1163 break; 1164 1165 default: 1166 DPRINTF(sc, "transaction (type 0x%x)", BTHID_TYPE(data[0])); 1167 break; 1168 } 1169 1170 release: 1171 m_freem(m); 1172 } 1173 1174 /* 1175 * parse the Basic report (0x10), which according to the provided 1176 * HID descriptor is in the following format 1177 * 1178 * button 1 1-bit 1179 * button 2 1-bit 1180 * padding 6-bits 1181 * dX 16-bits (signed) 1182 * dY 16-bits (signed) 1183 * 1184 * Even when the magic touch reports are enabled, the basic report is 1185 * sent for mouse move events where no touches are detected. 1186 */ 1187 static const struct { 1188 struct hid_location button1; 1189 struct hid_location button2; 1190 struct hid_location dX; 1191 struct hid_location dY; 1192 } basic = { 1193 .button1 = { .pos = 0, .size = 1 }, 1194 .button2 = { .pos = 1, .size = 1 }, 1195 .dX = { .pos = 8, .size = 16 }, 1196 .dY = { .pos = 24, .size = 16 }, 1197 }; 1198 1199 static void 1200 btmagic_input_basic(struct btmagic_softc *sc, uint8_t *data, size_t len) 1201 { 1202 int dx, dy; 1203 uint32_t mb; 1204 int s; 1205 1206 if (len != 5) 1207 return; 1208 1209 dx = hid_get_data(data, &basic.dX); 1210 dx = btmagic_scale(dx, &sc->sc_rx, sc->sc_resolution); 1211 1212 dy = hid_get_data(data, &basic.dY); 1213 dy = btmagic_scale(dy, &sc->sc_ry, sc->sc_resolution); 1214 1215 mb = 0; 1216 if (hid_get_udata(data, &basic.button1)) 1217 mb |= __BIT(0); 1218 if (hid_get_udata(data, &basic.button2)) 1219 mb |= __BIT(2); 1220 1221 if (dx != 0 || dy != 0 || mb != sc->sc_mb) { 1222 sc->sc_mb = mb; 1223 1224 s = spltty(); 1225 wsmouse_input(sc->sc_wsmouse, mb, 1226 dx, -dy, 0, 0, WSMOUSE_INPUT_DELTA); 1227 splx(s); 1228 } 1229 } 1230 1231 /* 1232 * the Magic touch report (0x29), according to the Linux driver 1233 * written by Michael Poole, is variable length starting with the 1234 * fixed 40-bit header 1235 * 1236 * dX lsb 8-bits (signed) 1237 * dY lsb 8-bits (signed) 1238 * button 1 1-bit 1239 * button 2 1-bit 1240 * dX msb 2-bits (signed) 1241 * dY msb 2-bits (signed) 1242 * timestamp 18-bits 1243 * 1244 * followed by (up to 5?) touch reports of 64-bits each 1245 * 1246 * abs W 12-bits (signed) 1247 * abs Z 12-bits (signed) 1248 * axis major 8-bits 1249 * axis minor 8-bits 1250 * pressure 6-bits 1251 * id 4-bits 1252 * angle 6-bits (from E(0)->N(32)->W(64)) 1253 * unknown 4-bits 1254 * phase 4-bits 1255 */ 1256 1257 static const struct { 1258 struct hid_location dXl; 1259 struct hid_location dYl; 1260 struct hid_location button1; 1261 struct hid_location button2; 1262 struct hid_location dXm; 1263 struct hid_location dYm; 1264 struct hid_location timestamp; 1265 } magic = { 1266 .dXl = { .pos = 0, .size = 8 }, 1267 .dYl = { .pos = 8, .size = 8 }, 1268 .button1 = { .pos = 16, .size = 1 }, 1269 .button2 = { .pos = 17, .size = 1 }, 1270 .dXm = { .pos = 18, .size = 2 }, 1271 .dYm = { .pos = 20, .size = 2 }, 1272 .timestamp = { .pos = 22, .size = 18 }, 1273 }; 1274 1275 static const struct { 1276 struct hid_location aW; 1277 struct hid_location aZ; 1278 struct hid_location major; 1279 struct hid_location minor; 1280 struct hid_location pressure; 1281 struct hid_location id; 1282 struct hid_location angle; 1283 struct hid_location unknown; 1284 struct hid_location phase; 1285 } touch = { 1286 .aW = { .pos = 0, .size = 12 }, 1287 .aZ = { .pos = 12, .size = 12 }, 1288 .major = { .pos = 24, .size = 8 }, 1289 .minor = { .pos = 32, .size = 8 }, 1290 .pressure = { .pos = 40, .size = 6 }, 1291 .id = { .pos = 46, .size = 4 }, 1292 .angle = { .pos = 50, .size = 6 }, 1293 .unknown = { .pos = 56, .size = 4 }, 1294 .phase = { .pos = 60, .size = 4 }, 1295 }; 1296 1297 /* 1298 * the phase of the touch starts at 0x01 as the finger is first detected 1299 * approaching the mouse, increasing to 0x04 while the finger is touching, 1300 * then increases towards 0x07 as the finger is lifted, and we get 0x00 1301 * when the touch is cancelled. The values below seem to be produced for 1302 * every touch, the others less consistently depending on how fast the 1303 * approach or departure is. 1304 * 1305 * In fact we ignore touches unless they are in the steady 0x04 phase. 1306 */ 1307 #define BTMAGIC_PHASE_START 0x3 1308 #define BTMAGIC_PHASE_CONT 0x4 1309 #define BTMAGIC_PHASE_END 0x7 1310 #define BTMAGIC_PHASE_CANCEL 0x0 1311 1312 static void 1313 btmagic_input_magicm(struct btmagic_softc *sc, uint8_t *data, size_t len) 1314 { 1315 uint32_t mb; 1316 int dx, dy, dz, dw; 1317 int id, nf, az, aw, tz, tw; 1318 int s; 1319 1320 if (((len - 5) % 8) != 0) 1321 return; 1322 1323 dx = (hid_get_data(data, &magic.dXm) << 8) 1324 | (hid_get_data(data, &magic.dXl) & 0xff); 1325 dx = btmagic_scale(dx, &sc->sc_rx, sc->sc_resolution); 1326 1327 dy = (hid_get_data(data, &magic.dYm) << 8) 1328 | (hid_get_data(data, &magic.dYl) & 0xff); 1329 dy = btmagic_scale(dy, &sc->sc_ry, sc->sc_resolution); 1330 1331 mb = 0; 1332 if (hid_get_udata(data, &magic.button1)) 1333 mb |= __BIT(0); 1334 if (hid_get_udata(data, &magic.button2)) 1335 mb |= __BIT(2); 1336 1337 nf = 0; 1338 dz = 0; 1339 dw = 0; 1340 len = (len - 5) / 8; 1341 for (data += 5; len-- > 0; data += 8) { 1342 id = hid_get_udata(data, &touch.id); 1343 az = hid_get_data(data, &touch.aZ); 1344 aw = hid_get_data(data, &touch.aW); 1345 1346 /* 1347 * scrolling is triggered by an established touch moving 1348 * beyond a minimum distance from its start point and is 1349 * cancelled as the touch starts to fade. 1350 * 1351 * Multiple touches may be scrolling simultaneously, the 1352 * effect is cumulative. 1353 */ 1354 1355 switch (hid_get_udata(data, &touch.phase)) { 1356 case BTMAGIC_PHASE_CONT: 1357 #define sc_az sc_ay 1358 #define sc_aw sc_ax 1359 tz = az - sc->sc_az[id]; 1360 tw = aw - sc->sc_aw[id]; 1361 1362 if (ISSET(sc->sc_smask, __BIT(id))) { 1363 /* scrolling finger */ 1364 dz += btmagic_scale(tz, &sc->sc_rz, 1365 sc->sc_resolution / sc->sc_scale); 1366 dw += btmagic_scale(tw, &sc->sc_rw, 1367 sc->sc_resolution / sc->sc_scale); 1368 } else if (abs(tz) > sc->sc_dist 1369 || abs(tw) > sc->sc_dist) { 1370 /* new scrolling finger */ 1371 if (sc->sc_smask == 0) { 1372 sc->sc_rz = 0; 1373 sc->sc_rw = 0; 1374 } 1375 1376 SET(sc->sc_smask, __BIT(id)); 1377 } else { 1378 /* not scrolling finger */ 1379 az = sc->sc_az[id]; 1380 aw = sc->sc_aw[id]; 1381 } 1382 1383 /* count firm touches for middle-click */ 1384 if (hid_get_udata(data, &touch.pressure) > sc->sc_firm) 1385 nf++; 1386 1387 break; 1388 1389 default: 1390 CLR(sc->sc_smask, __BIT(id)); 1391 break; 1392 } 1393 1394 sc->sc_az[id] = az; 1395 sc->sc_aw[id] = aw; 1396 #undef sc_az 1397 #undef sc_aw 1398 } 1399 1400 /* 1401 * The mouse only has one click detector, and says left or right but 1402 * never both. We convert multiple firm touches while clicking into 1403 * a middle button press, and cancel any scroll effects while click 1404 * is active. 1405 */ 1406 if (mb != 0) { 1407 if (sc->sc_mb != 0) 1408 mb = sc->sc_mb; 1409 else if (nf > 1) 1410 mb = __BIT(1); 1411 1412 sc->sc_smask = 0; 1413 dz = 0; 1414 dw = 0; 1415 } 1416 1417 if (dx != 0 || dy != 0 || dz != 0 || dw != 0 || mb != sc->sc_mb) { 1418 sc->sc_mb = mb; 1419 1420 s = spltty(); 1421 wsmouse_input(sc->sc_wsmouse, mb, 1422 dx, -dy, -dz, dw, WSMOUSE_INPUT_DELTA); 1423 splx(s); 1424 } 1425 } 1426 1427 /* 1428 * the Magic touch trackpad report (0x28), according to the Linux driver 1429 * written by Michael Poole and Chase Douglas, is variable length starting 1430 * with the fixed 24-bit header 1431 * 1432 * button 1 1-bit 1433 * unknown 5-bits 1434 * timestamp 18-bits 1435 * 1436 * followed by (up to 5?) touch reports of 72-bits each 1437 * 1438 * abs X 13-bits (signed) 1439 * abs Y 13-bits (signed) 1440 * unknown 6-bits 1441 * axis major 8-bits 1442 * axis minor 8-bits 1443 * pressure 6-bits 1444 * id 4-bits 1445 * angle 6-bits (from E(0)->N(32)->W(64)) 1446 * unknown 4-bits 1447 * phase 4-bits 1448 */ 1449 1450 static const struct { 1451 struct hid_location button; 1452 struct hid_location timestamp; 1453 } magict = { 1454 .button = { .pos = 0, .size = 1 }, 1455 .timestamp = { .pos = 6, .size = 18 }, 1456 }; 1457 1458 static const struct { 1459 struct hid_location aX; 1460 struct hid_location aY; 1461 struct hid_location major; 1462 struct hid_location minor; 1463 struct hid_location pressure; 1464 struct hid_location id; 1465 struct hid_location angle; 1466 struct hid_location unknown; 1467 struct hid_location phase; 1468 } toucht = { 1469 .aX = { .pos = 0, .size = 13 }, 1470 .aY = { .pos = 13, .size = 13 }, 1471 .major = { .pos = 32, .size = 8 }, 1472 .minor = { .pos = 40, .size = 8 }, 1473 .pressure = { .pos = 48, .size = 6 }, 1474 .id = { .pos = 54, .size = 4 }, 1475 .angle = { .pos = 58, .size = 6 }, 1476 .unknown = { .pos = 64, .size = 4 }, 1477 .phase = { .pos = 68, .size = 4 }, 1478 }; 1479 1480 /* 1481 * as for btmagic_input_magicm, 1482 * the phase of the touch starts at 0x01 as the finger is first detected 1483 * approaching the mouse, increasing to 0x04 while the finger is touching, 1484 * then increases towards 0x07 as the finger is lifted, and we get 0x00 1485 * when the touch is cancelled. The values below seem to be produced for 1486 * every touch, the others less consistently depending on how fast the 1487 * approach or departure is. 1488 * 1489 * In fact we ignore touches unless they are in the steady 0x04 phase. 1490 */ 1491 1492 /* min and max values reported */ 1493 #define MAGICT_X_MIN (-2910) 1494 #define MAGICT_X_MAX (3170) 1495 #define MAGICT_Y_MIN (-2565) 1496 #define MAGICT_Y_MAX (2455) 1497 1498 /* 1499 * area for detecting the buttons: divide in 3 areas on X, 1500 * below -1900 on y 1501 */ 1502 #define MAGICT_B_YMAX (-1900) 1503 #define MAGICT_B_XSIZE ((MAGICT_X_MAX - MAGICT_X_MIN) / 3) 1504 #define MAGICT_B_X1MAX (MAGICT_X_MIN + MAGICT_B_XSIZE) 1505 #define MAGICT_B_X2MAX (MAGICT_X_MIN + MAGICT_B_XSIZE * 2) 1506 1507 static void 1508 btmagic_input_magict(struct btmagic_softc *sc, uint8_t *data, size_t len) 1509 { 1510 bool bpress; 1511 uint32_t mb; 1512 int id, ax, ay, tx, ty; 1513 int dx, dy, dz, dw; 1514 int s; 1515 1516 if (((len - 3) % 9) != 0) 1517 return; 1518 1519 bpress = 0; 1520 if (hid_get_udata(data, &magict.button)) 1521 bpress = 1; 1522 1523 dx = dy = dz = dw = 0; 1524 mb = 0; 1525 1526 len = (len - 3) / 9; 1527 for (data += 3; len-- > 0; data += 9) { 1528 id = hid_get_udata(data, &toucht.id); 1529 ax = hid_get_data(data, &toucht.aX); 1530 ay = hid_get_data(data, &toucht.aY); 1531 1532 DPRINTF(sc, 1533 "btmagic_input_magict: id %d ax %d ay %d phase %ld %s\n", 1534 id, ax, ay, hid_get_udata(data, &toucht.phase), 1535 bpress ? "button pressed" : ""); 1536 1537 /* 1538 * a single touch is interpreted as a mouse move. 1539 * If a button is pressed, the touch in the button area 1540 * defined above defines the button; a second touch is 1541 * interpreted as a mouse move. 1542 */ 1543 1544 switch (hid_get_udata(data, &toucht.phase)) { 1545 case BTMAGIC_PHASE_CONT: 1546 if (bpress) { 1547 if (sc->sc_mb == 0 && ay < MAGICT_B_YMAX) { 1548 /* 1549 * we have a new button press, 1550 * and this id tells which one 1551 */ 1552 if (ax < MAGICT_B_X1MAX) 1553 mb = __BIT(0); 1554 else if (ax > MAGICT_B_X2MAX) 1555 mb = __BIT(2); 1556 else 1557 mb = __BIT(1); 1558 sc->sc_mb_id = id; 1559 } else { 1560 /* keep previous state */ 1561 mb = sc->sc_mb; 1562 } 1563 } else { 1564 /* no button pressed */ 1565 mb = 0; 1566 sc->sc_mb_id = -1; 1567 } 1568 if (id == sc->sc_mb_id) { 1569 /* 1570 * this id selects the button 1571 * ignore for move/scroll 1572 */ 1573 continue; 1574 } 1575 if (id >= __arraycount(sc->sc_ax)) 1576 continue; 1577 1578 tx = ax - sc->sc_ax[id]; 1579 ty = ay - sc->sc_ay[id]; 1580 1581 if (ISSET(sc->sc_smask, __BIT(id))) { 1582 struct timeval now_tv; 1583 getmicrotime(&now_tv); 1584 if (sc->sc_nfingers == 1 && mb == 0 && 1585 timercmp(&sc->sc_taptime, &now_tv, >)) { 1586 /* still detecting a tap */ 1587 continue; 1588 } 1589 1590 if (sc->sc_nfingers == 1 || mb != 0) { 1591 /* single finger moving */ 1592 dx += btmagic_scale(tx, &sc->sc_rx, 1593 sc->sc_resolution); 1594 dy += btmagic_scale(ty, &sc->sc_ry, 1595 sc->sc_resolution); 1596 } else { 1597 /* scrolling fingers */ 1598 dz += btmagic_scale(ty, &sc->sc_rz, 1599 sc->sc_resolution / sc->sc_scale); 1600 dw += btmagic_scale(tx, &sc->sc_rw, 1601 sc->sc_resolution / sc->sc_scale); 1602 } 1603 } else if (ay > MAGICT_B_YMAX) { /* new finger */ 1604 sc->sc_rx = 0; 1605 sc->sc_ry = 0; 1606 sc->sc_rz = 0; 1607 sc->sc_rw = 0; 1608 KASSERT(!ISSET(sc->sc_smask, __BIT(id))); 1609 SET(sc->sc_smask, __BIT(id)); 1610 sc->sc_nfingers++; 1611 if (sc->sc_tapmb_id == -1 && 1612 mb == 0 && sc->sc_mb == 0) { 1613 sc->sc_tapmb_id = id; 1614 getmicrotime(&sc->sc_taptime); 1615 sc->sc_taptime.tv_usec += 1616 sc->sc_taptimeout * 1000; 1617 if (sc->sc_taptime.tv_usec > 1000000) { 1618 sc->sc_taptime.tv_usec -= 1619 1000000; 1620 sc->sc_taptime.tv_sec++; 1621 } 1622 } 1623 1624 } 1625 1626 break; 1627 default: 1628 if (ISSET(sc->sc_smask, __BIT(id))) { 1629 CLR(sc->sc_smask, __BIT(id)); 1630 sc->sc_nfingers--; 1631 KASSERT(sc->sc_nfingers >= 0); 1632 if (id == sc->sc_tapmb_id) { 1633 mb = btmagic_tap(sc, id); 1634 } 1635 } 1636 break; 1637 } 1638 1639 if (id >= __arraycount(sc->sc_ax)) 1640 continue; 1641 1642 sc->sc_ax[id] = ax; 1643 sc->sc_ay[id] = ay; 1644 } 1645 1646 if (dx != 0 || dy != 0 || dz != 0 || dw != 0 || mb != sc->sc_mb) { 1647 sc->sc_mb = mb; 1648 1649 s = spltty(); 1650 wsmouse_input(sc->sc_wsmouse, mb, 1651 dx, dy, -dz, dw, WSMOUSE_INPUT_DELTA); 1652 splx(s); 1653 } 1654 } 1655 1656 static int 1657 btmagic_tap(struct btmagic_softc *sc, int id) 1658 { 1659 struct timeval now_tv; 1660 1661 sc->sc_tapmb_id = -1; 1662 getmicrotime(&now_tv); 1663 if (timercmp(&sc->sc_taptime, &now_tv, >)) { 1664 /* got a tap */ 1665 callout_schedule( 1666 &sc->sc_tapcallout, 1667 mstohz(sc->sc_taptimeout)); 1668 return __BIT(0); 1669 } 1670 return 0; 1671 } 1672 1673 static void 1674 btmagic_tapcallout(void *arg) 1675 { 1676 struct btmagic_softc *sc = arg; 1677 int s; 1678 1679 mutex_enter(bt_lock); 1680 callout_ack(&sc->sc_tapcallout); 1681 if ((sc->sc_mb & __BIT(0)) != 0) { 1682 sc->sc_mb &= ~__BIT(0); 1683 s = spltty(); 1684 wsmouse_input(sc->sc_wsmouse, sc->sc_mb, 1685 0, 0, 0, 0, WSMOUSE_INPUT_DELTA); 1686 splx(s); 1687 } 1688 mutex_exit(bt_lock); 1689 } 1690