Implement SCO related sysctls.
[dragonfly.git] / sys / dev / usbmisc / ubt / ubt.c
blob03d1d2a537dafc4af584de9fa3ce6ec6cf71f1be
1 /* $OpenBSD: ubt.c,v 1.9 2007/10/11 18:33:14 deraadt Exp $ */
2 /* $DragonFly: src/sys/dev/usbmisc/ubt/ubt.c,v 1.2 2008/02/03 06:27:48 hasso Exp $ */
4 /*-
5 * Copyright (c) 2006 Itronix Inc.
6 * All rights reserved.
8 * Written by Iain Hibbert for Itronix Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of Itronix Inc. may not be used to endorse
19 * or promote products derived from this software without specific
20 * prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
35 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
36 * All rights reserved.
38 * This code is derived from software contributed to The NetBSD Foundation
39 * by Lennart Augustsson (lennart@augustsson.net) and
40 * David Sainty (David.Sainty@dtsp.co.nz).
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by the NetBSD
53 * Foundation, Inc. and its contributors.
54 * 4. Neither the name of The NetBSD Foundation nor the names of its
55 * contributors may be used to endorse or promote products derived
56 * from this software without specific prior written permission.
58 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
59 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
60 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
61 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
62 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
63 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
64 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
65 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
66 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
67 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68 * POSSIBILITY OF SUCH DAMAGE.
71 * This driver originally written by Lennart Augustsson and David Sainty,
72 * but was mostly rewritten for the NetBSD Bluetooth protocol stack by
73 * Iain Hibbert for Itronix, Inc using the FreeBSD ng_ubt.c driver as a
74 * reference.
77 #include <sys/bus.h>
78 #include <sys/kernel.h>
79 #include <sys/proc.h>
80 #include <sys/sysctl.h>
82 #include <bus/usb/usb.h>
83 #include <bus/usb/usbdi.h>
84 #include <bus/usb/usbdi_util.h>
85 #include <bus/usb/usbdivar.h>
87 #include <netbt/bluetooth.h>
88 #include <netbt/hci.h>
90 /*******************************************************************************
92 * debugging stuff
94 #undef DPRINTF
95 #undef DPRINTFN
97 #ifdef UBT_DEBUG
98 int ubt_debug = UBT_DEBUG;
100 #define DPRINTF(fmt, args...) do { \
101 if (ubt_debug) \
102 kprintf("%s: "fmt, __func__ , ##args); \
103 } while (/* CONSTCOND */0)
105 #define DPRINTFN(n, fmt, args...) do { \
106 if (ubt_debug > (n)) \
107 kprintf("%s: "fmt, __func__ , ##args); \
108 } while (/* CONSTCOND */0)
110 #else
111 #define DPRINTF(...)
112 #define DPRINTFN(...)
113 #endif
115 /*******************************************************************************
117 * ubt softc structure
121 /* buffer sizes */
123 * NB: although ACL packets can extend to 65535 bytes, most devices
124 * have max_acl_size at much less (largest I have seen is 384)
126 #define UBT_BUFSIZ_CMD (HCI_CMD_PKT_SIZE - 1)
127 #define UBT_BUFSIZ_ACL (2048 - 1)
128 #define UBT_BUFSIZ_EVENT (HCI_EVENT_PKT_SIZE - 1)
130 /* Transmit timeouts */
132 #define UBT_CMD_TIMEOUT 100
133 #define UBT_ACL_TIMEOUT 100
136 * Specification says, that is must be 1ms, but it causes kernel panic.
137 * Setting interval to USBD_DEFAULT_INTERVAL is not working for some of
138 * us either.
139 * XXX: Make it sysctl.
141 #define UBT_INTR_TIMEOUT USBD_DEFAULT_INTERVAL
144 * ISOC transfers
146 * xfer buffer size depends on the frame size, and the number
147 * of frames per transfer is fixed, as each frame should be
148 * 1ms worth of data. This keeps the rate that xfers complete
149 * fairly constant. We use multiple xfers to keep the hardware
150 * busy
152 #define UBT_NXFERS 3 /* max xfers to queue */
153 #define UBT_NFRAMES 10 /* frames per xfer */
155 struct ubt_isoc_xfer {
156 struct ubt_softc *softc;
157 usbd_xfer_handle xfer;
158 uint8_t *buf;
159 uint16_t size[UBT_NFRAMES];
160 int busy;
163 struct ubt_softc {
164 device_t sc_dev;
165 usbd_device_handle sc_udev;
166 int sc_refcnt;
167 int sc_dying;
169 /* Control Interface */
170 usbd_interface_handle sc_iface0;
172 /* Commands (control) */
173 usbd_xfer_handle sc_cmd_xfer;
174 u_char *sc_cmd_buf;
176 /* Events (interrupt) */
177 int sc_evt_addr; /* endpoint address */
178 usbd_pipe_handle sc_evt_pipe;
179 u_char *sc_evt_buf;
182 /* ACL data (in) */
183 int sc_aclrd_addr; /* endpoint address */
184 usbd_pipe_handle sc_aclrd_pipe; /* read pipe */
185 usbd_xfer_handle sc_aclrd_xfer; /* read xfer */
186 u_char *sc_aclrd_buf; /* read buffer */
187 int sc_aclrd_busy; /* reading */
189 /* ACL data (out) */
190 int sc_aclwr_addr; /* endpoint address */
191 usbd_pipe_handle sc_aclwr_pipe; /* write pipe */
192 usbd_xfer_handle sc_aclwr_xfer; /* write xfer */
193 u_char *sc_aclwr_buf; /* write buffer */
195 /* ISOC interface */
196 usbd_interface_handle sc_iface1; /* ISOC interface */
197 struct sysctllog *sc_log; /* sysctl log */
198 int sc_config; /* current config no */
199 int sc_alt_config; /* no of alternates */
201 /* SCO data (in) */
202 int sc_scord_addr; /* endpoint address */
203 usbd_pipe_handle sc_scord_pipe; /* read pipe */
204 int sc_scord_size; /* frame length */
205 struct ubt_isoc_xfer sc_scord[UBT_NXFERS];
206 struct mbuf *sc_scord_mbuf; /* current packet */
208 /* SCO data (out) */
209 int sc_scowr_addr; /* endpoint address */
210 usbd_pipe_handle sc_scowr_pipe; /* write pipe */
211 int sc_scowr_size; /* frame length */
212 struct ubt_isoc_xfer sc_scowr[UBT_NXFERS];
213 struct mbuf *sc_scowr_mbuf; /* current packet */
215 /* Protocol structure */
216 struct hci_unit sc_unit;
218 /* Successfully attached */
219 int sc_ok;
221 struct sysctl_ctx_list sysctl_ctx;
222 struct sysctl_oid *sysctl_tree;
226 * Bluetooth unit/USB callback routines
228 int ubt_enable(struct hci_unit *);
229 void ubt_disable(struct hci_unit *);
231 void ubt_xmit_cmd_start(struct hci_unit *);
232 void ubt_xmit_cmd_complete(usbd_xfer_handle,
233 usbd_private_handle, usbd_status);
235 void ubt_xmit_acl_start(struct hci_unit *);
236 void ubt_xmit_acl_complete(usbd_xfer_handle,
237 usbd_private_handle, usbd_status);
239 void ubt_xmit_sco_start(struct hci_unit *);
240 void ubt_xmit_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
241 void ubt_xmit_sco_complete(usbd_xfer_handle,
242 usbd_private_handle, usbd_status);
244 void ubt_recv_event(usbd_xfer_handle,
245 usbd_private_handle, usbd_status);
247 void ubt_recv_acl_start(struct ubt_softc *);
248 void ubt_recv_acl_complete(usbd_xfer_handle,
249 usbd_private_handle, usbd_status);
251 void ubt_recv_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
252 void ubt_recv_sco_complete(usbd_xfer_handle,
253 usbd_private_handle, usbd_status);
255 static device_probe_t ubt_match;
256 static device_attach_t ubt_attach;
257 static device_detach_t ubt_detach;
259 static devclass_t ubt_devclass;
261 static device_method_t ubt_methods[] = {
262 DEVMETHOD(device_probe, ubt_match),
263 DEVMETHOD(device_attach, ubt_attach),
264 DEVMETHOD(device_detach, ubt_detach),
265 {0,0},
266 {0,0}
269 static driver_t ubt_driver = {
270 "ubt",
271 ubt_methods,
272 sizeof(struct ubt_softc)
275 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, usbd_driver_load, 0);
276 MODULE_DEPEND(ubt, netbt, 1, 1, 1);
277 #if 0 /* not yet */
278 MODULE_DEPEND(ubt, bthub, 1, 1, 1);
279 #endif
280 MODULE_DEPEND(ubt, usb, 1, 1, 1);
282 static int ubt_set_isoc_config(struct ubt_softc *);
283 static int ubt_sysctl_config(SYSCTL_HANDLER_ARGS);
284 static void ubt_abortdealloc(struct ubt_softc *);
287 * Match against the whole device, since we want to take
288 * both interfaces. If a device should be ignored then add
290 * { VendorID, ProductID }
292 * to the ubt_ignore list.
294 static const struct usb_devno ubt_ignore[] = {
295 { USB_DEVICE(0x0a5c, 0x2000) }, /* Braodcom BCM2033 */
296 { USB_DEVICE(0x0a5c, 0x2033) }, /* Broadcom BCM2033 (no fw) */
297 { 0, 0 } /* end of list */
300 static int
301 ubt_match(device_t self)
304 struct usb_attach_arg *uaa = device_get_ivars(self);
305 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
307 DPRINTFN(50, "ubt_match\n");
309 if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product))
310 return UMATCH_NONE;
312 if (dd->bDeviceClass == UDCLASS_WIRELESS
313 && dd->bDeviceSubClass == UDSUBCLASS_RF
314 && dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
315 return UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO;
316 return UMATCH_NONE;
319 static int
320 ubt_attach(device_t self)
322 struct ubt_softc *sc = device_get_softc(self);
323 struct usb_attach_arg *uaa = device_get_ivars(self);
325 usb_config_descriptor_t *cd;
326 usb_endpoint_descriptor_t *ed;
327 int err;
328 uint8_t count, i;
330 DPRINTFN(50, "ubt_attach: sc=%p\n", sc);
332 sc->sc_udev = uaa->device;
333 sc->sc_dev = self;
336 * Move the device into the configured state
338 err = usbd_set_config_index(sc->sc_udev, 0, 1);
339 if (err) {
340 kprintf("%s: failed to set configuration idx 0: %s\n",
341 device_get_nameunit(sc->sc_dev), usbd_errstr(err));
343 return ENXIO;
347 * Interface 0 must have 3 endpoints
348 * 1) Interrupt endpoint to receive HCI events
349 * 2) Bulk IN endpoint to receive ACL data
350 * 3) Bulk OUT endpoint to send ACL data
353 err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
354 if (err) {
355 kprintf("%s: Could not get interface 0 handle %s (%d)\n",
356 device_get_nameunit(sc->sc_dev), usbd_errstr(err), err);
358 return ENXIO;
361 sc->sc_evt_addr = -1;
362 sc->sc_aclrd_addr = -1;
363 sc->sc_aclwr_addr = -1;
365 count = 0;
366 (void)usbd_endpoint_count(sc->sc_iface0, &count);
368 for (i = 0 ; i < count ; i++) {
369 int dir, type;
371 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
372 if (ed == NULL) {
373 kprintf("%s: could not read endpoint descriptor %d\n",
374 device_get_nameunit(sc->sc_dev), i);
376 return ENXIO;
379 dir = UE_GET_DIR(ed->bEndpointAddress);
380 type = UE_GET_XFERTYPE(ed->bmAttributes);
382 if (dir == UE_DIR_IN && type == UE_INTERRUPT)
383 sc->sc_evt_addr = ed->bEndpointAddress;
384 else if (dir == UE_DIR_IN && type == UE_BULK)
385 sc->sc_aclrd_addr = ed->bEndpointAddress;
386 else if (dir == UE_DIR_OUT && type == UE_BULK)
387 sc->sc_aclwr_addr = ed->bEndpointAddress;
390 if (sc->sc_evt_addr == -1) {
391 kprintf("%s: missing INTERRUPT endpoint on interface 0\n",
392 device_get_nameunit(sc->sc_dev));
394 return ENXIO;
396 if (sc->sc_aclrd_addr == -1) {
397 kprintf("%s: missing BULK IN endpoint on interface 0\n",
398 device_get_nameunit(sc->sc_dev));
400 return ENXIO;
402 if (sc->sc_aclwr_addr == -1) {
403 kprintf("%s: missing BULK OUT endpoint on interface 0\n",
404 device_get_nameunit(sc->sc_dev));
406 return ENXIO;
410 * Interface 1 must have 2 endpoints
411 * 1) Isochronous IN endpoint to receive SCO data
412 * 2) Isochronous OUT endpoint to send SCO data
414 * and will have several configurations, which can be selected
415 * via a sysctl variable. We select config 0 to start, which
416 * means that no SCO data will be available.
419 err = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
420 if (err) {
421 kprintf("%s: Could not get interface 1 handle %s (%d)\n",
422 device_get_nameunit(sc->sc_dev), usbd_errstr(err), err);
424 return ENXIO;
427 cd = usbd_get_config_descriptor(sc->sc_udev);
428 if (cd == NULL) {
429 kprintf("%s: could not get config descriptor\n",
430 device_get_nameunit(sc->sc_dev));
432 return ENXIO;
435 sc->sc_alt_config = usbd_get_no_alts(cd, 1);
437 /* set initial config */
439 err = ubt_set_isoc_config(sc);
440 if (err) {
441 kprintf("%s: ISOC config failed\n",
442 device_get_nameunit(sc->sc_dev));
444 return ENXIO;
447 /* Attach HCI host's software */
449 /* Fill HCI part of struct with data */
450 sc->sc_unit.hci_softc = self;
451 sc->sc_unit.hci_devname = device_get_nameunit(sc->sc_dev);
452 sc->sc_unit.hci_enable = ubt_enable;
453 sc->sc_unit.hci_disable = ubt_disable;
454 sc->sc_unit.hci_start_cmd = ubt_xmit_cmd_start;
455 sc->sc_unit.hci_start_acl = ubt_xmit_acl_start;
456 sc->sc_unit.hci_start_sco = ubt_xmit_sco_start;
458 /* Attach to HCI software stack */
460 hci_attach(&sc->sc_unit);
462 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
463 sc->sc_dev);
464 sc->sc_ok = 1;
466 sysctl_ctx_init(&sc->sysctl_ctx);
467 sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
468 SYSCTL_STATIC_CHILDREN(_hw),
469 OID_AUTO,
470 device_get_nameunit(sc->sc_dev),
471 CTLFLAG_RD, 0, "");
473 if (sc->sysctl_tree == NULL) {
474 /* Failure isn't fatal */
475 device_printf(sc->sc_dev, "Unable to create sysctl tree\n");
476 return 0;
479 SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
480 OID_AUTO, "config", CTLTYPE_INT|CTLFLAG_RW, (void *)sc,
481 0, ubt_sysctl_config, "I", "Configuration number");
482 SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
483 OID_AUTO, "alt_config", CTLFLAG_RD, &sc->sc_alt_config,
484 0, "Number of alternate configurations");
485 SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
486 OID_AUTO, "sco_rxsize", CTLFLAG_RD, &sc->sc_scord_size,
487 0, "Max SCO receive size");
488 SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
489 OID_AUTO, "sco_wrsize", CTLFLAG_RD, &sc->sc_scowr_size,
490 0, "Max SCO transmit size");
492 return 0;
495 static int
496 ubt_detach(device_t self)
499 struct ubt_softc *sc = device_get_softc(self);
501 DPRINTF("sc=%p \n", sc);
503 sc->sc_dying = 1;
505 if (!sc->sc_ok)
506 return 0;
508 /* Detach HCI interface */
510 hci_detach(&sc->sc_unit);
513 * Abort all pipes. Causes processes waiting for transfer to wake.
515 * Actually, hci_detach() above will call ubt_disable() which may
516 * call ubt_abortdealloc(), but lets be sure since doing it twice
517 * wont cause an error.
520 ubt_abortdealloc(sc);
522 /* wait for all processes to finish */
524 if (sc->sc_refcnt-- > 0)
525 usb_detach_wait(sc->sc_dev);
527 if (sc->sysctl_tree != NULL) {
528 sc->sysctl_tree = NULL;
529 sysctl_ctx_free(&sc->sysctl_ctx);
532 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
533 sc->sc_dev);
535 DPRINTFN(1, "driver detached\n");
537 return 0;
540 /* set ISOC configuration */
542 ubt_set_isoc_config(struct ubt_softc *sc)
544 usb_endpoint_descriptor_t *ed;
545 int rd_addr, wr_addr, rd_size, wr_size;
546 uint8_t count, i;
547 int err;
549 err = usbd_set_interface(sc->sc_iface1, sc->sc_config);
550 if (err != USBD_NORMAL_COMPLETION) {
551 kprintf(
552 "%s: Could not set config %d on ISOC interface. %s (%d)\n",
553 device_get_nameunit(sc->sc_dev), sc->sc_config, usbd_errstr(err), err);
555 return err == USBD_IN_USE ? EBUSY : EIO;
559 * We wont get past the above if there are any pipes open, so no
560 * need to worry about buf/xfer/pipe deallocation. If we get an
561 * error after this, the frame quantities will be 0 and no SCO
562 * data will be possible.
565 sc->sc_scord_size = rd_size = 0;
566 sc->sc_scord_addr = rd_addr = -1;
568 sc->sc_scowr_size = wr_size = 0;
569 sc->sc_scowr_addr = wr_addr = -1;
571 count = 0;
572 (void)usbd_endpoint_count(sc->sc_iface1, &count);
574 for (i = 0 ; i < count ; i++) {
575 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
576 if (ed == NULL) {
577 kprintf("%s: could not read endpoint descriptor %d\n",
578 device_get_nameunit(sc->sc_dev), i);
580 return EIO;
583 DPRINTFN(5, "%s: endpoint type %02x (%02x) addr %02x (%s)\n",
584 device_get_nameunit(sc->sc_dev),
585 UE_GET_XFERTYPE(ed->bmAttributes),
586 UE_GET_ISO_TYPE(ed->bmAttributes),
587 ed->bEndpointAddress,
588 UE_GET_DIR(ed->bEndpointAddress) ? "in" : "out");
590 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
591 continue;
593 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
594 rd_addr = ed->bEndpointAddress;
595 rd_size = UGETW(ed->wMaxPacketSize);
596 } else {
597 wr_addr = ed->bEndpointAddress;
598 wr_size = UGETW(ed->wMaxPacketSize);
602 if (rd_addr == -1) {
603 kprintf(
604 "%s: missing ISOC IN endpoint on interface config %d\n",
605 device_get_nameunit(sc->sc_dev), sc->sc_config);
607 return ENOENT;
609 if (wr_addr == -1) {
610 kprintf(
611 "%s: missing ISOC OUT endpoint on interface config %d\n",
612 device_get_nameunit(sc->sc_dev), sc->sc_config);
614 return ENOENT;
617 #ifdef DIAGNOSTIC
618 if (rd_size > MLEN) {
619 kprintf("%s: rd_size=%d exceeds MLEN\n",
620 device_get_nameunit(sc->sc_dev), rd_size);
622 return EOVERFLOW;
625 if (wr_size > MLEN) {
626 kprintf("%s: wr_size=%d exceeds MLEN\n",
627 device_get_nameunit(sc->sc_dev), wr_size);
629 return EOVERFLOW;
631 #endif
633 sc->sc_scord_size = rd_size;
634 sc->sc_scord_addr = rd_addr;
636 sc->sc_scowr_size = wr_size;
637 sc->sc_scowr_addr = wr_addr;
639 return 0;
642 static int
643 ubt_sysctl_config(SYSCTL_HANDLER_ARGS)
645 struct ubt_softc *sc = (struct ubt_softc *)arg1;
646 int t, error;
648 t = sc->sc_config;
649 error = sysctl_handle_int(oidp, &t, sizeof(t), req);
650 if (error || req->newptr == NULL)
651 return error;
653 if (t < 0 || t >= sc->sc_alt_config)
654 return EINVAL;
656 /* This may not change when the unit is enabled */
657 if (sc->sc_unit.hci_flags & BTF_RUNNING)
658 return EBUSY;
660 sc->sc_config = t;
661 return ubt_set_isoc_config(sc);
664 void
665 ubt_abortdealloc(struct ubt_softc *sc)
667 int i;
669 DPRINTFN(1, "sc=%p\n", sc);
670 crit_enter();
671 /* Abort all pipes */
672 if (sc->sc_evt_pipe != NULL) {
673 usbd_abort_pipe(sc->sc_evt_pipe);
674 usbd_close_pipe(sc->sc_evt_pipe);
675 sc->sc_evt_pipe = NULL;
678 if (sc->sc_aclrd_pipe != NULL) {
679 usbd_abort_pipe(sc->sc_aclrd_pipe);
680 usbd_close_pipe(sc->sc_aclrd_pipe);
681 sc->sc_aclrd_pipe = NULL;
684 if (sc->sc_aclwr_pipe != NULL) {
685 usbd_abort_pipe(sc->sc_aclwr_pipe);
686 usbd_close_pipe(sc->sc_aclwr_pipe);
687 sc->sc_aclwr_pipe = NULL;
690 if (sc->sc_scord_pipe != NULL) {
691 usbd_abort_pipe(sc->sc_scord_pipe);
692 usbd_close_pipe(sc->sc_scord_pipe);
693 sc->sc_scord_pipe = NULL;
696 if (sc->sc_scowr_pipe != NULL) {
697 usbd_abort_pipe(sc->sc_scowr_pipe);
698 usbd_close_pipe(sc->sc_scowr_pipe);
699 sc->sc_scowr_pipe = NULL;
702 /* Free event buffer */
703 if (sc->sc_evt_buf != NULL) {
704 kfree(sc->sc_evt_buf, M_USBDEV);
705 sc->sc_evt_buf = NULL;
708 /* Free all xfers and xfer buffers (implicit) */
709 if (sc->sc_cmd_xfer != NULL) {
710 usbd_free_xfer(sc->sc_cmd_xfer);
711 sc->sc_cmd_xfer = NULL;
712 sc->sc_cmd_buf = NULL;
715 if (sc->sc_aclrd_xfer != NULL) {
716 usbd_free_xfer(sc->sc_aclrd_xfer);
717 sc->sc_aclrd_xfer = NULL;
718 sc->sc_aclrd_buf = NULL;
721 if (sc->sc_aclwr_xfer != NULL) {
722 usbd_free_xfer(sc->sc_aclwr_xfer);
723 sc->sc_aclwr_xfer = NULL;
724 sc->sc_aclwr_buf = NULL;
727 for (i = 0 ; i < UBT_NXFERS ; i++) {
728 if (sc->sc_scord[i].xfer != NULL) {
729 usbd_free_xfer(sc->sc_scord[i].xfer);
730 sc->sc_scord[i].xfer = NULL;
731 sc->sc_scord[i].buf = NULL;
734 if (sc->sc_scowr[i].xfer != NULL) {
735 usbd_free_xfer(sc->sc_scowr[i].xfer);
736 sc->sc_scowr[i].xfer = NULL;
737 sc->sc_scowr[i].buf = NULL;
741 /* Free partial SCO packets */
742 if (sc->sc_scord_mbuf != NULL) {
743 m_freem(sc->sc_scord_mbuf);
744 sc->sc_scord_mbuf = NULL;
747 if (sc->sc_scowr_mbuf != NULL) {
748 m_freem(sc->sc_scowr_mbuf);
749 sc->sc_scowr_mbuf = NULL;
751 crit_exit();
754 /*******************************************************************************
756 * Bluetooth Unit/USB callbacks
758 * All of this will be called at the IPL_ we specified above
761 ubt_enable(struct hci_unit *unit)
763 struct ubt_softc *sc = device_get_softc(unit->hci_softc);
764 usbd_status err;
765 int i, error;
767 DPRINTFN(1, "%s: sc=%p\n", __func__, sc);
769 if (unit->hci_flags & BTF_RUNNING)
770 return 0;
772 /* Events */
774 sc->sc_evt_buf = kmalloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT);
775 if (sc->sc_evt_buf == NULL) {
776 error = ENOMEM;
777 goto bad;
780 err = usbd_open_pipe_intr(sc->sc_iface0,
781 sc->sc_evt_addr,
782 USBD_SHORT_XFER_OK,
783 &sc->sc_evt_pipe,
785 sc->sc_evt_buf,
786 UBT_BUFSIZ_EVENT,
787 ubt_recv_event,
788 UBT_INTR_TIMEOUT);
789 if (err != USBD_NORMAL_COMPLETION) {
790 error = EIO;
791 kprintf("can't open events pipe_intr\n");
792 goto bad;
795 /* Commands */
797 sc->sc_cmd_xfer = usbd_alloc_xfer(sc->sc_udev);
798 if (sc->sc_cmd_xfer == NULL) {
799 kprintf("can't allocate cmd_xfer\n");
800 error = ENOMEM;
801 goto bad;
803 sc->sc_cmd_buf = usbd_alloc_buffer(sc->sc_cmd_xfer, UBT_BUFSIZ_CMD);
804 if (sc->sc_cmd_buf == NULL) {
805 kprintf("can't allocate cmd_buf\n");
806 error = ENOMEM;
807 goto bad;
810 /* ACL read */
812 err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr,
813 USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe);
814 if (err != USBD_NORMAL_COMPLETION) {
815 kprintf("can't open aclrd pipe\n");
816 error = EIO;
817 goto bad;
819 sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
820 if (sc->sc_aclrd_xfer == NULL) {
821 kprintf("can't allocate aclrd_xfer\n");
822 error = ENOMEM;
823 goto bad;
825 sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer, UBT_BUFSIZ_ACL);
826 if (sc->sc_aclrd_buf == NULL) {
827 kprintf("can't allocate aclrd_buf\n");
828 error = ENOMEM;
829 goto bad;
831 sc->sc_aclrd_busy = 0;
832 ubt_recv_acl_start(sc);
834 /* ACL write */
836 err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr,
837 USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe);
838 if (err != USBD_NORMAL_COMPLETION) {
839 kprintf("can't open aclwr pipe\n");
840 error = EIO;
841 goto bad;
843 sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
844 if (sc->sc_aclwr_xfer == NULL) {
845 kprintf("can't allocate aclwr_xfer\n");
846 error = ENOMEM;
847 goto bad;
849 sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer, UBT_BUFSIZ_ACL);
850 if (sc->sc_aclwr_buf == NULL) {
851 kprintf("can't allocate aclwr_buf\n");
852 error = ENOMEM;
853 goto bad;
856 /* SCO read */
858 if (sc->sc_scord_size > 0) {
859 err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr,
860 USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe);
861 if (err != USBD_NORMAL_COMPLETION) {
862 error = EIO;
863 goto bad;
866 for (i = 0 ; i < UBT_NXFERS ; i++) {
867 sc->sc_scord[i].xfer = usbd_alloc_xfer(sc->sc_udev);
868 if (sc->sc_scord[i].xfer == NULL) {
869 error = ENOMEM;
870 goto bad;
872 sc->sc_scord[i].buf = usbd_alloc_buffer(sc->sc_scord[i].xfer,
873 sc->sc_scord_size * UBT_NFRAMES);
874 if (sc->sc_scord[i].buf == NULL) {
875 error = ENOMEM;
876 goto bad;
878 sc->sc_scord[i].softc = sc;
879 sc->sc_scord[i].busy = 0;
880 ubt_recv_sco_start1(sc, &sc->sc_scord[i]);
884 /* SCO write */
886 if (sc->sc_scowr_size > 0) {
887 err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr,
888 USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe);
889 if (err != USBD_NORMAL_COMPLETION) {
890 error = EIO;
891 goto bad;
894 for (i = 0 ; i < UBT_NXFERS ; i++) {
895 sc->sc_scowr[i].xfer = usbd_alloc_xfer(sc->sc_udev);
896 if (sc->sc_scowr[i].xfer == NULL) {
897 error = ENOMEM;
898 goto bad;
900 sc->sc_scowr[i].buf = usbd_alloc_buffer(sc->sc_scowr[i].xfer,
901 sc->sc_scowr_size * UBT_NFRAMES);
902 if (sc->sc_scowr[i].buf == NULL) {
903 error = ENOMEM;
904 goto bad;
906 sc->sc_scowr[i].softc = sc;
907 sc->sc_scowr[i].busy = 0;
911 unit->hci_flags &= ~BTF_XMIT;
912 unit->hci_flags |= BTF_RUNNING;
914 return 0;
916 bad:
917 kprintf("ubt_enable: something going wrong... :( \n");
918 ubt_abortdealloc(sc);
919 return error;
922 void
923 ubt_disable(struct hci_unit *unit)
925 struct ubt_softc *sc = device_get_softc(unit->hci_softc);
927 DPRINTFN(1, "sc=%p\n", sc);
929 if ((unit->hci_flags & BTF_RUNNING) == 0)
930 return;
932 ubt_abortdealloc(sc);
934 unit->hci_flags &= ~BTF_RUNNING;
937 void
938 ubt_xmit_cmd_start(struct hci_unit *unit)
940 struct ubt_softc *sc = device_get_softc(unit->hci_softc);
941 usb_device_request_t req;
942 usbd_status status;
943 struct mbuf *m;
944 int len;
946 if (sc->sc_dying)
947 return;
951 if (IF_QEMPTY(&unit->hci_cmdq))
952 return;
953 IF_DEQUEUE(&unit->hci_cmdq, m);
954 DPRINTFN(15, " %s: xmit CMD packet (%d bytes)\n",
955 unit->hci_devname, m->m_pkthdr.len);
957 sc->sc_refcnt++;
959 unit->hci_flags |= BTF_XMIT_CMD;
961 len = m->m_pkthdr.len - 1;
962 m_copydata(m, 1, len, sc->sc_cmd_buf);
963 m_freem(m);
965 memset(&req, 0, sizeof(req));
966 req.bmRequestType = UT_WRITE_CLASS_DEVICE;
967 USETW(req.wLength, len);
969 usbd_setup_default_xfer(sc->sc_cmd_xfer,
970 sc->sc_udev,
971 unit,
972 UBT_CMD_TIMEOUT,
973 &req,
974 sc->sc_cmd_buf,
975 len,
976 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
977 ubt_xmit_cmd_complete);
979 status = usbd_transfer(sc->sc_cmd_xfer);
981 KKASSERT(status != USBD_NORMAL_COMPLETION);
983 if (status != USBD_IN_PROGRESS) {
984 DPRINTF("usbd_transfer status=%s (%d)\n",
985 usbd_errstr(status), status);
986 sc->sc_refcnt--;
987 unit->hci_flags &= ~BTF_XMIT_CMD;
992 void
993 ubt_xmit_cmd_complete(usbd_xfer_handle xfer,
994 usbd_private_handle h, usbd_status status)
996 struct hci_unit *unit = h;
997 struct ubt_softc *sc = device_get_softc(unit->hci_softc);
998 uint32_t count;
1000 DPRINTFN(15, " %s: CMD complete status=%s (%d)\n",
1001 unit->hci_devname, usbd_errstr(status), status);
1003 unit->hci_flags &= ~BTF_XMIT_CMD;
1005 if (--sc->sc_refcnt < 0) {
1006 DPRINTF("sc_refcnt=%d\n", sc->sc_refcnt);
1007 usb_detach_wakeup(sc->sc_dev);
1008 return;
1011 if (sc->sc_dying) {
1012 DPRINTF("sc_dying\n");
1013 return;
1016 if (status != USBD_NORMAL_COMPLETION) {
1017 DPRINTF("status=%s (%d)\n",
1018 usbd_errstr(status), status);
1019 unit->hci_stats.err_tx++;
1020 return;
1023 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1025 unit->hci_stats.cmd_tx++;
1026 unit->hci_stats.byte_tx += count;
1028 ubt_xmit_cmd_start(unit);
1031 void
1032 ubt_xmit_acl_start(struct hci_unit *unit)
1034 struct ubt_softc *sc = device_get_softc(unit->hci_softc);
1035 struct mbuf *m;
1036 usbd_status status;
1037 int len;
1039 if (sc->sc_dying)
1040 return;
1043 if (IF_QEMPTY(&unit->hci_acltxq))
1044 return;
1046 sc->sc_refcnt++;
1047 unit->hci_flags |= BTF_XMIT_ACL;
1049 IF_DEQUEUE(&unit->hci_acltxq, m);
1051 DPRINTFN(15, "%s: xmit ACL packet (%d bytes)\n",
1052 unit->hci_devname, m->m_pkthdr.len);
1054 len = m->m_pkthdr.len - 1;
1055 if (len > UBT_BUFSIZ_ACL) {
1056 DPRINTF("%s: truncating ACL packet (%d => %d)!\n",
1057 unit->hci_devname, len, UBT_BUFSIZ_ACL);
1059 len = UBT_BUFSIZ_ACL;
1062 m_copydata(m, 1, len, sc->sc_aclwr_buf);
1063 m_freem(m);
1065 unit->hci_stats.acl_tx++;
1066 unit->hci_stats.byte_tx += len;
1068 usbd_setup_xfer(sc->sc_aclwr_xfer,
1069 sc->sc_aclwr_pipe,
1070 unit,
1071 sc->sc_aclwr_buf,
1072 len,
1073 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1074 UBT_ACL_TIMEOUT,
1075 ubt_xmit_acl_complete);
1077 status = usbd_transfer(sc->sc_aclwr_xfer);
1079 KKASSERT(status != USBD_NORMAL_COMPLETION);
1081 if (status != USBD_IN_PROGRESS) {
1082 DPRINTF("usbd_transfer status=%s (%d)\n",
1083 usbd_errstr(status), status);
1085 sc->sc_refcnt--;
1086 unit->hci_flags &= ~BTF_XMIT_ACL;
1091 void
1092 ubt_xmit_acl_complete(usbd_xfer_handle xfer,
1093 usbd_private_handle h, usbd_status status)
1095 struct hci_unit *unit = h;
1096 struct ubt_softc *sc = device_get_softc(unit->hci_softc);
1098 DPRINTFN(15, "%s: ACL complete status=%s (%d)\n",
1099 unit->hci_devname, usbd_errstr(status), status);
1101 unit->hci_flags &= ~BTF_XMIT_ACL;
1103 if (--sc->sc_refcnt < 0) {
1104 usb_detach_wakeup(sc->sc_dev);
1105 return;
1108 if (sc->sc_dying)
1109 return;
1111 if (status != USBD_NORMAL_COMPLETION) {
1112 DPRINTF("status=%s (%d)\n",
1113 usbd_errstr(status), status);
1115 unit->hci_stats.err_tx++;
1117 if (status == USBD_STALLED)
1118 usbd_clear_endpoint_stall_async(sc->sc_aclwr_pipe);
1119 else
1120 return;
1123 ubt_xmit_acl_start(unit);
1127 void
1128 ubt_xmit_sco_start(struct hci_unit *unit)
1130 struct ubt_softc *sc = device_get_softc(unit->hci_softc);
1131 int i;
1133 if (sc->sc_dying || sc->sc_scowr_size == 0)
1134 return;
1136 for (i = 0 ; i < UBT_NXFERS ; i++) {
1137 if (sc->sc_scowr[i].busy)
1138 continue;
1140 ubt_xmit_sco_start1(sc, &sc->sc_scowr[i]);
1144 void
1145 ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1147 struct mbuf *m;
1148 uint8_t *buf;
1149 int num, len, size, space;
1151 if (sc->sc_dying)
1152 return;
1154 space = sc->sc_scowr_size * UBT_NFRAMES;
1155 buf = isoc->buf;
1156 len = 0;
1159 * Fill the request buffer with data from the queue,
1160 * keeping any leftover packet on our private hook.
1162 * Complete packets are passed back up to the stack
1163 * for disposal, since we can't rely on the controller
1164 * to tell us when it has finished with them.
1167 m = sc->sc_scowr_mbuf;
1168 while (space > 0) {
1169 if (m == NULL) {
1170 crit_enter();
1171 IF_DEQUEUE(&sc->sc_unit.hci_scotxq, m);
1172 crit_exit();
1173 if (m == NULL)
1174 break;
1176 m_adj(m, 1); /* packet type */
1180 if (m->m_pkthdr.len > 0) {
1181 size = MIN(m->m_pkthdr.len, space);
1183 m_copydata(m, 0, size, buf);
1184 m_adj(m, size);
1186 buf += size;
1187 len += size;
1188 space -= size;
1191 if (m->m_pkthdr.len == 0) {
1192 sc->sc_unit.hci_stats.sco_tx++;
1193 hci_complete_sco(&sc->sc_unit, m);
1194 m = NULL;
1197 sc->sc_scowr_mbuf = m;
1199 DPRINTFN(15, "isoc=%p, len=%d, space=%d\n", isoc, len, space);
1201 if (len == 0) /* nothing to send */
1203 return;
1205 sc->sc_refcnt++;
1206 sc->sc_unit.hci_flags |= BTF_XMIT_SCO;
1207 sc->sc_unit.hci_stats.byte_tx += len;
1208 isoc->busy = 1;
1211 * calculate number of isoc frames and sizes
1214 for (num = 0 ; len > 0 ; num++) {
1215 size = MIN(sc->sc_scowr_size, len);
1217 isoc->size[num] = size;
1218 len -= size;
1221 usbd_setup_isoc_xfer(isoc->xfer,
1222 sc->sc_scowr_pipe,
1223 isoc,
1224 isoc->size,
1225 num,
1226 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1227 ubt_xmit_sco_complete);
1229 usbd_transfer(isoc->xfer);
1232 void
1233 ubt_xmit_sco_complete(usbd_xfer_handle xfer,
1234 usbd_private_handle h, usbd_status status)
1236 struct ubt_isoc_xfer *isoc = h;
1237 struct ubt_softc *sc;
1238 int i;
1240 KKASSERT(xfer == isoc->xfer);
1241 sc = isoc->softc;
1243 DPRINTFN(15, "isoc=%p, status=%s (%d)\n",
1244 isoc, usbd_errstr(status), status);
1246 isoc->busy = 0;
1248 for (i = 0 ; ; i++) {
1249 if (i == UBT_NXFERS) {
1250 sc->sc_unit.hci_flags &= ~BTF_XMIT_SCO;
1251 break;
1254 if (sc->sc_scowr[i].busy)
1255 break;
1258 if (--sc->sc_refcnt < 0) {
1259 usb_detach_wakeup(sc->sc_dev);
1260 return;
1263 if (sc->sc_dying)
1264 return;
1266 if (status != USBD_NORMAL_COMPLETION) {
1267 DPRINTF("status=%s (%d)\n",
1268 usbd_errstr(status), status);
1270 sc->sc_unit.hci_stats.err_tx++;
1272 if (status == USBD_STALLED)
1273 usbd_clear_endpoint_stall_async(sc->sc_scowr_pipe);
1274 else
1275 return;
1278 ubt_xmit_sco_start(&sc->sc_unit);
1282 * Load incoming data into an mbuf with leading type byte.
1284 static struct mbuf *
1285 ubt_mbufload(uint8_t *buf, int count, uint8_t type)
1287 struct mbuf *m;
1288 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1289 if (m == NULL) {kprintf(" MGETHDR return NULL\n");
1290 return NULL; }
1291 *mtod(m, uint8_t *) = type;
1292 m->m_pkthdr.len = m->m_len = MHLEN;
1293 m_copyback(m, 1, count, buf); /* (extends if necessary)*/
1294 if (m->m_pkthdr.len != MAX(MHLEN, count + 1)) {
1295 m_free(m);
1296 kprintf(" m->m_pkthdr.len != MAX() \n");
1297 return NULL;
1299 m->m_pkthdr.len = count + 1;
1300 m->m_len = MIN(MHLEN, m->m_pkthdr.len);
1301 return m;
1304 void
1305 ubt_recv_event(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
1307 struct ubt_softc *sc = h;
1308 struct mbuf *m;
1309 uint32_t count;
1310 void *buf;
1312 DPRINTFN(15, "sc=%p status=%s (%d)\n",
1313 sc, usbd_errstr(status), status);
1315 if (status != USBD_NORMAL_COMPLETION || sc->sc_dying)
1316 return;
1318 usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
1320 if (count < sizeof(hci_event_hdr_t) - 1) {
1321 DPRINTF("dumped undersized event (count = %d)\n", count);
1322 sc->sc_unit.hci_stats.err_rx++;
1323 return;
1326 sc->sc_unit.hci_stats.evt_rx++;
1327 sc->sc_unit.hci_stats.byte_rx += count;
1329 m = ubt_mbufload(buf, count, HCI_EVENT_PKT);
1330 if (m != NULL){
1331 hci_input_event(&sc->sc_unit, m);
1333 else
1334 sc->sc_unit.hci_stats.err_rx++;
1337 void
1338 ubt_recv_acl_start(struct ubt_softc *sc)
1340 usbd_status status;
1342 DPRINTFN(15, "sc=%p\n", sc);
1344 if (sc->sc_aclrd_busy || sc->sc_dying) {
1345 DPRINTF("sc_aclrd_busy=%d, sc_dying=%d\n",
1346 sc->sc_aclrd_busy,
1347 sc->sc_dying);
1349 return;
1352 sc->sc_refcnt++;
1353 sc->sc_aclrd_busy = 1;
1355 usbd_setup_xfer(sc->sc_aclrd_xfer,
1356 sc->sc_aclrd_pipe,
1358 sc->sc_aclrd_buf,
1359 UBT_BUFSIZ_ACL,
1360 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1361 USBD_NO_TIMEOUT,
1362 ubt_recv_acl_complete);
1364 status = usbd_transfer(sc->sc_aclrd_xfer);
1366 KKASSERT(status != USBD_NORMAL_COMPLETION);
1368 if (status != USBD_IN_PROGRESS) {
1369 DPRINTF("usbd_transfer status=%s (%d)\n",
1370 usbd_errstr(status), status);
1372 sc->sc_refcnt--;
1373 sc->sc_aclrd_busy = 0;
1377 void
1378 ubt_recv_acl_complete(usbd_xfer_handle xfer,
1379 usbd_private_handle h, usbd_status status)
1381 struct ubt_softc *sc = h;
1382 struct mbuf *m;
1383 uint32_t count;
1384 void *buf;
1386 DPRINTFN(15, "sc=%p status=%s (%d)\n",
1387 sc, usbd_errstr(status), status);
1389 sc->sc_aclrd_busy = 0;
1391 if (--sc->sc_refcnt < 0) {
1392 DPRINTF("refcnt = %d\n", sc->sc_refcnt);
1393 usb_detach_wakeup(sc->sc_dev);
1394 return;
1397 if (sc->sc_dying) {
1398 DPRINTF("sc_dying\n");
1399 return;
1402 if (status != USBD_NORMAL_COMPLETION) {
1403 DPRINTF("status=%s (%d)\n",
1404 usbd_errstr(status), status);
1406 sc->sc_unit.hci_stats.err_rx++;
1408 if (status == USBD_STALLED)
1409 usbd_clear_endpoint_stall_async(sc->sc_aclrd_pipe);
1410 else
1411 return;
1412 } else {
1413 usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
1415 if (count < sizeof(hci_acldata_hdr_t) - 1) {
1416 DPRINTF("dumped undersized packet (%d)\n", count);
1417 sc->sc_unit.hci_stats.err_rx++;
1418 } else {
1419 sc->sc_unit.hci_stats.acl_rx++;
1420 sc->sc_unit.hci_stats.byte_rx += count;
1422 m = ubt_mbufload(buf, count, HCI_ACL_DATA_PKT);
1423 if (m != NULL)
1424 hci_input_acl(&sc->sc_unit, m);
1425 else
1426 sc->sc_unit.hci_stats.err_rx++;
1430 /* and restart */
1431 ubt_recv_acl_start(sc);
1434 void
1435 ubt_recv_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1437 int i;
1439 DPRINTFN(15, "sc=%p, isoc=%p\n", sc, isoc);
1441 if (isoc->busy || sc->sc_dying || sc->sc_scord_size == 0) {
1442 DPRINTF("%s%s%s\n",
1443 isoc->busy ? " busy" : "",
1444 sc->sc_dying ? " dying" : "",
1445 sc->sc_scord_size == 0 ? " size=0" : "");
1447 return;
1450 sc->sc_refcnt++;
1451 isoc->busy = 1;
1453 for (i = 0 ; i < UBT_NFRAMES ; i++)
1454 isoc->size[i] = sc->sc_scord_size;
1456 usbd_setup_isoc_xfer(isoc->xfer,
1457 sc->sc_scord_pipe,
1458 isoc,
1459 isoc->size,
1460 UBT_NFRAMES,
1461 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1462 ubt_recv_sco_complete);
1464 usbd_transfer(isoc->xfer);
1467 void
1468 ubt_recv_sco_complete(usbd_xfer_handle xfer,
1469 usbd_private_handle h, usbd_status status)
1471 struct ubt_isoc_xfer *isoc = h;
1472 struct ubt_softc *sc;
1473 struct mbuf *m;
1474 uint32_t count;
1475 uint8_t *ptr, *frame;
1476 int i, size, got, want;
1478 KKASSERT(isoc != NULL);
1479 KKASSERT(isoc->xfer == xfer);
1481 sc = isoc->softc;
1482 isoc->busy = 0;
1484 if (--sc->sc_refcnt < 0) {
1485 DPRINTF("refcnt=%d\n", sc->sc_refcnt);
1486 usb_detach_wakeup(sc->sc_dev);
1487 return;
1490 if (sc->sc_dying) {
1491 DPRINTF("sc_dying\n");
1492 return;
1495 if (status != USBD_NORMAL_COMPLETION) {
1496 DPRINTF("status=%s (%d)\n",
1497 usbd_errstr(status), status);
1499 sc->sc_unit.hci_stats.err_rx++;
1501 if (status == USBD_STALLED) {
1502 usbd_clear_endpoint_stall_async(sc->sc_scord_pipe);
1503 goto restart;
1506 return;
1509 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1510 if (count == 0)
1511 goto restart;
1513 DPRINTFN(15, "sc=%p, isoc=%p, count=%u\n",
1514 sc, isoc, count);
1516 sc->sc_unit.hci_stats.byte_rx += count;
1519 * Extract SCO packets from ISOC frames. The way we have it,
1520 * no SCO packet can be bigger than MHLEN. This is unlikely
1521 * to actually happen, but if we ran out of mbufs and lost
1522 * sync then we may get spurious data that makes it seem that
1523 * way, so we discard data that wont fit. This doesnt really
1524 * help with the lost sync situation alas.
1527 m = sc->sc_scord_mbuf;
1528 if (m != NULL) {
1529 sc->sc_scord_mbuf = NULL;
1530 ptr = mtod(m, uint8_t *) + m->m_pkthdr.len;
1531 got = m->m_pkthdr.len;
1532 want = sizeof(hci_scodata_hdr_t);
1533 if (got >= want)
1534 want += mtod(m, hci_scodata_hdr_t *)->length ;
1535 } else {
1536 ptr = NULL;
1537 got = 0;
1538 want = 0;
1541 for (i = 0 ; i < UBT_NFRAMES ; i++) {
1542 frame = isoc->buf + (i * sc->sc_scord_size);
1544 while (isoc->size[i] > 0) {
1545 size = isoc->size[i];
1547 if (m == NULL) {
1548 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1549 if (m == NULL) {
1550 kprintf("%s: out of memory (xfer halted)\n",
1551 device_get_nameunit(sc->sc_dev));
1553 sc->sc_unit.hci_stats.err_rx++;
1554 return; /* lost sync */
1557 ptr = mtod(m, uint8_t *);
1558 *ptr++ = HCI_SCO_DATA_PKT;
1559 got = 1;
1560 want = sizeof(hci_scodata_hdr_t);
1563 if (got + size > want)
1564 size = want - got;
1566 if (got + size > MHLEN)
1567 memcpy(ptr, frame, MHLEN - got);
1568 else
1569 memcpy(ptr, frame, size);
1571 ptr += size;
1572 got += size;
1573 frame += size;
1575 if (got == want) {
1577 * If we only got a header, add the packet
1578 * length to our want count. Send complete
1579 * packets up to protocol stack.
1581 if (want == sizeof(hci_scodata_hdr_t))
1582 want += mtod(m, hci_scodata_hdr_t *)->length;
1584 if (got == want) {
1585 m->m_pkthdr.len = m->m_len = got;
1586 sc->sc_unit.hci_stats.sco_rx++;
1587 hci_input_sco(&sc->sc_unit, m);
1588 m = NULL;
1592 isoc->size[i] -= size;
1596 if (m != NULL) {
1597 m->m_pkthdr.len = m->m_len = got;
1598 sc->sc_scord_mbuf = m;
1601 restart: /* and restart */
1602 ubt_recv_sco_start1(sc, isoc);