6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * $Id: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $
31 * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c,v 1.33 2007/06/23 04:34:38 imp Exp $
34 #include <sys/param.h>
35 #include <sys/systm.h>
38 #include <sys/endian.h>
39 #include <sys/filio.h>
40 #include <sys/fcntl.h>
42 #include <sys/malloc.h>
43 #include <sys/kernel.h>
44 #include <sys/module.h>
47 #include <machine/bus.h>
49 #include <dev/usb/usb.h>
50 #include <dev/usb/usbdi.h>
51 #include <dev/usb/usbdi_util.h>
52 #include <dev/usb/usbdivar.h>
54 #include "ng_message.h"
57 #include "bluetooth/include/ng_bluetooth.h"
58 #include "bluetooth/include/ng_hci.h"
59 #include "bluetooth/include/ng_ubt.h"
60 #include "bluetooth/drivers/ubt/ng_ubt_var.h"
68 static device_probe_t ubt_match;
69 static device_attach_t ubt_attach;
70 static device_detach_t ubt_detach;
72 static device_method_t ubt_methods[] = {
73 /* Device interface */
74 DEVMETHOD(device_probe, ubt_match),
75 DEVMETHOD(device_attach, ubt_attach),
76 DEVMETHOD(device_detach, ubt_detach),
81 static driver_t ubt_driver = {
84 sizeof(struct ubt_softc)
87 static devclass_t ubt_devclass;
89 static int ubt_modevent (module_t, int, void *);
91 static usbd_status ubt_request_start (ubt_softc_p);
92 static void ubt_request_complete (usbd_xfer_handle,
93 usbd_private_handle, usbd_status);
94 static void ubt_request_complete2 (node_p, hook_p, void *, int);
96 static usbd_status ubt_intr_start (ubt_softc_p);
97 static void ubt_intr_complete (usbd_xfer_handle,
98 usbd_private_handle, usbd_status);
99 static void ubt_intr_complete2 (node_p, hook_p, void *, int);
101 static usbd_status ubt_bulk_in_start (ubt_softc_p);
102 static void ubt_bulk_in_complete (usbd_xfer_handle,
103 usbd_private_handle, usbd_status);
104 static void ubt_bulk_in_complete2 (node_p, hook_p, void *, int);
106 static usbd_status ubt_bulk_out_start (ubt_softc_p);
107 static void ubt_bulk_out_complete (usbd_xfer_handle,
108 usbd_private_handle, usbd_status);
109 static void ubt_bulk_out_complete2 (node_p, hook_p, void *, int);
111 static usbd_status ubt_isoc_in_start (ubt_softc_p);
112 static void ubt_isoc_in_complete (usbd_xfer_handle,
113 usbd_private_handle, usbd_status);
114 static void ubt_isoc_in_complete2 (node_p, hook_p, void *, int);
116 static usbd_status ubt_isoc_out_start (ubt_softc_p);
117 static void ubt_isoc_out_complete (usbd_xfer_handle,
118 usbd_private_handle, usbd_status);
119 static void ubt_isoc_out_complete2 (node_p, hook_p, void *, int);
121 static void ubt_reset (ubt_softc_p);
127 static ng_constructor_t ng_ubt_constructor;
128 static ng_shutdown_t ng_ubt_shutdown;
129 static ng_newhook_t ng_ubt_newhook;
130 static ng_connect_t ng_ubt_connect;
131 static ng_disconnect_t ng_ubt_disconnect;
132 static ng_rcvmsg_t ng_ubt_rcvmsg;
133 static ng_rcvdata_t ng_ubt_rcvdata;
136 static const struct ng_parse_struct_field ng_ubt_node_qlen_type_fields[] =
138 { "queue", &ng_parse_int32_type, },
139 { "qlen", &ng_parse_int32_type, },
142 static const struct ng_parse_type ng_ubt_node_qlen_type = {
143 &ng_parse_struct_type,
144 &ng_ubt_node_qlen_type_fields
148 static const struct ng_parse_struct_field ng_ubt_node_stat_type_fields[] =
150 { "pckts_recv", &ng_parse_uint32_type, },
151 { "bytes_recv", &ng_parse_uint32_type, },
152 { "pckts_sent", &ng_parse_uint32_type, },
153 { "bytes_sent", &ng_parse_uint32_type, },
154 { "oerrors", &ng_parse_uint32_type, },
155 { "ierrors", &ng_parse_uint32_type, },
158 static const struct ng_parse_type ng_ubt_node_stat_type = {
159 &ng_parse_struct_type,
160 &ng_ubt_node_stat_type_fields
163 /* Netgraph node command list */
164 static const struct ng_cmdlist ng_ubt_cmdlist[] = {
167 NGM_UBT_NODE_SET_DEBUG,
169 &ng_parse_uint16_type,
174 NGM_UBT_NODE_GET_DEBUG,
177 &ng_parse_uint16_type
181 NGM_UBT_NODE_SET_QLEN,
183 &ng_ubt_node_qlen_type,
188 NGM_UBT_NODE_GET_QLEN,
190 &ng_ubt_node_qlen_type,
191 &ng_ubt_node_qlen_type
195 NGM_UBT_NODE_GET_STAT,
198 &ng_ubt_node_stat_type
202 NGM_UBT_NODE_RESET_STAT,
210 /* Netgraph node type */
211 static struct ng_type typestruct = {
212 .version = NG_ABI_VERSION,
213 .name = NG_UBT_NODE_TYPE,
214 .constructor = ng_ubt_constructor,
215 .rcvmsg = ng_ubt_rcvmsg,
216 .shutdown = ng_ubt_shutdown,
217 .newhook = ng_ubt_newhook,
218 .connect = ng_ubt_connect,
219 .rcvdata = ng_ubt_rcvdata,
220 .disconnect = ng_ubt_disconnect,
221 .cmdlist = ng_ubt_cmdlist
228 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, NULL);
229 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
230 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
231 MODULE_DEPEND(ubt, usb, 1, 1, 1);
234 /****************************************************************************
235 ****************************************************************************
237 ****************************************************************************
238 ****************************************************************************/
241 * Load/Unload the driver module
245 ubt_modevent(module_t mod, int event, void *data)
251 error = ng_newtype(&typestruct);
254 "%s: Could not register Netgraph node type, error=%d\n",
255 NG_UBT_NODE_TYPE, error);
257 error = usbd_driver_load(mod, event, data);
261 error = ng_rmtype(&typestruct);
263 error = usbd_driver_load(mod, event, data);
275 * Probe for a USB Bluetooth device
279 ubt_match(device_t self)
282 * If for some reason device should not be attached then put
283 * VendorID/ProductID pair into the list below. The format is
286 * { VENDOR_ID, PRODUCT_ID },
288 * where VENDOR_ID and PRODUCT_ID are hex numbers.
291 static struct usb_devno const ubt_ignored_devices[] = {
292 { USB_VENDOR_AVM, 0x2200 }, /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
293 { 0, 0 } /* This should be the last item in the list */
297 * If device violates Bluetooth specification and has bDeviceClass,
298 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
299 * could try to put VendorID/ProductID pair into the list below.
300 * Adding VendorID/ProductID pair into this list forces ng_ubt(4)
301 * to attach to the broken device.
304 static struct usb_devno const ubt_broken_devices[] = {
305 { USB_VENDOR_AVM, 0x3800 }, /* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
306 { 0, 0 } /* This should be the last item in the list */
309 struct usb_attach_arg *uaa = device_get_ivars(self);
310 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
312 if (uaa->iface == NULL ||
313 usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
314 return (UMATCH_NONE);
316 if (dd->bDeviceClass == UDCLASS_WIRELESS &&
317 dd->bDeviceSubClass == UDSUBCLASS_RF &&
318 dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
319 return (UMATCH_DEVCLASS_DEVSUBCLASS);
321 if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
322 return (UMATCH_VENDOR_PRODUCT);
324 return (UMATCH_NONE);
332 ubt_attach(device_t self)
334 struct ubt_softc *sc = device_get_softc(self);
335 struct usb_attach_arg *uaa = device_get_ivars(self);
336 usb_config_descriptor_t *cd = NULL;
337 usb_interface_descriptor_t *id = NULL;
338 usb_endpoint_descriptor_t *ed = NULL;
340 int i, ai, alt_no, isoc_in, isoc_out,
341 isoc_isize, isoc_osize;
343 /* Get USB device info */
345 sc->sc_udev = uaa->device;
348 * Initialize device softc structure
352 sc->sc_debug = NG_UBT_WARN_LEVEL;
354 NG_UBT_STAT_RESET(sc->sc_stat);
357 sc->sc_iface0 = sc->sc_iface1 = NULL;
361 sc->sc_intr_pipe = NULL;
362 sc->sc_intr_xfer = NULL;
363 sc->sc_intr_buffer = NULL;
366 sc->sc_ctrl_xfer = NULL;
367 sc->sc_ctrl_buffer = NULL;
368 NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
371 sc->sc_bulk_in_ep = -1;
372 sc->sc_bulk_in_pipe = NULL;
373 sc->sc_bulk_in_xfer = NULL;
374 sc->sc_bulk_in_buffer = NULL;
377 sc->sc_bulk_out_ep = -1;
378 sc->sc_bulk_out_pipe = NULL;
379 sc->sc_bulk_out_xfer = NULL;
380 sc->sc_bulk_out_buffer = NULL;
381 NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
384 sc->sc_isoc_in_ep = -1;
385 sc->sc_isoc_in_pipe = NULL;
386 sc->sc_isoc_in_xfer = NULL;
389 sc->sc_isoc_out_ep = -1;
390 sc->sc_isoc_out_pipe = NULL;
391 sc->sc_isoc_out_xfer = NULL;
392 sc->sc_isoc_size = -1;
393 NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
400 * XXX set configuration?
402 * Configure Bluetooth USB device. Discover all required USB interfaces
405 * USB device must present two interfaces:
406 * 1) Interface 0 that has 3 endpoints
407 * 1) Interrupt endpoint to receive HCI events
408 * 2) Bulk IN endpoint to receive ACL data
409 * 3) Bulk OUT endpoint to send ACL data
411 * 2) Interface 1 then has 2 endpoints
412 * 1) Isochronous IN endpoint to receive SCO data
413 * 2) Isochronous OUT endpoint to send SCO data
415 * Interface 1 (with isochronous endpoints) has several alternate
416 * configurations with different packet size.
423 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
424 if (error || sc->sc_iface0 == NULL) {
425 printf("%s: Could not get interface 0 handle. %s (%d), " \
426 "handle=%p\n", device_get_nameunit(sc->sc_dev),
427 usbd_errstr(error), error, sc->sc_iface0);
431 id = usbd_get_interface_descriptor(sc->sc_iface0);
433 printf("%s: Could not get interface 0 descriptor\n",
434 device_get_nameunit(sc->sc_dev));
438 for (i = 0; i < id->bNumEndpoints; i ++) {
439 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
441 printf("%s: Could not read endpoint descriptor for " \
442 "interface 0, i=%d\n", device_get_nameunit(sc->sc_dev),
447 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
449 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
450 sc->sc_bulk_in_ep = ed->bEndpointAddress;
452 sc->sc_bulk_out_ep = ed->bEndpointAddress;
456 sc->sc_intr_ep = ed->bEndpointAddress;
461 /* Check if we got everything we wanted on Interface 0 */
462 if (sc->sc_intr_ep == -1) {
463 printf("%s: Could not detect interrupt endpoint\n",
464 device_get_nameunit(sc->sc_dev));
467 if (sc->sc_bulk_in_ep == -1) {
468 printf("%s: Could not detect bulk-in endpoint\n",
469 device_get_nameunit(sc->sc_dev));
472 if (sc->sc_bulk_out_ep == -1) {
473 printf("%s: Could not detect bulk-out endpoint\n",
474 device_get_nameunit(sc->sc_dev));
478 printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
479 "bulk-out=%#x\n", device_get_nameunit(sc->sc_dev),
480 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
486 cd = usbd_get_config_descriptor(sc->sc_udev);
488 printf("%s: Could not get device configuration descriptor\n",
489 device_get_nameunit(sc->sc_dev));
493 error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
494 if (error || sc->sc_iface1 == NULL) {
495 printf("%s: Could not get interface 1 handle. %s (%d), " \
496 "handle=%p\n", device_get_nameunit(sc->sc_dev),
497 usbd_errstr(error), error, sc->sc_iface1);
501 id = usbd_get_interface_descriptor(sc->sc_iface1);
503 printf("%s: Could not get interface 1 descriptor\n",
504 device_get_nameunit(sc->sc_dev));
509 * Scan all alternate configurations for interface 1
514 for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++) {
515 error = usbd_set_interface(sc->sc_iface1, ai);
517 printf("%s: [SCAN] Could not set alternate " \
518 "configuration %d for interface 1. %s (%d)\n",
519 device_get_nameunit(sc->sc_dev), ai, usbd_errstr(error),
523 id = usbd_get_interface_descriptor(sc->sc_iface1);
525 printf("%s: Could not get interface 1 descriptor for " \
526 "alternate configuration %d\n",
527 device_get_nameunit(sc->sc_dev), ai);
531 isoc_in = isoc_out = -1;
532 isoc_isize = isoc_osize = 0;
534 for (i = 0; i < id->bNumEndpoints; i ++) {
535 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
537 printf("%s: Could not read endpoint " \
538 "descriptor for interface 1, " \
539 "alternate configuration %d, i=%d\n",
540 device_get_nameunit(sc->sc_dev), ai, i);
544 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
547 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
548 isoc_in = ed->bEndpointAddress;
549 isoc_isize = UGETW(ed->wMaxPacketSize);
551 isoc_out = ed->bEndpointAddress;
552 isoc_osize = UGETW(ed->wMaxPacketSize);
557 * Make sure that configuration looks sane and if so
558 * update current settings
561 if (isoc_in != -1 && isoc_out != -1 &&
562 isoc_isize > 0 && isoc_osize > 0 &&
563 isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
564 sc->sc_isoc_in_ep = isoc_in;
565 sc->sc_isoc_out_ep = isoc_out;
566 sc->sc_isoc_size = isoc_isize;
571 /* Check if we got everything we wanted on Interface 0 */
572 if (sc->sc_isoc_in_ep == -1) {
573 printf("%s: Could not detect isoc-in endpoint\n",
574 device_get_nameunit(sc->sc_dev));
577 if (sc->sc_isoc_out_ep == -1) {
578 printf("%s: Could not detect isoc-out endpoint\n",
579 device_get_nameunit(sc->sc_dev));
582 if (sc->sc_isoc_size <= 0) {
583 printf("%s: Invalid isoc. packet size=%d\n",
584 device_get_nameunit(sc->sc_dev), sc->sc_isoc_size);
588 error = usbd_set_interface(sc->sc_iface1, alt_no);
590 printf("%s: Could not set alternate configuration " \
591 "%d for interface 1. %s (%d)\n", device_get_nameunit(sc->sc_dev),
592 alt_no, usbd_errstr(error), error);
596 /* Allocate USB transfer handles and buffers */
597 sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
598 if (sc->sc_ctrl_xfer == NULL) {
599 printf("%s: Could not allocate control xfer handle\n",
600 device_get_nameunit(sc->sc_dev));
603 sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
604 UBT_CTRL_BUFFER_SIZE);
605 if (sc->sc_ctrl_buffer == NULL) {
606 printf("%s: Could not allocate control buffer\n",
607 device_get_nameunit(sc->sc_dev));
611 sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
612 if (sc->sc_intr_xfer == NULL) {
613 printf("%s: Could not allocate interrupt xfer handle\n",
614 device_get_nameunit(sc->sc_dev));
618 sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
619 if (sc->sc_bulk_in_xfer == NULL) {
620 printf("%s: Could not allocate bulk-in xfer handle\n",
621 device_get_nameunit(sc->sc_dev));
625 sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
626 if (sc->sc_bulk_out_xfer == NULL) {
627 printf("%s: Could not allocate bulk-out xfer handle\n",
628 device_get_nameunit(sc->sc_dev));
631 sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
632 UBT_BULK_BUFFER_SIZE);
633 if (sc->sc_bulk_out_buffer == NULL) {
634 printf("%s: Could not allocate bulk-out buffer\n",
635 device_get_nameunit(sc->sc_dev));
640 * Allocate buffers for isoc. transfers
643 sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
645 sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
646 if (sc->sc_isoc_in_xfer == NULL) {
647 printf("%s: Could not allocate isoc-in xfer handle\n",
648 device_get_nameunit(sc->sc_dev));
651 sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
652 sc->sc_isoc_nframes * sc->sc_isoc_size);
653 if (sc->sc_isoc_in_buffer == NULL) {
654 printf("%s: Could not allocate isoc-in buffer\n",
655 device_get_nameunit(sc->sc_dev));
658 sc->sc_isoc_in_frlen = kmalloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
659 M_USBDEV, M_WAITOK | M_NULLOK);
660 if (sc->sc_isoc_in_frlen == NULL) {
661 printf("%s: Could not allocate isoc-in frame sizes buffer\n",
662 device_get_nameunit(sc->sc_dev));
666 sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
667 if (sc->sc_isoc_out_xfer == NULL) {
668 printf("%s: Could not allocate isoc-out xfer handle\n",
669 device_get_nameunit(sc->sc_dev));
672 sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
673 sc->sc_isoc_nframes * sc->sc_isoc_size);
674 if (sc->sc_isoc_out_buffer == NULL) {
675 printf("%s: Could not allocate isoc-out buffer\n",
676 device_get_nameunit(sc->sc_dev));
679 sc->sc_isoc_out_frlen = kmalloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
680 M_USBDEV, M_WAITOK | M_NULLOK);
681 if (sc->sc_isoc_out_frlen == NULL) {
682 printf("%s: Could not allocate isoc-out frame sizes buffer\n",
683 device_get_nameunit(sc->sc_dev));
687 printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
688 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
689 device_get_nameunit(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
690 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
691 (sc->sc_isoc_nframes * sc->sc_isoc_size));
698 error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
699 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
700 if (error != USBD_NORMAL_COMPLETION) {
701 printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
702 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
708 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
709 USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
710 if (error != USBD_NORMAL_COMPLETION) {
711 printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
712 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
718 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
719 USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
720 if (error != USBD_NORMAL_COMPLETION) {
721 printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
722 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
727 #if 0 /* XXX FIXME */
729 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
730 USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
731 if (error != USBD_NORMAL_COMPLETION) {
732 printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
733 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
739 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
740 USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
741 if (error != USBD_NORMAL_COMPLETION) {
742 printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
743 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
749 /* Create Netgraph node */
750 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
751 printf("%s: Could not create Netgraph node\n",
752 device_get_nameunit(sc->sc_dev));
758 if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
759 printf("%s: Could not name Netgraph node\n",
760 device_get_nameunit(sc->sc_dev));
761 NG_NODE_UNREF(sc->sc_node);
766 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
767 NG_NODE_FORCE_WRITER(sc->sc_node);
769 /* Claim all interfaces on the device */
770 for (i = 0; i < uaa->nifaces; i++)
771 uaa->ifaces[i] = NULL;
773 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
788 ubt_detach(device_t self)
790 struct ubt_softc *sc = device_get_softc(self);
792 /* Destroy Netgraph node */
793 if (sc->sc_node != NULL) {
794 NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
795 ng_rmnode_self(sc->sc_node);
800 if (sc->sc_intr_pipe != NULL) {
801 usbd_close_pipe(sc->sc_intr_pipe);
802 sc->sc_intr_pipe = NULL;
805 if (sc->sc_bulk_in_pipe != NULL) {
806 usbd_close_pipe(sc->sc_bulk_in_pipe);
807 sc->sc_bulk_in_pipe = NULL;
809 if (sc->sc_bulk_out_pipe != NULL) {
810 usbd_close_pipe(sc->sc_bulk_out_pipe);
811 sc->sc_bulk_out_pipe = NULL;
814 if (sc->sc_isoc_in_pipe != NULL) {
815 usbd_close_pipe(sc->sc_isoc_in_pipe);
816 sc->sc_isoc_in_pipe = NULL;
818 if (sc->sc_isoc_out_pipe != NULL) {
819 usbd_close_pipe(sc->sc_isoc_out_pipe);
820 sc->sc_isoc_out_pipe = NULL;
823 /* Destroy USB transfer handles */
824 if (sc->sc_ctrl_xfer != NULL) {
825 usbd_free_xfer(sc->sc_ctrl_xfer);
826 sc->sc_ctrl_xfer = NULL;
829 if (sc->sc_intr_xfer != NULL) {
830 usbd_free_xfer(sc->sc_intr_xfer);
831 sc->sc_intr_xfer = NULL;
834 if (sc->sc_bulk_in_xfer != NULL) {
835 usbd_free_xfer(sc->sc_bulk_in_xfer);
836 sc->sc_bulk_in_xfer = NULL;
838 if (sc->sc_bulk_out_xfer != NULL) {
839 usbd_free_xfer(sc->sc_bulk_out_xfer);
840 sc->sc_bulk_out_xfer = NULL;
843 if (sc->sc_isoc_in_xfer != NULL) {
844 usbd_free_xfer(sc->sc_isoc_in_xfer);
845 sc->sc_isoc_in_xfer = NULL;
847 if (sc->sc_isoc_out_xfer != NULL) {
848 usbd_free_xfer(sc->sc_isoc_out_xfer);
849 sc->sc_isoc_out_xfer = NULL;
852 /* Destroy isoc. frame size buffers */
853 if (sc->sc_isoc_in_frlen != NULL) {
854 kfree(sc->sc_isoc_in_frlen, M_USBDEV);
855 sc->sc_isoc_in_frlen = NULL;
857 if (sc->sc_isoc_out_frlen != NULL) {
858 kfree(sc->sc_isoc_out_frlen, M_USBDEV);
859 sc->sc_isoc_out_frlen = NULL;
863 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
864 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
865 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
867 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
874 * Start USB control request (HCI command). Must be called with node locked
878 ubt_request_start(ubt_softc_p sc)
880 usb_device_request_t req;
881 struct mbuf *m = NULL;
884 KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
885 "%s: %s - Another control request is pending\n",
886 __func__, device_get_nameunit(sc->sc_dev)));
888 NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
891 "%s: %s - HCI command queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
893 return (USBD_NORMAL_COMPLETION);
897 * Check HCI command frame size and copy it back to
898 * linear USB transfer buffer.
901 if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
903 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
904 __func__, device_get_nameunit(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
907 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
909 /* Initialize a USB control request and then schedule it */
910 bzero(&req, sizeof(req));
911 req.bmRequestType = UBT_HCI_REQUEST;
912 USETW(req.wLength, m->m_pkthdr.len);
915 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
916 __func__, device_get_nameunit(sc->sc_dev), req.bmRequestType,
919 usbd_setup_default_xfer(
922 (usbd_private_handle) sc->sc_node,
923 USBD_DEFAULT_TIMEOUT, /* XXX */
928 ubt_request_complete);
930 NG_NODE_REF(sc->sc_node);
932 status = usbd_transfer(sc->sc_ctrl_xfer);
933 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
935 "%s: %s - Could not start control request. %s (%d)\n",
936 __func__, device_get_nameunit(sc->sc_dev),
937 usbd_errstr(status), status);
939 NG_NODE_UNREF(sc->sc_node);
941 NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
942 NG_UBT_STAT_OERROR(sc->sc_stat);
944 /* XXX FIXME should we try to resubmit another request? */
947 "%s: %s - Control request has been started\n",
948 __func__, device_get_nameunit(sc->sc_dev));
950 sc->sc_flags |= UBT_CMD_XMIT;
951 status = USBD_NORMAL_COMPLETION;
957 } /* ubt_request_start */
960 * USB control request callback
964 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
966 ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
967 NG_NODE_UNREF((node_p) p);
968 } /* ubt_request_complete */
971 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
973 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
974 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
975 usbd_status s = (usbd_status) arg2;
980 KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
981 "%s: %s - No control request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
983 sc->sc_flags &= ~UBT_CMD_XMIT;
985 if (s == USBD_CANCELLED) {
987 "%s: %s - Control request cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
992 if (s != USBD_NORMAL_COMPLETION) {
994 "%s: %s - Control request failed. %s (%d)\n",
995 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
997 if (s == USBD_STALLED)
998 usbd_clear_endpoint_stall_async(h->pipe);
1000 NG_UBT_STAT_OERROR(sc->sc_stat);
1003 "%s: %s - Sent %d bytes to control pipe\n",
1004 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1006 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1007 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1010 if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
1011 ubt_request_start(sc);
1012 } /* ubt_request_complete2 */
1015 * Start interrupt transfer. Must be called when node is locked
1019 ubt_intr_start(ubt_softc_p sc)
1021 struct mbuf *m = NULL;
1024 KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1025 "%s: %s - Another interrupt request is pending\n",
1026 __func__, device_get_nameunit(sc->sc_dev)));
1028 /* Allocate new mbuf cluster */
1029 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1031 return (USBD_NOMEM);
1033 MCLGET(m, MB_DONTWAIT);
1034 if (!(m->m_flags & M_EXT)) {
1036 return (USBD_NOMEM);
1039 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1040 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1041 m->m_pkthdr.len = m->m_len = 1;
1043 m->m_pkthdr.len = m->m_len = 0;
1045 /* Initialize a USB transfer and then schedule it */
1049 (usbd_private_handle) sc->sc_node,
1050 (void *)(mtod(m, u_int8_t *) + m->m_len),
1051 MCLBYTES - m->m_len,
1056 NG_NODE_REF(sc->sc_node);
1058 status = usbd_transfer(sc->sc_intr_xfer);
1059 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1061 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1062 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1065 NG_NODE_UNREF(sc->sc_node);
1072 sc->sc_flags |= UBT_EVT_RECV;
1073 sc->sc_intr_buffer = m;
1075 return (USBD_NORMAL_COMPLETION);
1076 } /* ubt_intr_start */
1079 * Process interrupt from USB device (We got data from interrupt pipe)
1083 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1085 ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1086 NG_NODE_UNREF((node_p) p);
1087 } /* ubt_intr_complete */
1090 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1092 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1093 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1094 usbd_status s = (usbd_status) arg2;
1095 struct mbuf *m = NULL;
1096 ng_hci_event_pkt_t *hdr = NULL;
1102 KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1103 "%s: %s - No interrupt request is pending\n",
1104 __func__, device_get_nameunit(sc->sc_dev)));
1106 sc->sc_flags &= ~UBT_EVT_RECV;
1108 m = sc->sc_intr_buffer;
1109 sc->sc_intr_buffer = NULL;
1111 hdr = mtod(m, ng_hci_event_pkt_t *);
1113 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1115 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1121 if (s == USBD_CANCELLED) {
1123 "%s: %s - Interrupt xfer cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
1129 if (s != USBD_NORMAL_COMPLETION) {
1131 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1132 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1134 if (s == USBD_STALLED)
1135 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1137 NG_UBT_STAT_IERROR(sc->sc_stat);
1140 return; /* XXX FIXME we should restart after some delay */
1143 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1144 m->m_pkthdr.len += h->actlen;
1145 m->m_len += h->actlen;
1148 "%s: %s - Got %d bytes from interrupt pipe\n",
1149 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1151 if (m->m_pkthdr.len < sizeof(*hdr)) {
1156 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1158 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1159 __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len,
1162 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1164 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1166 NG_UBT_STAT_IERROR(sc->sc_stat);
1169 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1170 __func__, device_get_nameunit(sc->sc_dev), hdr->length,
1173 NG_UBT_STAT_IERROR(sc->sc_stat);
1178 } /* ubt_intr_complete2 */
1181 * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1185 ubt_bulk_in_start(ubt_softc_p sc)
1187 struct mbuf *m = NULL;
1190 KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1191 "%s: %s - Another bulk-in request is pending\n",
1192 __func__, device_get_nameunit(sc->sc_dev)));
1194 /* Allocate new mbuf cluster */
1195 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1197 return (USBD_NOMEM);
1199 MCLGET(m, MB_DONTWAIT);
1200 if (!(m->m_flags & M_EXT)) {
1202 return (USBD_NOMEM);
1205 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1206 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1207 m->m_pkthdr.len = m->m_len = 1;
1209 m->m_pkthdr.len = m->m_len = 0;
1211 /* Initialize a bulk-in USB transfer and then schedule it */
1213 sc->sc_bulk_in_xfer,
1214 sc->sc_bulk_in_pipe,
1215 (usbd_private_handle) sc->sc_node,
1216 (void *)(mtod(m, u_int8_t *) + m->m_len),
1217 MCLBYTES - m->m_len,
1220 ubt_bulk_in_complete);
1222 NG_NODE_REF(sc->sc_node);
1224 status = usbd_transfer(sc->sc_bulk_in_xfer);
1225 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1227 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1228 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1231 NG_NODE_UNREF(sc->sc_node);
1238 sc->sc_flags |= UBT_ACL_RECV;
1239 sc->sc_bulk_in_buffer = m;
1241 return (USBD_NORMAL_COMPLETION);
1242 } /* ubt_bulk_in_start */
1245 * USB bulk-in transfer callback
1249 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1251 ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1252 NG_NODE_UNREF((node_p) p);
1253 } /* ubt_bulk_in_complete */
1256 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1258 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1259 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1260 usbd_status s = (usbd_status) arg2;
1261 struct mbuf *m = NULL;
1262 ng_hci_acldata_pkt_t *hdr = NULL;
1268 KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1269 "%s: %s - No bulk-in request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1271 sc->sc_flags &= ~UBT_ACL_RECV;
1273 m = sc->sc_bulk_in_buffer;
1274 sc->sc_bulk_in_buffer = NULL;
1276 hdr = mtod(m, ng_hci_acldata_pkt_t *);
1278 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1280 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1286 if (s == USBD_CANCELLED) {
1288 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1289 __func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_in_pipe);
1295 if (s != USBD_NORMAL_COMPLETION) {
1297 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1298 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1300 if (s == USBD_STALLED)
1301 usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1303 NG_UBT_STAT_IERROR(sc->sc_stat);
1306 return; /* XXX FIXME we should restart after some delay */
1309 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1310 m->m_pkthdr.len += h->actlen;
1311 m->m_len += h->actlen;
1314 "%s: %s - Got %d bytes from bulk-in pipe\n",
1315 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1317 if (m->m_pkthdr.len < sizeof(*hdr)) {
1322 len = le16toh(hdr->length);
1323 if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1325 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1326 __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len, len);
1328 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1330 NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1332 NG_UBT_STAT_IERROR(sc->sc_stat);
1335 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1336 __func__, device_get_nameunit(sc->sc_dev), len,
1339 NG_UBT_STAT_IERROR(sc->sc_stat);
1343 ubt_bulk_in_start(sc);
1344 } /* ubt_bulk_in_complete2 */
1347 * Start bulk-out USB transfer. Must be called with node locked
1351 ubt_bulk_out_start(ubt_softc_p sc)
1353 struct mbuf *m = NULL;
1356 KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1357 "%s: %s - Another bulk-out request is pending\n",
1358 __func__, device_get_nameunit(sc->sc_dev)));
1360 NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1363 "%s: %s - ACL data queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
1365 return (USBD_NORMAL_COMPLETION);
1369 * Check ACL data frame size and copy it back to linear USB
1373 if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1375 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1376 __func__, device_get_nameunit(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1379 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1381 /* Initialize a bulk-out USB transfer and then schedule it */
1383 sc->sc_bulk_out_xfer,
1384 sc->sc_bulk_out_pipe,
1385 (usbd_private_handle) sc->sc_node,
1386 sc->sc_bulk_out_buffer,
1389 USBD_DEFAULT_TIMEOUT, /* XXX */
1390 ubt_bulk_out_complete);
1392 NG_NODE_REF(sc->sc_node);
1394 status = usbd_transfer(sc->sc_bulk_out_xfer);
1395 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1397 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1398 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1401 NG_NODE_UNREF(sc->sc_node);
1403 NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1404 NG_UBT_STAT_OERROR(sc->sc_stat);
1406 /* XXX FIXME should we try to start another transfer? */
1409 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1410 __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len);
1412 sc->sc_flags |= UBT_ACL_XMIT;
1413 status = USBD_NORMAL_COMPLETION;
1419 } /* ubt_bulk_out_start */
1422 * USB bulk-out transfer callback
1426 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1428 ng_send_fn((node_p) p, NULL, ubt_bulk_out_complete2, (void *) h, s);
1429 NG_NODE_UNREF((node_p) p);
1430 } /* ubt_bulk_out_complete */
1433 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1435 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1436 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1437 usbd_status s = (usbd_status) arg2;
1442 KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1443 "%s: %s - No bulk-out request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1445 sc->sc_flags &= ~UBT_ACL_XMIT;
1447 if (s == USBD_CANCELLED) {
1449 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1450 __func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_out_pipe);
1455 if (s != USBD_NORMAL_COMPLETION) {
1457 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1458 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1460 if (s == USBD_STALLED)
1461 usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1463 NG_UBT_STAT_OERROR(sc->sc_stat);
1466 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1467 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1469 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1470 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1473 if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1474 ubt_bulk_out_start(sc);
1475 } /* ubt_bulk_out_complete2 */
1478 * Start Isochronous-in USB transfer. Must be called with node locked
1482 ubt_isoc_in_start(ubt_softc_p sc)
1487 KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1488 "%s: %s - Another isoc-in request is pending\n",
1489 __func__, device_get_nameunit(sc->sc_dev)));
1491 /* Initialize a isoc-in USB transfer and then schedule it */
1492 for (i = 0; i < sc->sc_isoc_nframes; i++)
1493 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1495 usbd_setup_isoc_xfer(
1496 sc->sc_isoc_in_xfer,
1497 sc->sc_isoc_in_pipe,
1498 (usbd_private_handle) sc->sc_node,
1499 sc->sc_isoc_in_frlen,
1500 sc->sc_isoc_nframes,
1501 USBD_NO_COPY, /* XXX flags */
1502 ubt_isoc_in_complete);
1504 NG_NODE_REF(sc->sc_node);
1506 status = usbd_transfer(sc->sc_isoc_in_xfer);
1507 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1509 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1510 __func__, device_get_nameunit(sc->sc_dev),
1511 usbd_errstr(status), status);
1513 NG_NODE_UNREF(sc->sc_node);
1518 sc->sc_flags |= UBT_SCO_RECV;
1520 return (USBD_NORMAL_COMPLETION);
1521 } /* ubt_isoc_in_start */
1524 * USB isochronous transfer callback
1528 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1530 ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1531 NG_NODE_UNREF((node_p) p);
1532 } /* ubt_isoc_in_complete */
1535 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1537 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1538 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1539 usbd_status s = (usbd_status) arg2;
1540 struct mbuf *m = NULL;
1541 ng_hci_scodata_pkt_t *hdr = NULL;
1548 KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1549 "%s: %s - No isoc-in request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1551 sc->sc_flags &= ~UBT_SCO_RECV;
1553 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1555 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1560 if (s == USBD_CANCELLED) {
1562 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1563 __func__, device_get_nameunit(sc->sc_dev), sc->sc_isoc_in_pipe);
1568 if (s != USBD_NORMAL_COMPLETION) {
1570 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1571 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1573 if (s == USBD_STALLED)
1574 usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1576 NG_UBT_STAT_IERROR(sc->sc_stat);
1578 return; /* XXX FIXME we should restart after some delay */
1581 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1584 "%s: %s - Got %d bytes from isoc-in pipe\n",
1585 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1587 /* Copy SCO data frame to mbuf */
1588 MGETHDR(m, MB_DONTWAIT, MT_DATA);
1591 "%s: %s - Could not allocate mbuf\n",
1592 __func__, device_get_nameunit(sc->sc_dev));
1594 NG_UBT_STAT_IERROR(sc->sc_stat);
1598 /* Fix SCO data frame header if required */
1599 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1600 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1601 m->m_pkthdr.len = 1;
1602 m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1604 m->m_pkthdr.len = 0;
1605 m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1609 * XXX FIXME how do we know how many frames we have received?
1610 * XXX use frlen for now. is that correct?
1613 b = (u_int8_t *) sc->sc_isoc_in_buffer;
1615 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1616 b += (i * sc->sc_isoc_size);
1618 if (sc->sc_isoc_in_frlen[i] > 0)
1619 m_copyback(m, m->m_pkthdr.len,
1620 sc->sc_isoc_in_frlen[i], b);
1623 if (m->m_pkthdr.len < sizeof(*hdr))
1626 hdr = mtod(m, ng_hci_scodata_pkt_t *);
1628 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1630 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1631 __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len,
1634 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1636 NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1638 NG_UBT_STAT_IERROR(sc->sc_stat);
1641 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1642 __func__, device_get_nameunit(sc->sc_dev), hdr->length,
1645 NG_UBT_STAT_IERROR(sc->sc_stat);
1649 ubt_isoc_in_start(sc);
1650 } /* ubt_isoc_in_complete2 */
1653 * Start isochronous-out USB transfer. Must be called with node locked
1657 ubt_isoc_out_start(ubt_softc_p sc)
1659 struct mbuf *m = NULL;
1661 int i, len, nframes;
1664 KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1665 "%s: %s - Another isoc-out request is pending\n",
1666 __func__, device_get_nameunit(sc->sc_dev)));
1668 NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1671 "%s: %s - SCO data queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
1673 return (USBD_NORMAL_COMPLETION);
1676 /* Copy entire SCO frame into USB transfer buffer and start transfer */
1677 b = (u_int8_t *) sc->sc_isoc_out_buffer;
1680 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1681 b += (i * sc->sc_isoc_size);
1683 len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1685 m_copydata(m, 0, len, b);
1690 sc->sc_isoc_out_frlen[i] = len;
1693 if (m->m_pkthdr.len > 0)
1695 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1696 __func__, device_get_nameunit(sc->sc_dev), sc->sc_isoc_nframes,
1697 sc->sc_isoc_size, m->m_pkthdr.len);
1701 /* Initialize a isoc-out USB transfer and then schedule it */
1702 usbd_setup_isoc_xfer(
1703 sc->sc_isoc_out_xfer,
1704 sc->sc_isoc_out_pipe,
1705 (usbd_private_handle) sc->sc_node,
1706 sc->sc_isoc_out_frlen,
1709 ubt_isoc_out_complete);
1711 NG_NODE_REF(sc->sc_node);
1713 status = usbd_transfer(sc->sc_isoc_out_xfer);
1714 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1716 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1717 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1720 NG_NODE_UNREF(sc->sc_node);
1722 NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1723 NG_UBT_STAT_OERROR(sc->sc_stat);
1726 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1727 __func__, device_get_nameunit(sc->sc_dev), nframes,
1730 sc->sc_flags |= UBT_SCO_XMIT;
1731 status = USBD_NORMAL_COMPLETION;
1735 } /* ubt_isoc_out_start */
1738 * USB isoc-out. transfer callback
1742 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1744 ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1745 NG_NODE_UNREF((node_p) p);
1746 } /* ubt_isoc_out_complete */
1749 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1751 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1752 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1753 usbd_status s = (usbd_status) arg2;
1758 KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1759 "%s: %s - No isoc-out request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1761 sc->sc_flags &= ~UBT_SCO_XMIT;
1763 if (s == USBD_CANCELLED) {
1765 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1766 __func__, device_get_nameunit(sc->sc_dev),
1767 sc->sc_isoc_out_pipe);
1772 if (s != USBD_NORMAL_COMPLETION) {
1774 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1775 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1777 if (s == USBD_STALLED)
1778 usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1780 NG_UBT_STAT_OERROR(sc->sc_stat);
1783 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1784 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1786 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1787 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1790 if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1791 ubt_isoc_out_start(sc);
1792 } /* ubt_isoc_out_complete2 */
1795 * Abort transfers on all USB pipes
1799 ubt_reset(ubt_softc_p sc)
1802 if (sc->sc_intr_pipe != NULL)
1803 usbd_abort_pipe(sc->sc_intr_pipe);
1806 if (sc->sc_bulk_in_pipe != NULL)
1807 usbd_abort_pipe(sc->sc_bulk_in_pipe);
1808 if (sc->sc_bulk_out_pipe != NULL)
1809 usbd_abort_pipe(sc->sc_bulk_out_pipe);
1812 if (sc->sc_isoc_in_pipe != NULL)
1813 usbd_abort_pipe(sc->sc_isoc_in_pipe);
1814 if (sc->sc_isoc_out_pipe != NULL)
1815 usbd_abort_pipe(sc->sc_isoc_out_pipe);
1817 /* Cleanup queues */
1818 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1819 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1820 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1823 /****************************************************************************
1824 ****************************************************************************
1825 ** Netgraph specific
1826 ****************************************************************************
1827 ****************************************************************************/
1830 * Netgraph node constructor. Do not allow to create node of this type.
1834 ng_ubt_constructor(node_p node)
1837 } /* ng_ubt_constructor */
1840 * Netgraph node destructor. Destroy node only when device has been detached
1844 ng_ubt_shutdown(node_p node)
1846 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1848 /* Let old node go */
1849 NG_NODE_SET_PRIVATE(node, NULL);
1850 NG_NODE_UNREF(node);
1855 /* Create Netgraph node */
1856 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1857 printf("%s: Could not create Netgraph node\n",
1858 device_get_nameunit(sc->sc_dev));
1864 if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
1865 printf("%s: Could not name Netgraph node\n",
1866 device_get_nameunit(sc->sc_dev));
1867 NG_NODE_UNREF(sc->sc_node);
1872 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1873 NG_NODE_FORCE_WRITER(sc->sc_node);
1876 } /* ng_ubt_shutdown */
1879 * Create new hook. There can only be one.
1883 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1885 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1887 if (strcmp(name, NG_UBT_HOOK) != 0)
1890 if (sc->sc_hook != NULL)
1896 } /* ng_ubt_newhook */
1899 * Connect hook. Start incoming USB transfers
1903 ng_ubt_connect(hook_p hook)
1905 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1908 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1910 /* Start intr transfer */
1911 status = ubt_intr_start(sc);
1912 if (status != USBD_NORMAL_COMPLETION) {
1914 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1915 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1920 /* Start bulk-in transfer */
1921 status = ubt_bulk_in_start(sc);
1922 if (status != USBD_NORMAL_COMPLETION) {
1924 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1925 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1930 #if 0 /* XXX FIXME */
1931 /* Start isoc-in transfer */
1932 status = ubt_isoc_in_start(sc);
1933 if (status != USBD_NORMAL_COMPLETION) {
1935 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1936 __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1948 } /* ng_ubt_connect */
1955 ng_ubt_disconnect(hook_p hook)
1957 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1960 if (hook != sc->sc_hook)
1968 } /* ng_ubt_disconnect */
1971 * Process control message
1975 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
1977 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1978 struct ng_mesg *msg = NULL, *rsp = NULL;
1979 struct ng_bt_mbufq *q = NULL;
1980 int error = 0, queue, qlen;
1987 NGI_GET_MSG(item, msg);
1989 switch (msg->header.typecookie) {
1990 case NGM_GENERIC_COOKIE:
1991 switch (msg->header.cmd) {
1992 case NGM_TEXT_STATUS:
1993 NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_WAITOK | M_NULLOK);
1997 snprintf(rsp->data, NG_TEXTRESPONSE,
2001 "CMD queue: [have:%d,max:%d]\n" \
2002 "ACL queue: [have:%d,max:%d]\n" \
2003 "SCO queue: [have:%d,max:%d]",
2004 (sc->sc_hook != NULL)? NG_UBT_HOOK : "",
2007 NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
2009 NG_BT_MBUFQ_LEN(&sc->sc_aclq),
2011 NG_BT_MBUFQ_LEN(&sc->sc_scoq),
2012 sc->sc_scoq.maxlen);
2021 case NGM_UBT_COOKIE:
2022 switch (msg->header.cmd) {
2023 case NGM_UBT_NODE_SET_DEBUG:
2024 if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2028 *((ng_ubt_node_debug_ep *)(msg->data));
2031 case NGM_UBT_NODE_GET_DEBUG:
2032 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2033 M_WAITOK | M_NULLOK);
2037 *((ng_ubt_node_debug_ep *)(rsp->data)) =
2041 case NGM_UBT_NODE_SET_QLEN:
2042 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2045 queue = ((ng_ubt_node_qlen_ep *)
2046 (msg->data))->queue;
2047 qlen = ((ng_ubt_node_qlen_ep *)
2056 case NGM_UBT_NODE_QUEUE_CMD:
2060 case NGM_UBT_NODE_QUEUE_ACL:
2064 case NGM_UBT_NODE_QUEUE_SCO:
2079 case NGM_UBT_NODE_GET_QLEN:
2080 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2085 queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2087 case NGM_UBT_NODE_QUEUE_CMD:
2091 case NGM_UBT_NODE_QUEUE_ACL:
2095 case NGM_UBT_NODE_QUEUE_SCO:
2106 NG_MKRESPONSE(rsp, msg,
2107 sizeof(ng_ubt_node_qlen_ep), M_WAITOK | M_NULLOK);
2113 ((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2115 ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2120 case NGM_UBT_NODE_GET_STAT:
2121 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2122 M_WAITOK | M_NULLOK);
2126 bcopy(&sc->sc_stat, rsp->data,
2127 sizeof(ng_ubt_node_stat_ep));
2130 case NGM_UBT_NODE_RESET_STAT:
2131 NG_UBT_STAT_RESET(sc->sc_stat);
2145 NG_RESPOND_MSG(error, node, item, rsp);
2149 } /* ng_ubt_rcvmsg */
2156 ng_ubt_rcvdata(hook_p hook, item_p item)
2158 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2159 struct mbuf *m = NULL;
2160 usbd_status (*f)(ubt_softc_p) = NULL;
2161 struct ng_bt_mbufq *q = NULL;
2169 if (hook != sc->sc_hook) {
2174 /* Deatch mbuf and get HCI frame type */
2177 /* Process HCI frame */
2178 switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2179 case NG_HCI_CMD_PKT:
2180 f = ubt_request_start;
2185 case NG_HCI_ACL_DATA_PKT:
2186 f = ubt_bulk_out_start;
2191 #if 0 /* XXX FIXME */
2192 case NG_HCI_SCO_DATA_PKT:
2193 f = ubt_isoc_out_start;
2201 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2202 __func__, device_get_nameunit(sc->sc_dev), *mtod(m, u_int8_t *),
2212 /* Loose frame type, if required */
2213 if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2214 m_adj(m, sizeof(u_int8_t));
2216 if (NG_BT_MBUFQ_FULL(q)) {
2218 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2219 __func__, device_get_nameunit(sc->sc_dev),
2220 *mtod(m, u_int8_t *), m->m_pkthdr.len);
2224 NG_BT_MBUFQ_ENQUEUE(q, m);
2226 if (!(sc->sc_flags & b))
2227 if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2233 } /* ng_ubt_rcvdata */