1 /* $NetBSD: btmagic.c,v 1.21 2021/08/07 16:19:09 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.21 2021/08/07 16:19:09 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
btmagic_match(device_t self,cfdata_t cfdata,void * aux)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
btmagic_attach(device_t parent,device_t self,void * aux)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, CFARGS_NONE);
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
btmagic_detach(device_t self,int flags)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
btmagic_listen(struct btmagic_softc * sc)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
btmagic_connect(struct btmagic_softc * sc)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
btmagic_sysctl_resolution(SYSCTLFN_ARGS)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
btmagic_sysctl_scale(SYSCTLFN_ARGS)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
btmagic_sysctl_taptimeout(SYSCTLFN_ARGS)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
btmagic_wsmouse_enable(void * self)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
btmagic_wsmouse_ioctl(void * self,unsigned long cmd,void * data,int flag,struct lwp * l)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
btmagic_wsmouse_disable(void * self)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
btmagic_timeout(void * arg)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
btmagic_ctl_send(struct btmagic_softc * sc,const uint8_t * data,size_t len)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
btmagic_enable(struct btmagic_softc * sc)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
btmagic_check_battery(struct btmagic_softc * sc)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
btmagic_scale(int delta,int * remainder,int resolution)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
btmagic_connecting(void * arg)853 btmagic_connecting(void *arg)
854 {
855
856 /* dont care */
857 }
858
859 static void
btmagic_ctl_connected(void * arg)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
btmagic_int_connected(void * arg)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
btmagic_ctl_disconnected(void * arg,int err)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
btmagic_int_disconnected(void * arg,int err)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 *
btmagic_ctl_newconn(void * arg,struct sockaddr_bt * laddr,struct sockaddr_bt * raddr)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 *
btmagic_int_newconn(void * arg,struct sockaddr_bt * laddr,struct sockaddr_bt * raddr)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
btmagic_complete(void * arg,int count)1044 btmagic_complete(void *arg, int count)
1045 {
1046
1047 /* dont care */
1048 }
1049
1050 static void
btmagic_linkmode(void * arg,int new)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
btmagic_input(void * arg,struct mbuf * m)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
btmagic_input_basic(struct btmagic_softc * sc,uint8_t * data,size_t len)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
btmagic_input_magicm(struct btmagic_softc * sc,uint8_t * data,size_t len)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
btmagic_input_magict(struct btmagic_softc * sc,uint8_t * data,size_t len)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
btmagic_tap(struct btmagic_softc * sc,int id)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
btmagic_tapcallout(void * arg)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