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