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