btmagic.c revision 1.10 1 /* $NetBSD: btmagic.c,v 1.10 2014/07/31 03:39:35 rtr 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 (at) 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.10 2014/07/31 03:39:35 rtr 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/usb/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; /* scrolling */
167 int sc_az[16];
168 int sc_aw[16];
169
170 /* previous mouse buttons */
171 uint32_t sc_mb;
172 };
173
174 /* sc_flags */
175 #define BTMAGIC_CONNECTING __BIT(0) /* we are connecting */
176 #define BTMAGIC_ENABLED __BIT(1) /* touch reports enabled */
177
178 /* sc_state */
179 #define BTMAGIC_CLOSED 0
180 #define BTMAGIC_WAIT_CTL 1
181 #define BTMAGIC_WAIT_INT 2
182 #define BTMAGIC_OPEN 3
183
184 /* autoconf(9) glue */
185 static int btmagic_match(device_t, cfdata_t, void *);
186 static void btmagic_attach(device_t, device_t, void *);
187 static int btmagic_detach(device_t, int);
188 static int btmagic_listen(struct btmagic_softc *);
189 static int btmagic_connect(struct btmagic_softc *);
190 static int btmagic_sysctl_resolution(SYSCTLFN_PROTO);
191 static int btmagic_sysctl_scale(SYSCTLFN_PROTO);
192
193 CFATTACH_DECL_NEW(btmagic, sizeof(struct btmagic_softc),
194 btmagic_match, btmagic_attach, btmagic_detach, NULL);
195
196 /* wsmouse(4) accessops */
197 static int btmagic_wsmouse_enable(void *);
198 static int btmagic_wsmouse_ioctl(void *, unsigned long, void *, int, struct lwp *);
199 static void btmagic_wsmouse_disable(void *);
200
201 static const struct wsmouse_accessops btmagic_wsmouse_accessops = {
202 btmagic_wsmouse_enable,
203 btmagic_wsmouse_ioctl,
204 btmagic_wsmouse_disable,
205 };
206
207 /* bluetooth(9) protocol methods for L2CAP */
208 static void btmagic_connecting(void *);
209 static void btmagic_ctl_connected(void *);
210 static void btmagic_int_connected(void *);
211 static void btmagic_ctl_disconnected(void *, int);
212 static void btmagic_int_disconnected(void *, int);
213 static void *btmagic_ctl_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
214 static void *btmagic_int_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
215 static void btmagic_complete(void *, int);
216 static void btmagic_linkmode(void *, int);
217 static void btmagic_input(void *, struct mbuf *);
218 static void btmagic_input_basic(struct btmagic_softc *, uint8_t *, size_t);
219 static void btmagic_input_magic(struct btmagic_softc *, uint8_t *, size_t);
220
221 static const struct btproto btmagic_ctl_proto = {
222 btmagic_connecting,
223 btmagic_ctl_connected,
224 btmagic_ctl_disconnected,
225 btmagic_ctl_newconn,
226 btmagic_complete,
227 btmagic_linkmode,
228 btmagic_input,
229 };
230
231 static const struct btproto btmagic_int_proto = {
232 btmagic_connecting,
233 btmagic_int_connected,
234 btmagic_int_disconnected,
235 btmagic_int_newconn,
236 btmagic_complete,
237 btmagic_linkmode,
238 btmagic_input,
239 };
240
241 /* btmagic internals */
242 static void btmagic_timeout(void *);
243 static int btmagic_ctl_send(struct btmagic_softc *, const uint8_t *, size_t);
244 static void btmagic_enable(struct btmagic_softc *);
245 static void btmagic_check_battery(struct btmagic_softc *);
246 static int btmagic_scale(int, int *, int);
247
248
249 /*****************************************************************************
250 *
251 * Magic Mouse autoconf(9) routines
252 */
253
254 static int
255 btmagic_match(device_t self, cfdata_t cfdata, void *aux)
256 {
257 uint16_t v, p;
258
259 if (prop_dictionary_get_uint16(aux, BTDEVvendor, &v)
260 && prop_dictionary_get_uint16(aux, BTDEVproduct, &p)
261 && v == USB_VENDOR_APPLE
262 && p == USB_PRODUCT_APPLE_MAGICMOUSE)
263 return 2; /* trump bthidev(4) */
264
265 return 0;
266 }
267
268 static void
269 btmagic_attach(device_t parent, device_t self, void *aux)
270 {
271 struct btmagic_softc *sc = device_private(self);
272 struct wsmousedev_attach_args wsma;
273 const struct sysctlnode *node;
274 prop_object_t obj;
275 int err;
276
277 /*
278 * Init softc
279 */
280 sc->sc_dev = self;
281 sc->sc_state = BTMAGIC_CLOSED;
282 callout_init(&sc->sc_timeout, 0);
283 callout_setfunc(&sc->sc_timeout, btmagic_timeout, sc);
284 sockopt_init(&sc->sc_mode, BTPROTO_L2CAP, SO_L2CAP_LM, 0);
285
286 /*
287 * extract config from proplist
288 */
289 obj = prop_dictionary_get(aux, BTDEVladdr);
290 bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj));
291
292 obj = prop_dictionary_get(aux, BTDEVraddr);
293 bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));
294
295 obj = prop_dictionary_get(aux, BTDEVmode);
296 if (prop_object_type(obj) == PROP_TYPE_STRING) {
297 if (prop_string_equals_cstring(obj, BTDEVauth))
298 sockopt_setint(&sc->sc_mode, L2CAP_LM_AUTH);
299 else if (prop_string_equals_cstring(obj, BTDEVencrypt))
300 sockopt_setint(&sc->sc_mode, L2CAP_LM_ENCRYPT);
301 else if (prop_string_equals_cstring(obj, BTDEVsecure))
302 sockopt_setint(&sc->sc_mode, L2CAP_LM_SECURE);
303 else {
304 aprint_error(" unknown %s\n", BTDEVmode);
305 return;
306 }
307
308 aprint_verbose(" %s %s", BTDEVmode,
309 prop_string_cstring_nocopy(obj));
310 } else
311 sockopt_setint(&sc->sc_mode, 0);
312
313 aprint_normal(": 3 buttons, W and Z dirs\n");
314 aprint_naive("\n");
315
316 /*
317 * set defaults
318 */
319 sc->sc_resolution = 650;
320 sc->sc_firm = 6;
321 sc->sc_dist = 130;
322 sc->sc_scale = 20;
323
324 sysctl_createv(&sc->sc_log, 0, NULL, &node,
325 0,
326 CTLTYPE_NODE, device_xname(self),
327 NULL,
328 NULL, 0,
329 NULL, 0,
330 CTL_HW,
331 CTL_CREATE, CTL_EOL);
332
333 if (node != NULL) {
334 sysctl_createv(&sc->sc_log, 0, NULL, NULL,
335 CTLFLAG_READWRITE,
336 CTLTYPE_INT, "soft_resolution",
337 NULL,
338 btmagic_sysctl_resolution, 0,
339 (void *)sc, 0,
340 CTL_HW, node->sysctl_num,
341 CTL_CREATE, CTL_EOL);
342
343 sysctl_createv(&sc->sc_log, 0, NULL, NULL,
344 CTLFLAG_READWRITE,
345 CTLTYPE_INT, "firm_touch_threshold",
346 NULL,
347 NULL, 0,
348 &sc->sc_firm, sizeof(sc->sc_firm),
349 CTL_HW, node->sysctl_num,
350 CTL_CREATE, CTL_EOL);
351
352 sysctl_createv(&sc->sc_log, 0, NULL, NULL,
353 CTLFLAG_READWRITE,
354 CTLTYPE_INT, "scroll_distance_threshold",
355 NULL,
356 NULL, 0,
357 &sc->sc_dist, sizeof(sc->sc_dist),
358 CTL_HW, node->sysctl_num,
359 CTL_CREATE, CTL_EOL);
360
361 sysctl_createv(&sc->sc_log, 0, NULL, NULL,
362 CTLFLAG_READWRITE,
363 CTLTYPE_INT, "scroll_downscale_factor",
364 NULL,
365 btmagic_sysctl_scale, 0,
366 (void *)sc, 0,
367 CTL_HW, node->sysctl_num,
368 CTL_CREATE, CTL_EOL);
369 }
370
371 /*
372 * attach the wsmouse
373 */
374 wsma.accessops = &btmagic_wsmouse_accessops;
375 wsma.accesscookie = self;
376 sc->sc_wsmouse = config_found(self, &wsma, wsmousedevprint);
377 if (sc->sc_wsmouse == NULL) {
378 aprint_error_dev(self, "failed to attach wsmouse\n");
379 return;
380 }
381
382 pmf_device_register(self, NULL, NULL);
383
384 /*
385 * start bluetooth connections
386 */
387 mutex_enter(bt_lock);
388 if ((err = btmagic_listen(sc)) != 0)
389 aprint_error_dev(self, "failed to listen (%d)\n", err);
390 btmagic_connect(sc);
391 mutex_exit(bt_lock);
392 }
393
394 static int
395 btmagic_detach(device_t self, int flags)
396 {
397 struct btmagic_softc *sc = device_private(self);
398 int err = 0;
399
400 mutex_enter(bt_lock);
401
402 /* release interrupt listen */
403 if (sc->sc_int_l != NULL) {
404 l2cap_detach_pcb(&sc->sc_int_l);
405 sc->sc_int_l = NULL;
406 }
407
408 /* release control listen */
409 if (sc->sc_ctl_l != NULL) {
410 l2cap_detach_pcb(&sc->sc_ctl_l);
411 sc->sc_ctl_l = NULL;
412 }
413
414 /* close interrupt channel */
415 if (sc->sc_int != NULL) {
416 l2cap_disconnect_pcb(sc->sc_int, 0);
417 l2cap_detach_pcb(&sc->sc_int);
418 sc->sc_int = NULL;
419 }
420
421 /* close control channel */
422 if (sc->sc_ctl != NULL) {
423 l2cap_disconnect_pcb(sc->sc_ctl, 0);
424 l2cap_detach_pcb(&sc->sc_ctl);
425 sc->sc_ctl = NULL;
426 }
427
428 callout_halt(&sc->sc_timeout, bt_lock);
429 callout_destroy(&sc->sc_timeout);
430
431 mutex_exit(bt_lock);
432
433 pmf_device_deregister(self);
434
435 sockopt_destroy(&sc->sc_mode);
436
437 sysctl_teardown(&sc->sc_log);
438
439 if (sc->sc_wsmouse != NULL) {
440 err = config_detach(sc->sc_wsmouse, flags);
441 sc->sc_wsmouse = NULL;
442 }
443
444 return err;
445 }
446
447 /*
448 * listen for our device
449 *
450 * bt_lock is held
451 */
452 static int
453 btmagic_listen(struct btmagic_softc *sc)
454 {
455 struct sockaddr_bt sa;
456 int err;
457
458 memset(&sa, 0, sizeof(sa));
459 sa.bt_len = sizeof(sa);
460 sa.bt_family = AF_BLUETOOTH;
461 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
462
463 /*
464 * Listen on control PSM
465 */
466 err = l2cap_attach_pcb(&sc->sc_ctl_l, &btmagic_ctl_proto, sc);
467 if (err)
468 return err;
469
470 err = l2cap_setopt(sc->sc_ctl_l, &sc->sc_mode);
471 if (err)
472 return err;
473
474 sa.bt_psm = L2CAP_PSM_HID_CNTL;
475 err = l2cap_bind_pcb(sc->sc_ctl_l, &sa);
476 if (err)
477 return err;
478
479 err = l2cap_listen_pcb(sc->sc_ctl_l);
480 if (err)
481 return err;
482
483 /*
484 * Listen on interrupt PSM
485 */
486 err = l2cap_attach_pcb(&sc->sc_int_l, &btmagic_int_proto, sc);
487 if (err)
488 return err;
489
490 err = l2cap_setopt(sc->sc_int_l, &sc->sc_mode);
491 if (err)
492 return err;
493
494 sa.bt_psm = L2CAP_PSM_HID_INTR;
495 err = l2cap_bind_pcb(sc->sc_int_l, &sa);
496 if (err)
497 return err;
498
499 err = l2cap_listen_pcb(sc->sc_int_l);
500 if (err)
501 return err;
502
503 sc->sc_state = BTMAGIC_WAIT_CTL;
504 return 0;
505 }
506
507 /*
508 * start connecting to our device
509 *
510 * bt_lock is held
511 */
512 static int
513 btmagic_connect(struct btmagic_softc *sc)
514 {
515 struct sockaddr_bt sa;
516 int err;
517
518 memset(&sa, 0, sizeof(sa));
519 sa.bt_len = sizeof(sa);
520 sa.bt_family = AF_BLUETOOTH;
521
522 err = l2cap_attach_pcb(&sc->sc_ctl, &btmagic_ctl_proto, sc);
523 if (err) {
524 printf("%s: l2cap_attach failed (%d)\n",
525 device_xname(sc->sc_dev), err);
526 return err;
527 }
528
529 err = l2cap_setopt(sc->sc_ctl, &sc->sc_mode);
530 if (err) {
531 printf("%s: l2cap_setopt failed (%d)\n",
532 device_xname(sc->sc_dev), err);
533 return err;
534 }
535
536 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
537 err = l2cap_bind_pcb(sc->sc_ctl, &sa);
538 if (err) {
539 printf("%s: l2cap_bind_pcb failed (%d)\n",
540 device_xname(sc->sc_dev), err);
541 return err;
542 }
543
544 sa.bt_psm = L2CAP_PSM_HID_CNTL;
545 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
546 err = l2cap_connect_pcb(sc->sc_ctl, &sa);
547 if (err) {
548 printf("%s: l2cap_connect_pcb failed (%d)\n",
549 device_xname(sc->sc_dev), err);
550 return err;
551 }
552
553 SET(sc->sc_flags, BTMAGIC_CONNECTING);
554 sc->sc_state = BTMAGIC_WAIT_CTL;
555 return 0;
556 }
557
558 /* validate soft_resolution */
559 static int
560 btmagic_sysctl_resolution(SYSCTLFN_ARGS)
561 {
562 struct sysctlnode node;
563 struct btmagic_softc *sc;
564 int t, error;
565
566 node = *rnode;
567 sc = node.sysctl_data;
568
569 t = sc->sc_resolution;
570 node.sysctl_data = &t;
571 error = sysctl_lookup(SYSCTLFN_CALL(&node));
572 if (error || newp == NULL)
573 return error;
574
575 if (t < 100 || t > 4000 || (t / sc->sc_scale) == 0)
576 return EINVAL;
577
578 sc->sc_resolution = t;
579 DPRINTF(sc, "sc_resolution = %u", t);
580 return 0;
581 }
582
583 /* validate scroll_downscale_factor */
584 static int
585 btmagic_sysctl_scale(SYSCTLFN_ARGS)
586 {
587 struct sysctlnode node;
588 struct btmagic_softc *sc;
589 int t, error;
590
591 node = *rnode;
592 sc = node.sysctl_data;
593
594 t = sc->sc_scale;
595 node.sysctl_data = &t;
596 error = sysctl_lookup(SYSCTLFN_CALL(&node));
597 if (error || newp == NULL)
598 return error;
599
600 if (t < 1 || t > 40 || (sc->sc_resolution / t) == 0)
601 return EINVAL;
602
603 sc->sc_scale = t;
604 DPRINTF(sc, "sc_scale = %u", t);
605 return 0;
606 }
607
608 /*****************************************************************************
609 *
610 * wsmouse(4) accessops
611 */
612
613 static int
614 btmagic_wsmouse_enable(void *self)
615 {
616 struct btmagic_softc *sc = device_private(self);
617
618 if (sc->sc_enabled)
619 return EBUSY;
620
621 sc->sc_enabled = 1;
622 DPRINTF(sc, "enable");
623 return 0;
624 }
625
626 static int
627 btmagic_wsmouse_ioctl(void *self, unsigned long cmd, void *data,
628 int flag, struct lwp *l)
629 {
630 /* struct btmagic_softc *sc = device_private(self); */
631 int err;
632
633 switch (cmd) {
634 case WSMOUSEIO_GTYPE:
635 *(uint *)data = WSMOUSE_TYPE_BLUETOOTH;
636 err = 0;
637 break;
638
639 default:
640 err = EPASSTHROUGH;
641 break;
642 }
643
644 return err;
645 }
646
647 static void
648 btmagic_wsmouse_disable(void *self)
649 {
650 struct btmagic_softc *sc = device_private(self);
651
652 DPRINTF(sc, "disable");
653 sc->sc_enabled = 0;
654 }
655
656
657 /*****************************************************************************
658 *
659 * setup routines
660 */
661
662 static void
663 btmagic_timeout(void *arg)
664 {
665 struct btmagic_softc *sc = arg;
666
667 mutex_enter(bt_lock);
668 callout_ack(&sc->sc_timeout);
669
670 switch (sc->sc_state) {
671 case BTMAGIC_CLOSED:
672 if (sc->sc_int != NULL) {
673 l2cap_disconnect_pcb(sc->sc_int, 0);
674 break;
675 }
676
677 if (sc->sc_ctl != NULL) {
678 l2cap_disconnect_pcb(sc->sc_ctl, 0);
679 break;
680 }
681 break;
682
683 case BTMAGIC_OPEN:
684 if (!ISSET(sc->sc_flags, BTMAGIC_ENABLED)) {
685 btmagic_enable(sc);
686 break;
687 }
688
689 btmagic_check_battery(sc);
690 break;
691
692 case BTMAGIC_WAIT_CTL:
693 case BTMAGIC_WAIT_INT:
694 default:
695 break;
696 }
697 mutex_exit(bt_lock);
698 }
699
700 /*
701 * Send report on control channel
702 *
703 * bt_lock is held
704 */
705 static int
706 btmagic_ctl_send(struct btmagic_softc *sc, const uint8_t *data, size_t len)
707 {
708 struct mbuf *m;
709
710 if (len > MLEN)
711 return EINVAL;
712
713 m = m_gethdr(M_DONTWAIT, MT_DATA);
714 if (m == NULL)
715 return ENOMEM;
716
717 #ifdef BTMAGIC_DEBUG
718 printf("%s: send", device_xname(sc->sc_dev));
719 for (size_t i = 0; i < len; i++)
720 printf(" 0x%02x", data[i]);
721 printf("\n");
722 #endif
723
724 memcpy(mtod(m, uint8_t *), data, len);
725 m->m_pkthdr.len = m->m_len = len;
726 return l2cap_send(sc->sc_ctl, m);
727 }
728
729 /*
730 * Enable touch reports by sending the following report
731 *
732 * SET_REPORT(FEATURE, 0xd7) = 0x01
733 *
734 * bt_lock is held
735 */
736 static void
737 btmagic_enable(struct btmagic_softc *sc)
738 {
739 static const uint8_t rep[] = { 0x53, 0xd7, 0x01 };
740
741 if (btmagic_ctl_send(sc, rep, sizeof(rep)) != 0) {
742 printf("%s: cannot enable touch reports\n",
743 device_xname(sc->sc_dev));
744
745 return;
746 }
747
748 SET(sc->sc_flags, BTMAGIC_ENABLED);
749 }
750
751 /*
752 * Request the battery level by sending the following report
753 *
754 * GET_REPORT(FEATURE, 0x47)
755 *
756 * bt_lock is held
757 */
758 static void
759 btmagic_check_battery(struct btmagic_softc *sc)
760 {
761 static const uint8_t rep[] = { 0x43, 0x47 };
762
763 if (btmagic_ctl_send(sc, rep, sizeof(rep)) != 0)
764 printf("%s: cannot request battery level\n",
765 device_xname(sc->sc_dev));
766 }
767
768 /*
769 * the Magic Mouse has a base resolution of 1300dpi which is rather flighty. We
770 * scale the output to the requested resolution, taking care to account for the
771 * remainders to prevent loss of small deltas.
772 */
773 static int
774 btmagic_scale(int delta, int *remainder, int resolution)
775 {
776 int new;
777
778 delta += *remainder;
779 new = delta * resolution / 1300;
780 *remainder = delta - new * 1300 / resolution;
781 return new;
782 }
783
784
785 /*****************************************************************************
786 *
787 * bluetooth(9) callback methods for L2CAP
788 *
789 * All these are called from Bluetooth Protocol code, holding bt_lock.
790 */
791
792 static void
793 btmagic_connecting(void *arg)
794 {
795
796 /* dont care */
797 }
798
799 static void
800 btmagic_ctl_connected(void *arg)
801 {
802 struct sockaddr_bt sa;
803 struct btmagic_softc *sc = arg;
804 int err;
805
806 if (sc->sc_state != BTMAGIC_WAIT_CTL)
807 return;
808
809 KASSERT(sc->sc_ctl != NULL);
810 KASSERT(sc->sc_int == NULL);
811
812 if (ISSET(sc->sc_flags, BTMAGIC_CONNECTING)) {
813 /* initiate connect on interrupt PSM */
814 err = l2cap_attach_pcb(&sc->sc_int, &btmagic_int_proto, sc);
815 if (err)
816 goto fail;
817
818 err = l2cap_setopt(sc->sc_int, &sc->sc_mode);
819 if (err)
820 goto fail;
821
822 memset(&sa, 0, sizeof(sa));
823 sa.bt_len = sizeof(sa);
824 sa.bt_family = AF_BLUETOOTH;
825 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
826
827 err = l2cap_bind_pcb(sc->sc_int, &sa);
828 if (err)
829 goto fail;
830
831 sa.bt_psm = L2CAP_PSM_HID_INTR;
832 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
833 err = l2cap_connect_pcb(sc->sc_int, &sa);
834 if (err)
835 goto fail;
836 }
837
838 sc->sc_state = BTMAGIC_WAIT_INT;
839 return;
840
841 fail:
842 l2cap_detach_pcb(&sc->sc_ctl);
843 sc->sc_ctl = NULL;
844
845 printf("%s: connect failed (%d)\n", device_xname(sc->sc_dev), err);
846 }
847
848 static void
849 btmagic_int_connected(void *arg)
850 {
851 struct btmagic_softc *sc = arg;
852
853 if (sc->sc_state != BTMAGIC_WAIT_INT)
854 return;
855
856 KASSERT(sc->sc_ctl != NULL);
857 KASSERT(sc->sc_int != NULL);
858
859 printf("%s: connected\n", device_xname(sc->sc_dev));
860 CLR(sc->sc_flags, BTMAGIC_CONNECTING);
861 sc->sc_state = BTMAGIC_OPEN;
862
863 /* trigger the setup */
864 CLR(sc->sc_flags, BTMAGIC_ENABLED);
865 callout_schedule(&sc->sc_timeout, hz);
866 }
867
868 /*
869 * Disconnected
870 *
871 * Depending on our state, this could mean several things, but essentially
872 * we are lost. If both channels are closed, schedule another connection.
873 */
874 static void
875 btmagic_ctl_disconnected(void *arg, int err)
876 {
877 struct btmagic_softc *sc = arg;
878
879 if (sc->sc_ctl != NULL) {
880 l2cap_detach_pcb(&sc->sc_ctl);
881 sc->sc_ctl = NULL;
882 }
883
884 if (sc->sc_int == NULL) {
885 printf("%s: disconnected (%d)\n", device_xname(sc->sc_dev), err);
886 CLR(sc->sc_flags, BTMAGIC_CONNECTING);
887 sc->sc_state = BTMAGIC_WAIT_CTL;
888 } else {
889 /*
890 * The interrupt channel should have been closed first,
891 * but its potentially unsafe to detach that from here.
892 * Give them a second to do the right thing or let the
893 * callout handle it.
894 */
895 sc->sc_state = BTMAGIC_CLOSED;
896 callout_schedule(&sc->sc_timeout, hz);
897 }
898 }
899
900 static void
901 btmagic_int_disconnected(void *arg, int err)
902 {
903 struct btmagic_softc *sc = arg;
904
905 if (sc->sc_int != NULL) {
906 l2cap_detach_pcb(&sc->sc_int);
907 sc->sc_int = NULL;
908 }
909
910 if (sc->sc_ctl == NULL) {
911 printf("%s: disconnected (%d)\n", device_xname(sc->sc_dev), err);
912 CLR(sc->sc_flags, BTMAGIC_CONNECTING);
913 sc->sc_state = BTMAGIC_WAIT_CTL;
914 } else {
915 /*
916 * The control channel should be closing also, allow
917 * them a chance to do that before we force it.
918 */
919 sc->sc_state = BTMAGIC_CLOSED;
920 callout_schedule(&sc->sc_timeout, hz);
921 }
922 }
923
924 /*
925 * New Connections
926 *
927 * We give a new L2CAP handle back if this matches the BDADDR we are
928 * listening for and we are in the right state. btmagic_connected will
929 * be called when the connection is open, so nothing else to do here
930 */
931 static void *
932 btmagic_ctl_newconn(void *arg, struct sockaddr_bt *laddr,
933 struct sockaddr_bt *raddr)
934 {
935 struct btmagic_softc *sc = arg;
936
937 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0)
938 return NULL;
939
940 if (sc->sc_state != BTMAGIC_WAIT_CTL
941 || ISSET(sc->sc_flags, BTMAGIC_CONNECTING)
942 || sc->sc_ctl != NULL
943 || sc->sc_int != NULL) {
944 DPRINTF(sc, "reject ctl newconn %s%s%s%s",
945 (sc->sc_state == BTMAGIC_WAIT_CTL) ? " (WAITING)": "",
946 ISSET(sc->sc_flags, BTMAGIC_CONNECTING) ? " (CONNECTING)" : "",
947 (sc->sc_ctl != NULL) ? " (GOT CONTROL)" : "",
948 (sc->sc_int != NULL) ? " (GOT INTERRUPT)" : "");
949
950 return NULL;
951 }
952
953 l2cap_attach_pcb(&sc->sc_ctl, &btmagic_ctl_proto, sc);
954 return sc->sc_ctl;
955 }
956
957 static void *
958 btmagic_int_newconn(void *arg, struct sockaddr_bt *laddr,
959 struct sockaddr_bt *raddr)
960 {
961 struct btmagic_softc *sc = arg;
962
963 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0)
964 return NULL;
965
966 if (sc->sc_state != BTMAGIC_WAIT_INT
967 || ISSET(sc->sc_flags, BTMAGIC_CONNECTING)
968 || sc->sc_ctl == NULL
969 || sc->sc_int != NULL) {
970 DPRINTF(sc, "reject int newconn %s%s%s%s",
971 (sc->sc_state == BTMAGIC_WAIT_INT) ? " (WAITING)": "",
972 ISSET(sc->sc_flags, BTMAGIC_CONNECTING) ? " (CONNECTING)" : "",
973 (sc->sc_ctl == NULL) ? " (NO CONTROL)" : "",
974 (sc->sc_int != NULL) ? " (GOT INTERRUPT)" : "");
975
976 return NULL;
977 }
978
979 l2cap_attach_pcb(&sc->sc_int, &btmagic_int_proto, sc);
980 return sc->sc_int;
981 }
982
983 static void
984 btmagic_complete(void *arg, int count)
985 {
986
987 /* dont care */
988 }
989
990 static void
991 btmagic_linkmode(void *arg, int new)
992 {
993 struct btmagic_softc *sc = arg;
994 int mode;
995
996 (void)sockopt_getint(&sc->sc_mode, &mode);
997
998 if (ISSET(mode, L2CAP_LM_AUTH) && !ISSET(new, L2CAP_LM_AUTH))
999 printf("%s: auth failed\n", device_xname(sc->sc_dev));
1000 else if (ISSET(mode, L2CAP_LM_ENCRYPT) && !ISSET(new, L2CAP_LM_ENCRYPT))
1001 printf("%s: encrypt off\n", device_xname(sc->sc_dev));
1002 else if (ISSET(mode, L2CAP_LM_SECURE) && !ISSET(new, L2CAP_LM_SECURE))
1003 printf("%s: insecure\n", device_xname(sc->sc_dev));
1004 else
1005 return;
1006
1007 if (sc->sc_int != NULL)
1008 l2cap_disconnect_pcb(sc->sc_int, 0);
1009
1010 if (sc->sc_ctl != NULL)
1011 l2cap_disconnect_pcb(sc->sc_ctl, 0);
1012 }
1013
1014 /*
1015 * Receive transaction from the mouse. We don't differentiate between
1016 * interrupt and control channel here, there is no need.
1017 */
1018 static void
1019 btmagic_input(void *arg, struct mbuf *m)
1020 {
1021 struct btmagic_softc *sc = arg;
1022 uint8_t *data;
1023 size_t len;
1024
1025 if (sc->sc_state != BTMAGIC_OPEN
1026 || sc->sc_wsmouse == NULL
1027 || sc->sc_enabled == 0)
1028 goto release;
1029
1030 if (m->m_pkthdr.len > m->m_len)
1031 printf("%s: truncating input\n", device_xname(sc->sc_dev));
1032
1033 data = mtod(m, uint8_t *);
1034 len = m->m_len;
1035
1036 if (len < 1)
1037 goto release;
1038
1039 switch (BTHID_TYPE(data[0])) {
1040 case BTHID_HANDSHAKE:
1041 DPRINTF(sc, "Handshake: 0x%x", BTHID_HANDSHAKE_PARAM(data[0]));
1042 callout_schedule(&sc->sc_timeout, hz);
1043 break;
1044
1045 case BTHID_DATA:
1046 if (len < 2)
1047 break;
1048
1049 switch (data[1]) {
1050 case 0x10: /* Basic mouse (input) */
1051 btmagic_input_basic(sc, data + 2, len - 2);
1052 break;
1053
1054 case 0x29: /* Magic touch (input) */
1055 btmagic_input_magic(sc, data + 2, len - 2);
1056 break;
1057
1058 case 0x30: /* Battery status (input) */
1059 if (len != 3)
1060 break;
1061
1062 printf("%s: Battery ", device_xname(sc->sc_dev));
1063 switch (data[2]) {
1064 case 0: printf("Ok\n"); break;
1065 case 1: printf("Warning\n"); break;
1066 case 2: printf("Critical\n"); break;
1067 default: printf("0x%02x\n", data[2]); break;
1068 }
1069 break;
1070
1071 case 0x47: /* Battery strength (feature) */
1072 if (len != 3)
1073 break;
1074
1075 printf("%s: Battery %d%%\n", device_xname(sc->sc_dev),
1076 data[2]);
1077 break;
1078
1079 case 0x61: /* Surface detection (input) */
1080 if (len != 3)
1081 break;
1082
1083 DPRINTF(sc, "Mouse %s",
1084 (data[2] == 0 ? "lowered" : "raised"));
1085 break;
1086
1087 case 0x60: /* unknown (input) */
1088 case 0xf0: /* unknown (feature) */
1089 case 0xf1: /* unknown (feature) */
1090 default:
1091 #if BTMAGIC_DEBUG
1092 printf("%s: recv", device_xname(sc->sc_dev));
1093 for (size_t i = 0; i < len; i++)
1094 printf(" 0x%02x", data[i]);
1095 printf("\n");
1096 #endif
1097 break;
1098 }
1099 break;
1100
1101 default:
1102 DPRINTF(sc, "transaction (type 0x%x)", BTHID_TYPE(data[0]));
1103 break;
1104 }
1105
1106 release:
1107 m_freem(m);
1108 }
1109
1110 /*
1111 * parse the Basic report (0x10), which according to the provided
1112 * HID descriptor is in the following format
1113 *
1114 * button 1 1-bit
1115 * button 2 1-bit
1116 * padding 6-bits
1117 * dX 16-bits (signed)
1118 * dY 16-bits (signed)
1119 *
1120 * Even when the magic touch reports are enabled, the basic report is
1121 * sent for mouse move events where no touches are detected.
1122 */
1123 static const struct {
1124 struct hid_location button1;
1125 struct hid_location button2;
1126 struct hid_location dX;
1127 struct hid_location dY;
1128 } basic = {
1129 .button1 = { .pos = 0, .size = 1 },
1130 .button2 = { .pos = 1, .size = 1 },
1131 .dX = { .pos = 8, .size = 16 },
1132 .dY = { .pos = 24, .size = 16 },
1133 };
1134
1135 static void
1136 btmagic_input_basic(struct btmagic_softc *sc, uint8_t *data, size_t len)
1137 {
1138 int dx, dy;
1139 uint32_t mb;
1140 int s;
1141
1142 if (len != 5)
1143 return;
1144
1145 dx = hid_get_data(data, &basic.dX);
1146 dx = btmagic_scale(dx, &sc->sc_rx, sc->sc_resolution);
1147
1148 dy = hid_get_data(data, &basic.dY);
1149 dy = btmagic_scale(dy, &sc->sc_ry, sc->sc_resolution);
1150
1151 mb = 0;
1152 if (hid_get_udata(data, &basic.button1))
1153 mb |= __BIT(0);
1154 if (hid_get_udata(data, &basic.button2))
1155 mb |= __BIT(2);
1156
1157 if (dx != 0 || dy != 0 || mb != sc->sc_mb) {
1158 sc->sc_mb = mb;
1159
1160 s = spltty();
1161 wsmouse_input(sc->sc_wsmouse, mb,
1162 dx, -dy, 0, 0, WSMOUSE_INPUT_DELTA);
1163 splx(s);
1164 }
1165 }
1166
1167 /*
1168 * the Magic touch report (0x29), according to the Linux driver
1169 * written by Michael Poole, is variable length starting with the
1170 * fixed 40-bit header
1171 *
1172 * dX lsb 8-bits (signed)
1173 * dY lsb 8-bits (signed)
1174 * button 1 1-bit
1175 * button 2 1-bit
1176 * dX msb 2-bits (signed)
1177 * dY msb 2-bits (signed)
1178 * timestamp 18-bits
1179 *
1180 * followed by (up to 5?) touch reports of 64-bits each
1181 *
1182 * abs W 12-bits (signed)
1183 * abs Z 12-bits (signed)
1184 * axis major 8-bits
1185 * axis minor 8-bits
1186 * pressure 6-bits
1187 * id 4-bits
1188 * angle 6-bits (from E(0)->N(32)->W(64))
1189 * unknown 4-bits
1190 * phase 4-bits
1191 */
1192
1193 static const struct {
1194 struct hid_location dXl;
1195 struct hid_location dYl;
1196 struct hid_location button1;
1197 struct hid_location button2;
1198 struct hid_location dXm;
1199 struct hid_location dYm;
1200 struct hid_location timestamp;
1201 } magic = {
1202 .dXl = { .pos = 0, .size = 8 },
1203 .dYl = { .pos = 8, .size = 8 },
1204 .button1 = { .pos = 16, .size = 1 },
1205 .button2 = { .pos = 17, .size = 1 },
1206 .dXm = { .pos = 18, .size = 2 },
1207 .dYm = { .pos = 20, .size = 2 },
1208 .timestamp = { .pos = 22, .size = 18 },
1209 };
1210
1211 static const struct {
1212 struct hid_location aW;
1213 struct hid_location aZ;
1214 struct hid_location major;
1215 struct hid_location minor;
1216 struct hid_location pressure;
1217 struct hid_location id;
1218 struct hid_location angle;
1219 struct hid_location unknown;
1220 struct hid_location phase;
1221 } touch = {
1222 .aW = { .pos = 0, .size = 12 },
1223 .aZ = { .pos = 12, .size = 12 },
1224 .major = { .pos = 24, .size = 8 },
1225 .minor = { .pos = 32, .size = 8 },
1226 .pressure = { .pos = 40, .size = 6 },
1227 .id = { .pos = 46, .size = 4 },
1228 .angle = { .pos = 50, .size = 6 },
1229 .unknown = { .pos = 56, .size = 4 },
1230 .phase = { .pos = 60, .size = 4 },
1231 };
1232
1233 /*
1234 * the phase of the touch starts at 0x01 as the finger is first detected
1235 * approaching the mouse, increasing to 0x04 while the finger is touching,
1236 * then increases towards 0x07 as the finger is lifted, and we get 0x00
1237 * when the touch is cancelled. The values below seem to be produced for
1238 * every touch, the others less consistently depending on how fast the
1239 * approach or departure is.
1240 *
1241 * In fact we ignore touches unless they are in the steady 0x04 phase.
1242 */
1243 #define BTMAGIC_PHASE_START 0x3
1244 #define BTMAGIC_PHASE_CONT 0x4
1245 #define BTMAGIC_PHASE_END 0x7
1246 #define BTMAGIC_PHASE_CANCEL 0x0
1247
1248 static void
1249 btmagic_input_magic(struct btmagic_softc *sc, uint8_t *data, size_t len)
1250 {
1251 uint32_t mb;
1252 int dx, dy, dz, dw;
1253 int id, nf, az, aw, tz, tw;
1254 int s;
1255
1256 if (((len - 5) % 8) != 0)
1257 return;
1258
1259 dx = (hid_get_data(data, &magic.dXm) << 8)
1260 | (hid_get_data(data, &magic.dXl) & 0xff);
1261 dx = btmagic_scale(dx, &sc->sc_rx, sc->sc_resolution);
1262
1263 dy = (hid_get_data(data, &magic.dYm) << 8)
1264 | (hid_get_data(data, &magic.dYl) & 0xff);
1265 dy = btmagic_scale(dy, &sc->sc_ry, sc->sc_resolution);
1266
1267 mb = 0;
1268 if (hid_get_udata(data, &magic.button1))
1269 mb |= __BIT(0);
1270 if (hid_get_udata(data, &magic.button2))
1271 mb |= __BIT(2);
1272
1273 nf = 0;
1274 dz = 0;
1275 dw = 0;
1276 len = (len - 5) / 8;
1277 for (data += 5; len-- > 0; data += 8) {
1278 id = hid_get_udata(data, &touch.id);
1279 az = hid_get_data(data, &touch.aZ);
1280 aw = hid_get_data(data, &touch.aW);
1281
1282 /*
1283 * scrolling is triggered by an established touch moving
1284 * beyond a minimum distance from its start point and is
1285 * cancelled as the touch starts to fade.
1286 *
1287 * Multiple touches may be scrolling simultaneously, the
1288 * effect is cumulative.
1289 */
1290
1291 switch (hid_get_udata(data, &touch.phase)) {
1292 case BTMAGIC_PHASE_CONT:
1293 tz = az - sc->sc_az[id];
1294 tw = aw - sc->sc_aw[id];
1295
1296 if (ISSET(sc->sc_smask, id)) {
1297 /* scrolling finger */
1298 dz += btmagic_scale(tz, &sc->sc_rz,
1299 sc->sc_resolution / sc->sc_scale);
1300 dw += btmagic_scale(tw, &sc->sc_rw,
1301 sc->sc_resolution / sc->sc_scale);
1302 } else if (abs(tz) > sc->sc_dist
1303 || abs(tw) > sc->sc_dist) {
1304 /* new scrolling finger */
1305 if (sc->sc_smask == 0) {
1306 sc->sc_rz = 0;
1307 sc->sc_rw = 0;
1308 }
1309
1310 SET(sc->sc_smask, id);
1311 } else {
1312 /* not scrolling finger */
1313 az = sc->sc_az[id];
1314 aw = sc->sc_aw[id];
1315 }
1316
1317 /* count firm touches for middle-click */
1318 if (hid_get_udata(data, &touch.pressure) > sc->sc_firm)
1319 nf++;
1320
1321 break;
1322
1323 default:
1324 CLR(sc->sc_smask, id);
1325 break;
1326 }
1327
1328 sc->sc_az[id] = az;
1329 sc->sc_aw[id] = aw;
1330 }
1331
1332 /*
1333 * The mouse only has one click detector, and says left or right but
1334 * never both. We convert multiple firm touches while clicking into
1335 * a middle button press, and cancel any scroll effects while click
1336 * is active.
1337 */
1338 if (mb != 0) {
1339 if (sc->sc_mb != 0)
1340 mb = sc->sc_mb;
1341 else if (nf > 1)
1342 mb = __BIT(1);
1343
1344 sc->sc_smask = 0;
1345 dz = 0;
1346 dw = 0;
1347 }
1348
1349 if (dx != 0 || dy != 0 || dz != 0 || dw != 0 || mb != sc->sc_mb) {
1350 sc->sc_mb = mb;
1351
1352 s = spltty();
1353 wsmouse_input(sc->sc_wsmouse, mb,
1354 dx, -dy, -dz, dw, WSMOUSE_INPUT_DELTA);
1355 splx(s);
1356 }
1357 }
1358