Sync Bluetooth stack with NetBSD.
[dragonfly.git] / sys / dev / usbmisc / ubt / ubt.c
blobde1da4b6b0b7b3b31b845339527d1fbbf86b258c
1 /* $DragonFly: src/sys/dev/usbmisc/ubt/ubt.c,v 1.3 2008/03/18 13:41:42 hasso Exp $ */
2 /* $OpenBSD: src/sys/dev/usb/ubt.c,v 1.11 2008/02/24 21:34:48 uwe Exp $ */
3 /* $NetBSD: ubt.c,v 1.30 2007/12/16 19:01:37 christos Exp $ */
5 /*-
6 * Copyright (c) 2006 Itronix Inc.
7 * All rights reserved.
9 * Written by Iain Hibbert for Itronix Inc.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of Itronix Inc. may not be used to endorse
20 * or promote products derived from this software without specific
21 * prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
24 * 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 ITRONIX INC. BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * 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.
36 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
37 * All rights reserved.
39 * This code is derived from software contributed to The NetBSD Foundation
40 * by Lennart Augustsson (lennart@augustsson.net) and
41 * David Sainty (David.Sainty@dtsp.co.nz).
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the NetBSD
54 * Foundation, Inc. and its contributors.
55 * 4. Neither the name of The NetBSD Foundation nor the names of its
56 * contributors may be used to endorse or promote products derived
57 * from this software without specific prior written permission.
59 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
60 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
61 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
62 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
63 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
64 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
65 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
66 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
67 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
68 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
69 * POSSIBILITY OF SUCH DAMAGE.
72 * This driver originally written by Lennart Augustsson and David Sainty,
73 * but was mostly rewritten for the NetBSD Bluetooth protocol stack by
74 * Iain Hibbert for Itronix, Inc using the FreeBSD ng_ubt.c driver as a
75 * reference.
78 #include <sys/bus.h>
79 #include <sys/kernel.h>
80 #include <sys/proc.h>
81 #include <sys/sysctl.h>
83 #include <bus/usb/usb.h>
84 #include <bus/usb/usbdi.h>
85 #include <bus/usb/usbdi_util.h>
86 #include <bus/usb/usbdivar.h>
88 #include <netbt/bluetooth.h>
89 #include <netbt/hci.h>
91 /*******************************************************************************
93 * debugging stuff
95 #undef DPRINTF
96 #undef DPRINTFN
98 #ifdef UBT_DEBUG
99 int ubt_debug = UBT_DEBUG;
101 #define DPRINTF(fmt, args...) do { \
102 if (ubt_debug) \
103 kprintf("%s: "fmt, __func__ , ##args); \
104 } while (/* CONSTCOND */0)
106 #define DPRINTFN(n, fmt, args...) do { \
107 if (ubt_debug > (n)) \
108 kprintf("%s: "fmt, __func__ , ##args); \
109 } while (/* CONSTCOND */0)
111 #else
112 #define DPRINTF(...)
113 #define DPRINTFN(...)
114 #endif
116 /*******************************************************************************
118 * ubt softc structure
122 /* buffer sizes */
124 * NB: although ACL packets can extend to 65535 bytes, most devices
125 * have max_acl_size at much less (largest I have seen is 384)
127 #define UBT_BUFSIZ_CMD (HCI_CMD_PKT_SIZE - 1)
128 #define UBT_BUFSIZ_ACL (2048 - 1)
129 #define UBT_BUFSIZ_EVENT (HCI_EVENT_PKT_SIZE - 1)
131 /* Transmit timeouts */
133 #define UBT_CMD_TIMEOUT 100
134 #define UBT_ACL_TIMEOUT 100
137 * Specification says, that is must be 1ms, but it causes kernel panic.
138 * Setting interval to USBD_DEFAULT_INTERVAL is not working for some of
139 * us either.
140 * XXX: Make it sysctl.
142 #define UBT_INTR_TIMEOUT USBD_DEFAULT_INTERVAL
145 * ISOC transfers
147 * xfer buffer size depends on the frame size, and the number
148 * of frames per transfer is fixed, as each frame should be
149 * 1ms worth of data. This keeps the rate that xfers complete
150 * fairly constant. We use multiple xfers to keep the hardware
151 * busy
153 #define UBT_NXFERS 3 /* max xfers to queue */
154 #define UBT_NFRAMES 10 /* frames per xfer */
156 struct ubt_isoc_xfer {
157 struct ubt_softc *softc;
158 usbd_xfer_handle xfer;
159 uint8_t *buf;
160 uint16_t size[UBT_NFRAMES];
161 int busy;
164 struct ubt_softc {
165 device_t sc_dev;
166 usbd_device_handle sc_udev;
167 int sc_refcnt;
168 int sc_dying;
169 int sc_enabled;
171 /* Control Interface */
172 usbd_interface_handle sc_iface0;
174 /* Commands (control) */
175 usbd_xfer_handle sc_cmd_xfer;
176 u_char *sc_cmd_buf;
177 int sc_cmd_busy; /* write active */
178 struct ifqueue sc_cmd_queue; /* output queue */
180 /* Events (interrupt) */
181 int sc_evt_addr; /* endpoint address */
182 usbd_pipe_handle sc_evt_pipe;
183 u_char *sc_evt_buf;
186 /* ACL data (in) */
187 int sc_aclrd_addr; /* endpoint address */
188 usbd_pipe_handle sc_aclrd_pipe; /* read pipe */
189 usbd_xfer_handle sc_aclrd_xfer; /* read xfer */
190 u_char *sc_aclrd_buf; /* read buffer */
191 int sc_aclrd_busy; /* reading */
193 /* ACL data (out) */
194 int sc_aclwr_addr; /* endpoint address */
195 usbd_pipe_handle sc_aclwr_pipe; /* write pipe */
196 usbd_xfer_handle sc_aclwr_xfer; /* write xfer */
197 u_char *sc_aclwr_buf; /* write buffer */
198 int sc_aclwr_busy; /* write active */
199 struct ifqueue sc_aclwr_queue;/* output queue */
201 /* ISOC interface */
202 usbd_interface_handle sc_iface1; /* ISOC interface */
203 struct sysctllog *sc_log; /* sysctl log */
204 int sc_config; /* current config no */
205 int sc_alt_config; /* no of alternates */
207 /* SCO data (in) */
208 int sc_scord_addr; /* endpoint address */
209 usbd_pipe_handle sc_scord_pipe; /* read pipe */
210 int sc_scord_size; /* frame length */
211 struct ubt_isoc_xfer sc_scord[UBT_NXFERS];
212 struct mbuf *sc_scord_mbuf; /* current packet */
214 /* SCO data (out) */
215 int sc_scowr_addr; /* endpoint address */
216 usbd_pipe_handle sc_scowr_pipe; /* write pipe */
217 int sc_scowr_size; /* frame length */
218 struct ubt_isoc_xfer sc_scowr[UBT_NXFERS];
219 struct mbuf *sc_scowr_mbuf; /* current packet */
220 int sc_scowr_busy; /* write active */
221 struct ifqueue sc_scowr_queue;/* output queue */
223 /* Protocol structure */
224 struct hci_unit *sc_unit;
225 struct bt_stats sc_stats;
227 /* Successfully attached */
228 int sc_ok;
230 struct sysctl_ctx_list sysctl_ctx;
231 struct sysctl_oid *sysctl_tree;
235 * Bluetooth unit/USB callback routines
237 int ubt_enable(struct device *);
238 void ubt_disable(struct device *);
240 void ubt_xmit_cmd(struct device *, struct mbuf *);
241 void ubt_xmit_cmd_start(struct ubt_softc *);
242 void ubt_xmit_cmd_complete(usbd_xfer_handle,
243 usbd_private_handle, usbd_status);
245 void ubt_xmit_acl(struct device *, struct mbuf *);
246 void ubt_xmit_acl_start(struct ubt_softc *);
247 void ubt_xmit_acl_complete(usbd_xfer_handle,
248 usbd_private_handle, usbd_status);
250 void ubt_xmit_sco(struct device *, struct mbuf *);
251 void ubt_xmit_sco_start(struct ubt_softc *);
252 void ubt_xmit_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
253 void ubt_xmit_sco_complete(usbd_xfer_handle,
254 usbd_private_handle, usbd_status);
256 void ubt_recv_event(usbd_xfer_handle,
257 usbd_private_handle, usbd_status);
259 void ubt_recv_acl_start(struct ubt_softc *);
260 void ubt_recv_acl_complete(usbd_xfer_handle,
261 usbd_private_handle, usbd_status);
263 void ubt_recv_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
264 void ubt_recv_sco_complete(usbd_xfer_handle,
265 usbd_private_handle, usbd_status);
267 void ubt_stats(struct device *, struct bt_stats *, int);
269 static device_probe_t ubt_match;
270 static device_attach_t ubt_attach;
271 static device_detach_t ubt_detach;
273 static devclass_t ubt_devclass;
275 static device_method_t ubt_methods[] = {
276 DEVMETHOD(device_probe, ubt_match),
277 DEVMETHOD(device_attach, ubt_attach),
278 DEVMETHOD(device_detach, ubt_detach),
279 {0,0},
280 {0,0}
283 static driver_t ubt_driver = {
284 "ubt",
285 ubt_methods,
286 sizeof(struct ubt_softc)
289 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, usbd_driver_load, 0);
290 MODULE_DEPEND(ubt, netbt, 1, 1, 1);
291 #if 0 /* not yet */
292 MODULE_DEPEND(ubt, bthub, 1, 1, 1);
293 #endif
294 MODULE_DEPEND(ubt, usb, 1, 1, 1);
296 const struct hci_if ubt_hci = {
297 .enable = ubt_enable,
298 .disable = ubt_disable,
299 .output_cmd = ubt_xmit_cmd,
300 .output_acl = ubt_xmit_acl,
301 .output_sco = ubt_xmit_sco,
302 .get_stats = ubt_stats,
305 static int ubt_set_isoc_config(struct ubt_softc *);
306 static int ubt_sysctl_config(SYSCTL_HANDLER_ARGS);
307 static void ubt_abortdealloc(struct ubt_softc *);
310 * Match against the whole device, since we want to take
311 * both interfaces. If a device should be ignored then add
313 * { VendorID, ProductID }
315 * to the ubt_ignore list.
317 static const struct usb_devno ubt_ignore[] = {
318 { USB_DEVICE(0x0a5c, 0x2033) }, /* Broadcom BCM2033 */
319 { 0, 0 } /* end of list */
322 static int
323 ubt_match(device_t self)
325 struct usb_attach_arg *uaa = device_get_ivars(self);
326 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
328 DPRINTFN(50, "ubt_match\n");
330 if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product))
331 return UMATCH_NONE;
333 if (dd->bDeviceClass == UDCLASS_WIRELESS
334 && dd->bDeviceSubClass == UDSUBCLASS_RF
335 && dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
336 return UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO;
337 return UMATCH_NONE;
340 static int
341 ubt_attach(device_t self)
343 struct ubt_softc *sc = device_get_softc(self);
344 struct usb_attach_arg *uaa = device_get_ivars(self);
346 usb_config_descriptor_t *cd;
347 usb_endpoint_descriptor_t *ed;
348 int err;
349 uint8_t count, i;
351 DPRINTFN(50, "ubt_attach: sc=%p\n", sc);
353 sc->sc_udev = uaa->device;
354 sc->sc_dev = self;
357 * Move the device into the configured state
359 err = usbd_set_config_index(sc->sc_udev, 0, 1);
360 if (err) {
361 kprintf("%s: failed to set configuration idx 0: %s\n",
362 device_get_nameunit(sc->sc_dev), usbd_errstr(err));
364 return ENXIO;
368 * Interface 0 must have 3 endpoints
369 * 1) Interrupt endpoint to receive HCI events
370 * 2) Bulk IN endpoint to receive ACL data
371 * 3) Bulk OUT endpoint to send ACL data
373 err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
374 if (err) {
375 kprintf("%s: Could not get interface 0 handle %s (%d)\n",
376 device_get_nameunit(sc->sc_dev), usbd_errstr(err), err);
378 return ENXIO;
381 sc->sc_evt_addr = -1;
382 sc->sc_aclrd_addr = -1;
383 sc->sc_aclwr_addr = -1;
385 count = 0;
386 (void)usbd_endpoint_count(sc->sc_iface0, &count);
388 for (i = 0 ; i < count ; i++) {
389 int dir, type;
391 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
392 if (ed == NULL) {
393 kprintf("%s: could not read endpoint descriptor %d\n",
394 device_get_nameunit(sc->sc_dev), i);
396 return ENXIO;
399 dir = UE_GET_DIR(ed->bEndpointAddress);
400 type = UE_GET_XFERTYPE(ed->bmAttributes);
402 if (dir == UE_DIR_IN && type == UE_INTERRUPT)
403 sc->sc_evt_addr = ed->bEndpointAddress;
404 else if (dir == UE_DIR_IN && type == UE_BULK)
405 sc->sc_aclrd_addr = ed->bEndpointAddress;
406 else if (dir == UE_DIR_OUT && type == UE_BULK)
407 sc->sc_aclwr_addr = ed->bEndpointAddress;
410 if (sc->sc_evt_addr == -1) {
411 kprintf("%s: missing INTERRUPT endpoint on interface 0\n",
412 device_get_nameunit(sc->sc_dev));
414 return ENXIO;
416 if (sc->sc_aclrd_addr == -1) {
417 kprintf("%s: missing BULK IN endpoint on interface 0\n",
418 device_get_nameunit(sc->sc_dev));
420 return ENXIO;
422 if (sc->sc_aclwr_addr == -1) {
423 kprintf("%s: missing BULK OUT endpoint on interface 0\n",
424 device_get_nameunit(sc->sc_dev));
426 return ENXIO;
430 * Interface 1 must have 2 endpoints
431 * 1) Isochronous IN endpoint to receive SCO data
432 * 2) Isochronous OUT endpoint to send SCO data
434 * and will have several configurations, which can be selected
435 * via a sysctl variable. We select config 0 to start, which
436 * means that no SCO data will be available.
438 err = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
439 if (err) {
440 kprintf("%s: Could not get interface 1 handle %s (%d)\n",
441 device_get_nameunit(sc->sc_dev), usbd_errstr(err), err);
443 return ENXIO;
446 cd = usbd_get_config_descriptor(sc->sc_udev);
447 if (cd == NULL) {
448 kprintf("%s: could not get config descriptor\n",
449 device_get_nameunit(sc->sc_dev));
451 return ENXIO;
454 sc->sc_alt_config = usbd_get_no_alts(cd, 1);
456 /* set initial config */
457 err = ubt_set_isoc_config(sc);
458 if (err) {
459 kprintf("%s: ISOC config failed\n",
460 device_get_nameunit(sc->sc_dev));
462 return ENXIO;
465 /* Attach HCI */
466 sc->sc_unit = hci_attach(&ubt_hci, sc->sc_dev, 0);
468 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
469 sc->sc_dev);
471 sc->sc_ok = 1;
473 sysctl_ctx_init(&sc->sysctl_ctx);
474 sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
475 SYSCTL_STATIC_CHILDREN(_hw),
476 OID_AUTO,
477 device_get_nameunit(sc->sc_dev),
478 CTLFLAG_RD, 0, "");
480 if (sc->sysctl_tree == NULL) {
481 /* Failure isn't fatal */
482 device_printf(sc->sc_dev, "Unable to create sysctl tree\n");
483 return 0;
486 SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
487 OID_AUTO, "config", CTLTYPE_INT|CTLFLAG_RW, (void *)sc,
488 0, ubt_sysctl_config, "I", "Configuration number");
489 SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
490 OID_AUTO, "alt_config", CTLFLAG_RD, &sc->sc_alt_config,
491 0, "Number of alternate configurations");
492 SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
493 OID_AUTO, "sco_rxsize", CTLFLAG_RD, &sc->sc_scord_size,
494 0, "Max SCO receive size");
495 SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
496 OID_AUTO, "sco_wrsize", CTLFLAG_RD, &sc->sc_scowr_size,
497 0, "Max SCO transmit size");
499 return 0;
502 static int
503 ubt_detach(device_t self)
506 struct ubt_softc *sc = device_get_softc(self);
508 DPRINTF("sc=%p \n", sc);
510 sc->sc_dying = 1;
512 if (!sc->sc_ok)
513 return 0;
515 /* Detach HCI interface */
516 if (sc->sc_unit) {
517 hci_detach(sc->sc_unit);
518 sc->sc_unit = NULL;
522 * Abort all pipes. Causes processes waiting for transfer to wake.
524 * Actually, hci_detach() above will call ubt_disable() which may
525 * call ubt_abortdealloc(), but lets be sure since doing it twice
526 * wont cause an error.
528 ubt_abortdealloc(sc);
530 /* wait for all processes to finish */
531 if (sc->sc_refcnt-- > 0)
532 usb_detach_wait(sc->sc_dev);
534 if (sc->sysctl_tree != NULL) {
535 sc->sysctl_tree = NULL;
536 sysctl_ctx_free(&sc->sysctl_ctx);
539 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
540 sc->sc_dev);
542 DPRINTFN(1, "driver detached\n");
544 return 0;
547 /* set ISOC configuration */
549 ubt_set_isoc_config(struct ubt_softc *sc)
551 usb_endpoint_descriptor_t *ed;
552 int rd_addr, wr_addr, rd_size, wr_size;
553 uint8_t count, i;
554 int err;
556 err = usbd_set_interface(sc->sc_iface1, sc->sc_config);
557 if (err != USBD_NORMAL_COMPLETION) {
558 kprintf(
559 "%s: Could not set config %d on ISOC interface. %s (%d)\n",
560 device_get_nameunit(sc->sc_dev), sc->sc_config, usbd_errstr(err), err);
562 return err == USBD_IN_USE ? EBUSY : EIO;
566 * We wont get past the above if there are any pipes open, so no
567 * need to worry about buf/xfer/pipe deallocation. If we get an
568 * error after this, the frame quantities will be 0 and no SCO
569 * data will be possible.
572 sc->sc_scord_size = rd_size = 0;
573 sc->sc_scord_addr = rd_addr = -1;
575 sc->sc_scowr_size = wr_size = 0;
576 sc->sc_scowr_addr = wr_addr = -1;
578 count = 0;
579 (void)usbd_endpoint_count(sc->sc_iface1, &count);
581 for (i = 0 ; i < count ; i++) {
582 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
583 if (ed == NULL) {
584 kprintf("%s: could not read endpoint descriptor %d\n",
585 device_get_nameunit(sc->sc_dev), i);
587 return EIO;
590 DPRINTFN(5, "%s: endpoint type %02x (%02x) addr %02x (%s)\n",
591 device_get_nameunit(sc->sc_dev),
592 UE_GET_XFERTYPE(ed->bmAttributes),
593 UE_GET_ISO_TYPE(ed->bmAttributes),
594 ed->bEndpointAddress,
595 UE_GET_DIR(ed->bEndpointAddress) ? "in" : "out");
597 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
598 continue;
600 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
601 rd_addr = ed->bEndpointAddress;
602 rd_size = UGETW(ed->wMaxPacketSize);
603 } else {
604 wr_addr = ed->bEndpointAddress;
605 wr_size = UGETW(ed->wMaxPacketSize);
609 if (rd_addr == -1) {
610 kprintf(
611 "%s: missing ISOC IN endpoint on interface config %d\n",
612 device_get_nameunit(sc->sc_dev), sc->sc_config);
614 return ENOENT;
616 if (wr_addr == -1) {
617 kprintf(
618 "%s: missing ISOC OUT endpoint on interface config %d\n",
619 device_get_nameunit(sc->sc_dev), sc->sc_config);
621 return ENOENT;
624 #ifdef DIAGNOSTIC
625 if (rd_size > MLEN) {
626 kprintf("%s: rd_size=%d exceeds MLEN\n",
627 device_get_nameunit(sc->sc_dev), rd_size);
629 return EOVERFLOW;
632 if (wr_size > MLEN) {
633 kprintf("%s: wr_size=%d exceeds MLEN\n",
634 device_get_nameunit(sc->sc_dev), wr_size);
636 return EOVERFLOW;
638 #endif
640 sc->sc_scord_size = rd_size;
641 sc->sc_scord_addr = rd_addr;
643 sc->sc_scowr_size = wr_size;
644 sc->sc_scowr_addr = wr_addr;
646 return 0;
649 static int
650 ubt_sysctl_config(SYSCTL_HANDLER_ARGS)
652 struct ubt_softc *sc = (struct ubt_softc *)arg1;
653 int t, error;
655 t = sc->sc_config;
656 error = sysctl_handle_int(oidp, &t, sizeof(t), req);
657 if (error || req->newptr == NULL)
658 return error;
660 if (t < 0 || t >= sc->sc_alt_config)
661 return EINVAL;
663 /* This may not change when the unit is enabled */
664 if (sc->sc_enabled)
665 return EBUSY;
667 sc->sc_config = t;
668 return ubt_set_isoc_config(sc);
671 void
672 ubt_abortdealloc(struct ubt_softc *sc)
674 int i;
676 DPRINTFN(1, "sc=%p\n", sc);
678 crit_enter();
679 /* Abort all pipes */
680 if (sc->sc_evt_pipe != NULL) {
681 usbd_abort_pipe(sc->sc_evt_pipe);
682 usbd_close_pipe(sc->sc_evt_pipe);
683 sc->sc_evt_pipe = NULL;
686 if (sc->sc_aclrd_pipe != NULL) {
687 usbd_abort_pipe(sc->sc_aclrd_pipe);
688 usbd_close_pipe(sc->sc_aclrd_pipe);
689 sc->sc_aclrd_pipe = NULL;
692 if (sc->sc_aclwr_pipe != NULL) {
693 usbd_abort_pipe(sc->sc_aclwr_pipe);
694 usbd_close_pipe(sc->sc_aclwr_pipe);
695 sc->sc_aclwr_pipe = NULL;
698 if (sc->sc_scord_pipe != NULL) {
699 usbd_abort_pipe(sc->sc_scord_pipe);
700 usbd_close_pipe(sc->sc_scord_pipe);
701 sc->sc_scord_pipe = NULL;
704 if (sc->sc_scowr_pipe != NULL) {
705 usbd_abort_pipe(sc->sc_scowr_pipe);
706 usbd_close_pipe(sc->sc_scowr_pipe);
707 sc->sc_scowr_pipe = NULL;
710 /* Free event buffer */
711 if (sc->sc_evt_buf != NULL) {
712 kfree(sc->sc_evt_buf, M_USBDEV);
713 sc->sc_evt_buf = NULL;
716 /* Free all xfers and xfer buffers (implicit) */
717 if (sc->sc_cmd_xfer != NULL) {
718 usbd_free_xfer(sc->sc_cmd_xfer);
719 sc->sc_cmd_xfer = NULL;
720 sc->sc_cmd_buf = NULL;
723 if (sc->sc_aclrd_xfer != NULL) {
724 usbd_free_xfer(sc->sc_aclrd_xfer);
725 sc->sc_aclrd_xfer = NULL;
726 sc->sc_aclrd_buf = NULL;
729 if (sc->sc_aclwr_xfer != NULL) {
730 usbd_free_xfer(sc->sc_aclwr_xfer);
731 sc->sc_aclwr_xfer = NULL;
732 sc->sc_aclwr_buf = NULL;
735 for (i = 0 ; i < UBT_NXFERS ; i++) {
736 if (sc->sc_scord[i].xfer != NULL) {
737 usbd_free_xfer(sc->sc_scord[i].xfer);
738 sc->sc_scord[i].xfer = NULL;
739 sc->sc_scord[i].buf = NULL;
742 if (sc->sc_scowr[i].xfer != NULL) {
743 usbd_free_xfer(sc->sc_scowr[i].xfer);
744 sc->sc_scowr[i].xfer = NULL;
745 sc->sc_scowr[i].buf = NULL;
749 /* Free partial SCO packets */
750 if (sc->sc_scord_mbuf != NULL) {
751 m_freem(sc->sc_scord_mbuf);
752 sc->sc_scord_mbuf = NULL;
755 if (sc->sc_scowr_mbuf != NULL) {
756 m_freem(sc->sc_scowr_mbuf);
757 sc->sc_scowr_mbuf = NULL;
760 /* Empty mbuf queues */
761 IF_DRAIN(&sc->sc_cmd_queue);
762 IF_DRAIN(&sc->sc_aclwr_queue);
763 IF_DRAIN(&sc->sc_scowr_queue);
765 crit_exit();
768 /*******************************************************************************
770 * Bluetooth Unit/USB callbacks
772 * All of this will be called at the IPL_ we specified above
775 ubt_enable(struct device *self)
777 struct ubt_softc *sc = device_get_softc(self);
778 usbd_status err;
779 int i, error;
781 DPRINTFN(1, "%s: sc=%p\n", __func__, sc);
783 if (sc->sc_enabled)
784 return 0;
786 crit_enter();
788 /* Events */
789 sc->sc_evt_buf = kmalloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT);
790 if (sc->sc_evt_buf == NULL) {
791 error = ENOMEM;
792 goto bad;
795 err = usbd_open_pipe_intr(sc->sc_iface0,
796 sc->sc_evt_addr,
797 USBD_SHORT_XFER_OK,
798 &sc->sc_evt_pipe,
800 sc->sc_evt_buf,
801 UBT_BUFSIZ_EVENT,
802 ubt_recv_event,
803 UBT_INTR_TIMEOUT);
804 if (err != USBD_NORMAL_COMPLETION) {
805 error = EIO;
806 kprintf("can't open events pipe_intr\n");
807 goto bad;
810 /* Commands */
811 sc->sc_cmd_xfer = usbd_alloc_xfer(sc->sc_udev);
812 if (sc->sc_cmd_xfer == NULL) {
813 kprintf("can't allocate cmd_xfer\n");
814 error = ENOMEM;
815 goto bad;
817 sc->sc_cmd_buf = usbd_alloc_buffer(sc->sc_cmd_xfer, UBT_BUFSIZ_CMD);
818 if (sc->sc_cmd_buf == NULL) {
819 kprintf("can't allocate cmd_buf\n");
820 error = ENOMEM;
821 goto bad;
823 sc->sc_cmd_busy = 0;
825 /* ACL read */
826 err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr,
827 USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe);
828 if (err != USBD_NORMAL_COMPLETION) {
829 kprintf("can't open aclrd pipe\n");
830 error = EIO;
831 goto bad;
833 sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
834 if (sc->sc_aclrd_xfer == NULL) {
835 kprintf("can't allocate aclrd_xfer\n");
836 error = ENOMEM;
837 goto bad;
839 sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer, UBT_BUFSIZ_ACL);
840 if (sc->sc_aclrd_buf == NULL) {
841 kprintf("can't allocate aclrd_buf\n");
842 error = ENOMEM;
843 goto bad;
845 sc->sc_aclrd_busy = 0;
846 ubt_recv_acl_start(sc);
848 /* ACL write */
849 err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr,
850 USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe);
851 if (err != USBD_NORMAL_COMPLETION) {
852 kprintf("can't open aclwr pipe\n");
853 error = EIO;
854 goto bad;
856 sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
857 if (sc->sc_aclwr_xfer == NULL) {
858 kprintf("can't allocate aclwr_xfer\n");
859 error = ENOMEM;
860 goto bad;
862 sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer, UBT_BUFSIZ_ACL);
863 if (sc->sc_aclwr_buf == NULL) {
864 kprintf("can't allocate aclwr_buf\n");
865 error = ENOMEM;
866 goto bad;
868 sc->sc_aclwr_busy = 0;
870 /* SCO read */
871 if (sc->sc_scord_size > 0) {
872 err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr,
873 USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe);
874 if (err != USBD_NORMAL_COMPLETION) {
875 error = EIO;
876 goto bad;
879 for (i = 0 ; i < UBT_NXFERS ; i++) {
880 sc->sc_scord[i].xfer = usbd_alloc_xfer(sc->sc_udev);
881 if (sc->sc_scord[i].xfer == NULL) {
882 error = ENOMEM;
883 goto bad;
885 sc->sc_scord[i].buf = usbd_alloc_buffer(sc->sc_scord[i].xfer,
886 sc->sc_scord_size * UBT_NFRAMES);
887 if (sc->sc_scord[i].buf == NULL) {
888 error = ENOMEM;
889 goto bad;
891 sc->sc_scord[i].softc = sc;
892 sc->sc_scord[i].busy = 0;
893 ubt_recv_sco_start1(sc, &sc->sc_scord[i]);
897 /* SCO write */
898 if (sc->sc_scowr_size > 0) {
899 err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr,
900 USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe);
901 if (err != USBD_NORMAL_COMPLETION) {
902 error = EIO;
903 goto bad;
906 for (i = 0 ; i < UBT_NXFERS ; i++) {
907 sc->sc_scowr[i].xfer = usbd_alloc_xfer(sc->sc_udev);
908 if (sc->sc_scowr[i].xfer == NULL) {
909 error = ENOMEM;
910 goto bad;
912 sc->sc_scowr[i].buf = usbd_alloc_buffer(sc->sc_scowr[i].xfer,
913 sc->sc_scowr_size * UBT_NFRAMES);
914 if (sc->sc_scowr[i].buf == NULL) {
915 error = ENOMEM;
916 goto bad;
918 sc->sc_scowr[i].softc = sc;
919 sc->sc_scowr[i].busy = 0;
922 sc->sc_scowr_busy = 0;
925 sc->sc_enabled = 1;
926 crit_exit();
927 return 0;
929 bad:
930 ubt_abortdealloc(sc);
931 crit_exit();
932 return error;
935 void
936 ubt_disable(struct device *self)
938 struct ubt_softc *sc = device_get_softc(self);
940 DPRINTFN(1, "sc=%p\n", sc);
942 if (sc->sc_enabled == 0)
943 return;
945 ubt_abortdealloc(sc);
946 sc->sc_enabled = 0;
949 void
950 ubt_xmit_cmd(struct device *self, struct mbuf *m)
952 struct ubt_softc *sc = device_get_softc(self);
954 KKASSERT(sc->sc_enabled);
956 crit_enter();
957 IF_ENQUEUE(&sc->sc_cmd_queue, m);
959 if (sc->sc_cmd_busy == 0)
960 ubt_xmit_cmd_start(sc);
962 crit_exit();
965 void
966 ubt_xmit_cmd_start(struct ubt_softc *sc)
968 usb_device_request_t req;
969 usbd_status status;
970 struct mbuf *m;
971 int len;
973 if (sc->sc_dying)
974 return;
976 if (IF_QEMPTY(&sc->sc_cmd_queue))
977 return;
979 IF_DEQUEUE(&sc->sc_cmd_queue, m);
980 KKASSERT(m != NULL);
981 DPRINTFN(15, " %s: xmit CMD packet (%d bytes)\n",
982 device_get_nameunit(sc->sc_dev), m->m_pkthdr.len);
984 sc->sc_refcnt++;
986 sc->sc_cmd_busy = 1;
988 len = m->m_pkthdr.len - 1;
989 m_copydata(m, 1, len, sc->sc_cmd_buf);
990 m_freem(m);
992 memset(&req, 0, sizeof(req));
993 req.bmRequestType = UT_WRITE_CLASS_DEVICE;
994 USETW(req.wLength, len);
996 usbd_setup_default_xfer(sc->sc_cmd_xfer,
997 sc->sc_udev,
999 UBT_CMD_TIMEOUT,
1000 &req,
1001 sc->sc_cmd_buf,
1002 len,
1003 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1004 ubt_xmit_cmd_complete);
1006 status = usbd_transfer(sc->sc_cmd_xfer);
1008 KKASSERT(status != USBD_NORMAL_COMPLETION);
1010 if (status != USBD_IN_PROGRESS) {
1011 DPRINTF("usbd_transfer status=%s (%d)\n",
1012 usbd_errstr(status), status);
1013 sc->sc_refcnt--;
1014 sc->sc_cmd_busy = 0;
1019 void
1020 ubt_xmit_cmd_complete(usbd_xfer_handle xfer,
1021 usbd_private_handle h, usbd_status status)
1023 struct ubt_softc *sc = h;
1024 uint32_t count;
1026 DPRINTFN(15, " %s: CMD complete status=%s (%d)\n",
1027 device_get_nameunit(sc->sc_dev), usbd_errstr(status), status);
1029 sc->sc_cmd_busy = 0;
1031 if (--sc->sc_refcnt < 0) {
1032 DPRINTF("sc_refcnt=%d\n", sc->sc_refcnt);
1033 usb_detach_wakeup(sc->sc_dev);
1034 return;
1037 if (sc->sc_dying) {
1038 DPRINTF("sc_dying\n");
1039 return;
1042 if (status != USBD_NORMAL_COMPLETION) {
1043 DPRINTF("status=%s (%d)\n",
1044 usbd_errstr(status), status);
1045 sc->sc_stats.err_tx++;
1046 return;
1049 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1050 sc->sc_stats.cmd_tx++;
1051 sc->sc_stats.byte_tx += count;
1053 ubt_xmit_cmd_start(sc);
1056 void
1057 ubt_xmit_acl(struct device *self, struct mbuf *m)
1059 struct ubt_softc *sc = device_get_softc(self);
1061 KKASSERT(sc->sc_enabled);
1063 crit_enter();
1064 IF_ENQUEUE(&sc->sc_aclwr_queue, m);
1066 if (sc->sc_aclwr_busy == 0)
1067 ubt_xmit_acl_start(sc);
1069 crit_exit();
1072 void
1073 ubt_xmit_acl_start(struct ubt_softc *sc)
1075 struct mbuf *m;
1076 usbd_status status;
1077 int len;
1079 if (sc->sc_dying)
1080 return;
1083 if (IF_QEMPTY(&sc->sc_aclwr_queue))
1084 return;
1086 sc->sc_refcnt++;
1087 sc->sc_aclwr_busy = 1;
1089 IF_DEQUEUE(&sc->sc_aclwr_queue, m);
1090 KKASSERT(m != NULL);
1092 DPRINTFN(15, "%s: xmit ACL packet (%d bytes)\n",
1093 device_get_nameunit(sc->sc_dev), m->m_pkthdr.len);
1095 len = m->m_pkthdr.len - 1;
1096 if (len > UBT_BUFSIZ_ACL) {
1097 DPRINTF("%s: truncating ACL packet (%d => %d)!\n",
1098 device_get_nameunit(sc->sc_dev), len, UBT_BUFSIZ_ACL);
1100 len = UBT_BUFSIZ_ACL;
1103 m_copydata(m, 1, len, sc->sc_aclwr_buf);
1104 m_freem(m);
1106 sc->sc_stats.acl_tx++;
1107 sc->sc_stats.byte_tx += len;
1109 usbd_setup_xfer(sc->sc_aclwr_xfer,
1110 sc->sc_aclwr_pipe,
1112 sc->sc_aclwr_buf,
1113 len,
1114 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1115 UBT_ACL_TIMEOUT,
1116 ubt_xmit_acl_complete);
1118 status = usbd_transfer(sc->sc_aclwr_xfer);
1120 KKASSERT(status != USBD_NORMAL_COMPLETION);
1122 if (status != USBD_IN_PROGRESS) {
1123 DPRINTF("usbd_transfer status=%s (%d)\n",
1124 usbd_errstr(status), status);
1126 sc->sc_refcnt--;
1127 sc->sc_aclwr_busy = 0;
1132 void
1133 ubt_xmit_acl_complete(usbd_xfer_handle xfer,
1134 usbd_private_handle h, usbd_status status)
1136 struct ubt_softc *sc = h;
1138 DPRINTFN(15, "%s: ACL complete status=%s (%d)\n",
1139 device_get_nameunit(sc->sc_dev), usbd_errstr(status), status);
1141 sc->sc_aclwr_busy = 0;
1143 if (--sc->sc_refcnt < 0) {
1144 usb_detach_wakeup(sc->sc_dev);
1145 return;
1148 if (sc->sc_dying)
1149 return;
1151 if (status != USBD_NORMAL_COMPLETION) {
1152 DPRINTF("status=%s (%d)\n",
1153 usbd_errstr(status), status);
1155 sc->sc_stats.err_tx++;
1157 if (status == USBD_STALLED)
1158 usbd_clear_endpoint_stall_async(sc->sc_aclwr_pipe);
1159 else
1160 return;
1163 ubt_xmit_acl_start(sc);
1167 void
1168 ubt_xmit_sco(struct device *self, struct mbuf *m)
1170 struct ubt_softc *sc = device_get_softc(self);
1172 KKASSERT(sc->sc_enabled);
1174 crit_enter();
1175 IF_ENQUEUE(&sc->sc_scowr_queue, m);
1177 if (sc->sc_scowr_busy == 0)
1178 ubt_xmit_sco_start(sc);
1180 crit_exit();
1183 void
1184 ubt_xmit_sco_start(struct ubt_softc *sc)
1186 int i;
1188 if (sc->sc_dying || sc->sc_scowr_size == 0)
1189 return;
1191 for (i = 0 ; i < UBT_NXFERS ; i++) {
1192 if (sc->sc_scowr[i].busy)
1193 continue;
1195 ubt_xmit_sco_start1(sc, &sc->sc_scowr[i]);
1199 void
1200 ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1202 struct mbuf *m;
1203 uint8_t *buf;
1204 int num, len, size, space;
1206 if (sc->sc_dying)
1207 return;
1209 space = sc->sc_scowr_size * UBT_NFRAMES;
1210 buf = isoc->buf;
1211 len = 0;
1214 * Fill the request buffer with data from the queue,
1215 * keeping any leftover packet on our private hook.
1217 * Complete packets are passed back up to the stack
1218 * for disposal, since we can't rely on the controller
1219 * to tell us when it has finished with them.
1222 m = sc->sc_scowr_mbuf;
1223 while (space > 0) {
1224 if (m == NULL) {
1225 crit_enter();
1226 IF_DEQUEUE(&sc->sc_scowr_queue, m);
1227 crit_exit();
1228 if (m == NULL)
1229 break;
1231 m_adj(m, 1); /* packet type */
1235 if (m->m_pkthdr.len > 0) {
1236 size = MIN(m->m_pkthdr.len, space);
1238 m_copydata(m, 0, size, buf);
1239 m_adj(m, size);
1241 buf += size;
1242 len += size;
1243 space -= size;
1246 if (m->m_pkthdr.len == 0) {
1247 sc->sc_stats.sco_tx++;
1248 if (!hci_complete_sco(sc->sc_unit, m))
1249 sc->sc_stats.err_tx++;
1251 m = NULL;
1254 sc->sc_scowr_mbuf = m;
1256 DPRINTFN(15, "isoc=%p, len=%d, space=%d\n", isoc, len, space);
1258 if (len == 0) /* nothing to send */
1260 return;
1262 sc->sc_refcnt++;
1263 sc->sc_scowr_busy = 1;
1264 sc->sc_stats.byte_tx += len;
1265 isoc->busy = 1;
1268 * calculate number of isoc frames and sizes
1271 for (num = 0 ; len > 0 ; num++) {
1272 size = MIN(sc->sc_scowr_size, len);
1274 isoc->size[num] = size;
1275 len -= size;
1278 usbd_setup_isoc_xfer(isoc->xfer,
1279 sc->sc_scowr_pipe,
1280 isoc,
1281 isoc->size,
1282 num,
1283 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1284 ubt_xmit_sco_complete);
1286 usbd_transfer(isoc->xfer);
1289 void
1290 ubt_xmit_sco_complete(usbd_xfer_handle xfer,
1291 usbd_private_handle h, usbd_status status)
1293 struct ubt_isoc_xfer *isoc = h;
1294 struct ubt_softc *sc;
1295 int i;
1297 KKASSERT(xfer == isoc->xfer);
1298 sc = isoc->softc;
1300 DPRINTFN(15, "isoc=%p, status=%s (%d)\n",
1301 isoc, usbd_errstr(status), status);
1303 isoc->busy = 0;
1305 for (i = 0 ; ; i++) {
1306 if (i == UBT_NXFERS) {
1307 sc->sc_scowr_busy = 0;
1308 break;
1311 if (sc->sc_scowr[i].busy)
1312 break;
1315 if (--sc->sc_refcnt < 0) {
1316 usb_detach_wakeup(sc->sc_dev);
1317 return;
1320 if (sc->sc_dying)
1321 return;
1323 if (status != USBD_NORMAL_COMPLETION) {
1324 DPRINTF("status=%s (%d)\n",
1325 usbd_errstr(status), status);
1327 sc->sc_stats.err_tx++;
1329 if (status == USBD_STALLED)
1330 usbd_clear_endpoint_stall_async(sc->sc_scowr_pipe);
1331 else
1332 return;
1335 ubt_xmit_sco_start(sc);
1339 * Load incoming data into an mbuf with leading type byte.
1341 static struct mbuf *
1342 ubt_mbufload(uint8_t *buf, int count, uint8_t type)
1344 struct mbuf *m;
1345 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1346 if (m == NULL) {kprintf(" MGETHDR return NULL\n");
1347 return NULL; }
1348 *mtod(m, uint8_t *) = type;
1349 m->m_pkthdr.len = m->m_len = MHLEN;
1350 m_copyback(m, 1, count, buf); /* (extends if necessary)*/
1351 if (m->m_pkthdr.len != MAX(MHLEN, count + 1)) {
1352 m_free(m);
1353 kprintf(" m->m_pkthdr.len != MAX() \n");
1354 return NULL;
1356 m->m_pkthdr.len = count + 1;
1357 m->m_len = MIN(MHLEN, m->m_pkthdr.len);
1358 return m;
1361 void
1362 ubt_recv_event(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
1364 struct ubt_softc *sc = h;
1365 struct mbuf *m;
1366 uint32_t count;
1367 void *buf;
1369 DPRINTFN(15, "sc=%p status=%s (%d)\n",
1370 sc, usbd_errstr(status), status);
1372 if (status != USBD_NORMAL_COMPLETION || sc->sc_dying)
1373 return;
1375 usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
1377 if (count < sizeof(hci_event_hdr_t) - 1) {
1378 DPRINTF("dumped undersized event (count = %d)\n", count);
1379 sc->sc_stats.err_rx++;
1380 return;
1383 sc->sc_stats.evt_rx++;
1384 sc->sc_stats.byte_rx += count;
1386 m = ubt_mbufload(buf, count, HCI_EVENT_PKT);
1387 if (m == NULL || !hci_input_event(sc->sc_unit, m))
1388 sc->sc_stats.err_rx++;
1391 void
1392 ubt_recv_acl_start(struct ubt_softc *sc)
1394 usbd_status status;
1396 DPRINTFN(15, "sc=%p\n", sc);
1398 if (sc->sc_aclrd_busy || sc->sc_dying) {
1399 DPRINTF("sc_aclrd_busy=%d, sc_dying=%d\n",
1400 sc->sc_aclrd_busy,
1401 sc->sc_dying);
1403 return;
1406 sc->sc_refcnt++;
1407 sc->sc_aclrd_busy = 1;
1409 usbd_setup_xfer(sc->sc_aclrd_xfer,
1410 sc->sc_aclrd_pipe,
1412 sc->sc_aclrd_buf,
1413 UBT_BUFSIZ_ACL,
1414 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1415 USBD_NO_TIMEOUT,
1416 ubt_recv_acl_complete);
1418 status = usbd_transfer(sc->sc_aclrd_xfer);
1420 KKASSERT(status != USBD_NORMAL_COMPLETION);
1422 if (status != USBD_IN_PROGRESS) {
1423 DPRINTF("usbd_transfer status=%s (%d)\n",
1424 usbd_errstr(status), status);
1426 sc->sc_refcnt--;
1427 sc->sc_aclrd_busy = 0;
1431 void
1432 ubt_recv_acl_complete(usbd_xfer_handle xfer,
1433 usbd_private_handle h, usbd_status status)
1435 struct ubt_softc *sc = h;
1436 struct mbuf *m;
1437 uint32_t count;
1438 void *buf;
1440 DPRINTFN(15, "sc=%p status=%s (%d)\n",
1441 sc, usbd_errstr(status), status);
1443 sc->sc_aclrd_busy = 0;
1445 if (--sc->sc_refcnt < 0) {
1446 DPRINTF("refcnt = %d\n", sc->sc_refcnt);
1447 usb_detach_wakeup(sc->sc_dev);
1448 return;
1451 if (sc->sc_dying) {
1452 DPRINTF("sc_dying\n");
1453 return;
1456 if (status != USBD_NORMAL_COMPLETION) {
1457 DPRINTF("status=%s (%d)\n",
1458 usbd_errstr(status), status);
1460 sc->sc_stats.err_rx++;
1462 if (status == USBD_STALLED)
1463 usbd_clear_endpoint_stall_async(sc->sc_aclrd_pipe);
1464 else
1465 return;
1466 } else {
1467 usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
1469 if (count < sizeof(hci_acldata_hdr_t) - 1) {
1470 DPRINTF("dumped undersized packet (%d)\n", count);
1471 sc->sc_stats.err_rx++;
1472 } else {
1473 sc->sc_stats.acl_rx++;
1474 sc->sc_stats.byte_rx += count;
1476 m = ubt_mbufload(buf, count, HCI_ACL_DATA_PKT);
1477 if (m == NULL || !hci_input_acl(sc->sc_unit, m))
1478 sc->sc_stats.err_rx++;
1482 /* and restart */
1483 ubt_recv_acl_start(sc);
1486 void
1487 ubt_recv_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1489 int i;
1491 DPRINTFN(15, "sc=%p, isoc=%p\n", sc, isoc);
1493 if (isoc->busy || sc->sc_dying || sc->sc_scord_size == 0) {
1494 DPRINTF("%s%s%s\n",
1495 isoc->busy ? " busy" : "",
1496 sc->sc_dying ? " dying" : "",
1497 sc->sc_scord_size == 0 ? " size=0" : "");
1499 return;
1502 sc->sc_refcnt++;
1503 isoc->busy = 1;
1505 for (i = 0 ; i < UBT_NFRAMES ; i++)
1506 isoc->size[i] = sc->sc_scord_size;
1508 usbd_setup_isoc_xfer(isoc->xfer,
1509 sc->sc_scord_pipe,
1510 isoc,
1511 isoc->size,
1512 UBT_NFRAMES,
1513 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1514 ubt_recv_sco_complete);
1516 usbd_transfer(isoc->xfer);
1519 void
1520 ubt_recv_sco_complete(usbd_xfer_handle xfer,
1521 usbd_private_handle h, usbd_status status)
1523 struct ubt_isoc_xfer *isoc = h;
1524 struct ubt_softc *sc;
1525 struct mbuf *m;
1526 uint32_t count;
1527 uint8_t *ptr, *frame;
1528 int i, size, got, want;
1530 KKASSERT(isoc != NULL);
1531 KKASSERT(isoc->xfer == xfer);
1533 sc = isoc->softc;
1534 isoc->busy = 0;
1536 if (--sc->sc_refcnt < 0) {
1537 DPRINTF("refcnt=%d\n", sc->sc_refcnt);
1538 usb_detach_wakeup(sc->sc_dev);
1539 return;
1542 if (sc->sc_dying) {
1543 DPRINTF("sc_dying\n");
1544 return;
1547 if (status != USBD_NORMAL_COMPLETION) {
1548 DPRINTF("status=%s (%d)\n",
1549 usbd_errstr(status), status);
1551 sc->sc_stats.err_rx++;
1553 if (status == USBD_STALLED) {
1554 usbd_clear_endpoint_stall_async(sc->sc_scord_pipe);
1555 goto restart;
1558 return;
1561 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1562 if (count == 0)
1563 goto restart;
1565 DPRINTFN(15, "sc=%p, isoc=%p, count=%u\n",
1566 sc, isoc, count);
1568 sc->sc_stats.byte_rx += count;
1571 * Extract SCO packets from ISOC frames. The way we have it,
1572 * no SCO packet can be bigger than MHLEN. This is unlikely
1573 * to actually happen, but if we ran out of mbufs and lost
1574 * sync then we may get spurious data that makes it seem that
1575 * way, so we discard data that wont fit. This doesnt really
1576 * help with the lost sync situation alas.
1579 m = sc->sc_scord_mbuf;
1580 if (m != NULL) {
1581 sc->sc_scord_mbuf = NULL;
1582 ptr = mtod(m, uint8_t *) + m->m_pkthdr.len;
1583 got = m->m_pkthdr.len;
1584 want = sizeof(hci_scodata_hdr_t);
1585 if (got >= want)
1586 want += mtod(m, hci_scodata_hdr_t *)->length ;
1587 } else {
1588 ptr = NULL;
1589 got = 0;
1590 want = 0;
1593 for (i = 0 ; i < UBT_NFRAMES ; i++) {
1594 frame = isoc->buf + (i * sc->sc_scord_size);
1596 while (isoc->size[i] > 0) {
1597 size = isoc->size[i];
1599 if (m == NULL) {
1600 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1601 if (m == NULL) {
1602 kprintf("%s: out of memory (xfer halted)\n",
1603 device_get_nameunit(sc->sc_dev));
1605 sc->sc_stats.err_rx++;
1606 return; /* lost sync */
1609 ptr = mtod(m, uint8_t *);
1610 *ptr++ = HCI_SCO_DATA_PKT;
1611 got = 1;
1612 want = sizeof(hci_scodata_hdr_t);
1615 if (got + size > want)
1616 size = want - got;
1618 if (got + size > MHLEN)
1619 memcpy(ptr, frame, MHLEN - got);
1620 else
1621 memcpy(ptr, frame, size);
1623 ptr += size;
1624 got += size;
1625 frame += size;
1627 if (got == want) {
1629 * If we only got a header, add the packet
1630 * length to our want count. Send complete
1631 * packets up to protocol stack.
1633 if (want == sizeof(hci_scodata_hdr_t))
1634 want += mtod(m, hci_scodata_hdr_t *)->length;
1636 if (got == want) {
1637 m->m_pkthdr.len = m->m_len = got;
1638 sc->sc_stats.sco_rx++;
1639 if (!hci_input_sco(sc->sc_unit, m))
1640 sc->sc_stats.err_rx++;
1642 m = NULL;
1646 isoc->size[i] -= size;
1650 if (m != NULL) {
1651 m->m_pkthdr.len = m->m_len = got;
1652 sc->sc_scord_mbuf = m;
1655 restart: /* and restart */
1656 ubt_recv_sco_start1(sc, isoc);
1659 void
1660 ubt_stats(struct device *self, struct bt_stats *dest, int flush)
1662 struct ubt_softc *sc = device_get_softc(self);
1664 crit_enter();
1665 memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
1667 if (flush)
1668 memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
1670 crit_exit();