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 $
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 <netgraph/ng_message.h>
55 #include <netgraph/netgraph.h>
56 #include <netgraph/ng_parse.h>
57 #include <netgraph/bluetooth/include/ng_bluetooth.h>
58 #include <netgraph/bluetooth/include/ng_hci.h>
59 #include <netgraph/bluetooth/include/ng_ubt.h>
60 #include <netgraph/bluetooth/drivers/ubt/ng_ubt_var.h>
68 USB_DECLARE_DRIVER(ubt);
70 Static int ubt_modevent (module_t, int, void *);
72 Static usbd_status ubt_request_start (ubt_softc_p);
73 Static void ubt_request_complete (usbd_xfer_handle,
74 usbd_private_handle, usbd_status);
75 Static void ubt_request_complete2 (node_p, hook_p, void *, int);
77 Static usbd_status ubt_intr_start (ubt_softc_p);
78 Static void ubt_intr_complete (usbd_xfer_handle,
79 usbd_private_handle, usbd_status);
80 Static void ubt_intr_complete2 (node_p, hook_p, void *, int);
82 Static usbd_status ubt_bulk_in_start (ubt_softc_p);
83 Static void ubt_bulk_in_complete (usbd_xfer_handle,
84 usbd_private_handle, usbd_status);
85 Static void ubt_bulk_in_complete2 (node_p, hook_p, void *, int);
87 Static usbd_status ubt_bulk_out_start (ubt_softc_p);
88 Static void ubt_bulk_out_complete (usbd_xfer_handle,
89 usbd_private_handle, usbd_status);
90 Static void ubt_bulk_out_complete2 (node_p, hook_p, void *, int);
92 Static usbd_status ubt_isoc_in_start (ubt_softc_p);
93 Static void ubt_isoc_in_complete (usbd_xfer_handle,
94 usbd_private_handle, usbd_status);
95 Static void ubt_isoc_in_complete2 (node_p, hook_p, void *, int);
97 Static usbd_status ubt_isoc_out_start (ubt_softc_p);
98 Static void ubt_isoc_out_complete (usbd_xfer_handle,
99 usbd_private_handle, usbd_status);
100 Static void ubt_isoc_out_complete2 (node_p, hook_p, void *, int);
102 Static void ubt_reset (ubt_softc_p);
108 Static ng_constructor_t ng_ubt_constructor;
109 Static ng_shutdown_t ng_ubt_shutdown;
110 Static ng_newhook_t ng_ubt_newhook;
111 Static ng_connect_t ng_ubt_connect;
112 Static ng_disconnect_t ng_ubt_disconnect;
113 Static ng_rcvmsg_t ng_ubt_rcvmsg;
114 Static ng_rcvdata_t ng_ubt_rcvdata;
117 Static const struct ng_parse_struct_field ng_ubt_node_qlen_type_fields[] =
119 { "queue", &ng_parse_int32_type, },
120 { "qlen", &ng_parse_int32_type, },
123 Static const struct ng_parse_type ng_ubt_node_qlen_type = {
124 &ng_parse_struct_type,
125 &ng_ubt_node_qlen_type_fields
129 Static const struct ng_parse_struct_field ng_ubt_node_stat_type_fields[] =
131 { "pckts_recv", &ng_parse_uint32_type, },
132 { "bytes_recv", &ng_parse_uint32_type, },
133 { "pckts_sent", &ng_parse_uint32_type, },
134 { "bytes_sent", &ng_parse_uint32_type, },
135 { "oerrors", &ng_parse_uint32_type, },
136 { "ierrors", &ng_parse_uint32_type, },
139 Static const struct ng_parse_type ng_ubt_node_stat_type = {
140 &ng_parse_struct_type,
141 &ng_ubt_node_stat_type_fields
144 /* Netgraph node command list */
145 Static const struct ng_cmdlist ng_ubt_cmdlist[] = {
148 NGM_UBT_NODE_SET_DEBUG,
150 &ng_parse_uint16_type,
155 NGM_UBT_NODE_GET_DEBUG,
158 &ng_parse_uint16_type
162 NGM_UBT_NODE_SET_QLEN,
164 &ng_ubt_node_qlen_type,
169 NGM_UBT_NODE_GET_QLEN,
171 &ng_ubt_node_qlen_type,
172 &ng_ubt_node_qlen_type
176 NGM_UBT_NODE_GET_STAT,
179 &ng_ubt_node_stat_type
183 NGM_UBT_NODE_RESET_STAT,
191 /* Netgraph node type */
192 Static struct ng_type typestruct = {
193 .version = NG_ABI_VERSION,
194 .name = NG_UBT_NODE_TYPE,
195 .constructor = ng_ubt_constructor,
196 .rcvmsg = ng_ubt_rcvmsg,
197 .shutdown = ng_ubt_shutdown,
198 .newhook = ng_ubt_newhook,
199 .connect = ng_ubt_connect,
200 .rcvdata = ng_ubt_rcvdata,
201 .disconnect = ng_ubt_disconnect,
202 .cmdlist = ng_ubt_cmdlist
209 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
210 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
211 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
213 /****************************************************************************
214 ****************************************************************************
216 ****************************************************************************
217 ****************************************************************************/
220 * Load/Unload the driver module
224 ubt_modevent(module_t mod, int event, void *data)
230 error = ng_newtype(&typestruct);
233 "%s: Could not register Netgraph node type, error=%d\n",
234 NG_UBT_NODE_TYPE, error);
236 error = usbd_driver_load(mod, event, data);
240 error = ng_rmtype(&typestruct);
242 error = usbd_driver_load(mod, event, data);
254 * Probe for a USB Bluetooth device
260 * If for some reason device should not be attached then put
261 * VendorID/ProductID pair into the list below. Currently I
262 * do not know of any such devices. The format is as follows:
264 * { VENDOR_ID, PRODUCT_ID },
266 * where VENDOR_ID and PRODUCT_ID are hex numbers.
269 Static struct usb_devno const ubt_ignored_devices[] = {
270 { 0, 0 } /* This should be the last item in the list */
274 * If device violates Bluetooth specification and has bDeviceClass,
275 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
276 * could try to put VendorID/ProductID pair into the list below.
277 * Currently I do not know of any such devices.
280 Static struct usb_devno const ubt_broken_devices[] = {
281 { 0, 0 } /* This should be the last item in the list */
284 USB_MATCH_START(ubt, uaa);
286 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
288 if (uaa->iface == NULL ||
289 usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
290 return (UMATCH_NONE);
292 if (dd->bDeviceClass == UDCLASS_WIRELESS &&
293 dd->bDeviceSubClass == UDSUBCLASS_RF &&
294 dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
295 return (UMATCH_DEVCLASS_DEVSUBCLASS);
297 if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
298 return (UMATCH_VENDOR_PRODUCT);
300 return (UMATCH_NONE);
301 } /* USB_MATCH(ubt) */
309 USB_ATTACH_START(ubt, sc, uaa);
310 usb_config_descriptor_t *cd = NULL;
311 usb_interface_descriptor_t *id = NULL;
312 usb_endpoint_descriptor_t *ed = NULL;
315 int i, ai, alt_no, isoc_in, isoc_out,
316 isoc_isize, isoc_osize;
318 /* Get USB device info */
319 sc->sc_udev = uaa->device;
320 usbd_devinfo(sc->sc_udev, 0, devinfo);
322 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
325 * Initialize device softc structure
329 sc->sc_debug = NG_UBT_WARN_LEVEL;
331 NG_UBT_STAT_RESET(sc->sc_stat);
334 sc->sc_iface0 = sc->sc_iface1 = NULL;
338 sc->sc_intr_pipe = NULL;
339 sc->sc_intr_xfer = NULL;
340 sc->sc_intr_buffer = NULL;
343 sc->sc_ctrl_xfer = NULL;
344 sc->sc_ctrl_buffer = NULL;
345 NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
348 sc->sc_bulk_in_ep = -1;
349 sc->sc_bulk_in_pipe = NULL;
350 sc->sc_bulk_in_xfer = NULL;
351 sc->sc_bulk_in_buffer = NULL;
354 sc->sc_bulk_out_ep = -1;
355 sc->sc_bulk_out_pipe = NULL;
356 sc->sc_bulk_out_xfer = NULL;
357 sc->sc_bulk_out_buffer = NULL;
358 NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
361 sc->sc_isoc_in_ep = -1;
362 sc->sc_isoc_in_pipe = NULL;
363 sc->sc_isoc_in_xfer = NULL;
366 sc->sc_isoc_out_ep = -1;
367 sc->sc_isoc_out_pipe = NULL;
368 sc->sc_isoc_out_xfer = NULL;
369 sc->sc_isoc_size = -1;
370 NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
377 * XXX set configuration?
379 * Configure Bluetooth USB device. Discover all required USB interfaces
382 * USB device must present two interfaces:
383 * 1) Interface 0 that has 3 endpoints
384 * 1) Interrupt endpoint to receive HCI events
385 * 2) Bulk IN endpoint to receive ACL data
386 * 3) Bulk OUT endpoint to send ACL data
388 * 2) Interface 1 then has 2 endpoints
389 * 1) Isochronous IN endpoint to receive SCO data
390 * 2) Isochronous OUT endpoint to send SCO data
392 * Interface 1 (with isochronous endpoints) has several alternate
393 * configurations with different packet size.
400 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
401 if (error || sc->sc_iface0 == NULL) {
402 printf("%s: Could not get interface 0 handle. %s (%d), " \
403 "handle=%p\n", USBDEVNAME(sc->sc_dev),
404 usbd_errstr(error), error, sc->sc_iface0);
408 id = usbd_get_interface_descriptor(sc->sc_iface0);
410 printf("%s: Could not get interface 0 descriptor\n",
411 USBDEVNAME(sc->sc_dev));
415 for (i = 0; i < id->bNumEndpoints; i ++) {
416 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
418 printf("%s: Could not read endpoint descriptor for " \
419 "interface 0, i=%d\n", USBDEVNAME(sc->sc_dev),
424 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
426 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
427 sc->sc_bulk_in_ep = ed->bEndpointAddress;
429 sc->sc_bulk_out_ep = ed->bEndpointAddress;
433 sc->sc_intr_ep = ed->bEndpointAddress;
438 /* Check if we got everything we wanted on Interface 0 */
439 if (sc->sc_intr_ep == -1) {
440 printf("%s: Could not detect interrupt endpoint\n",
441 USBDEVNAME(sc->sc_dev));
444 if (sc->sc_bulk_in_ep == -1) {
445 printf("%s: Could not detect bulk-in endpoint\n",
446 USBDEVNAME(sc->sc_dev));
449 if (sc->sc_bulk_out_ep == -1) {
450 printf("%s: Could not detect bulk-out endpoint\n",
451 USBDEVNAME(sc->sc_dev));
455 printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
456 "bulk-out=%#x\n", USBDEVNAME(sc->sc_dev),
457 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
463 cd = usbd_get_config_descriptor(sc->sc_udev);
465 printf("%s: Could not get device configuration descriptor\n",
466 USBDEVNAME(sc->sc_dev));
470 error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
471 if (error || sc->sc_iface1 == NULL) {
472 printf("%s: Could not get interface 1 handle. %s (%d), " \
473 "handle=%p\n", USBDEVNAME(sc->sc_dev),
474 usbd_errstr(error), error, sc->sc_iface1);
478 id = usbd_get_interface_descriptor(sc->sc_iface1);
480 printf("%s: Could not get interface 1 descriptor\n",
481 USBDEVNAME(sc->sc_dev));
486 * Scan all alternate configurations for interface 1
491 for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++) {
492 error = usbd_set_interface(sc->sc_iface1, ai);
494 printf("%s: [SCAN] Could not set alternate " \
495 "configuration %d for interface 1. %s (%d)\n",
496 USBDEVNAME(sc->sc_dev), ai, usbd_errstr(error),
500 id = usbd_get_interface_descriptor(sc->sc_iface1);
502 printf("%s: Could not get interface 1 descriptor for " \
503 "alternate configuration %d\n",
504 USBDEVNAME(sc->sc_dev), ai);
508 isoc_in = isoc_out = -1;
509 isoc_isize = isoc_osize = 0;
511 for (i = 0; i < id->bNumEndpoints; i ++) {
512 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
514 printf("%s: Could not read endpoint " \
515 "descriptor for interface 1, " \
516 "alternate configuration %d, i=%d\n",
517 USBDEVNAME(sc->sc_dev), ai, i);
521 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
524 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
525 isoc_in = ed->bEndpointAddress;
526 isoc_isize = UGETW(ed->wMaxPacketSize);
528 isoc_out = ed->bEndpointAddress;
529 isoc_osize = UGETW(ed->wMaxPacketSize);
534 * Make sure that configuration looks sane and if so
535 * update current settings
538 if (isoc_in != -1 && isoc_out != -1 &&
539 isoc_isize > 0 && isoc_osize > 0 &&
540 isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
541 sc->sc_isoc_in_ep = isoc_in;
542 sc->sc_isoc_out_ep = isoc_out;
543 sc->sc_isoc_size = isoc_isize;
548 /* Check if we got everything we wanted on Interface 0 */
549 if (sc->sc_isoc_in_ep == -1) {
550 printf("%s: Could not detect isoc-in endpoint\n",
551 USBDEVNAME(sc->sc_dev));
554 if (sc->sc_isoc_out_ep == -1) {
555 printf("%s: Could not detect isoc-out endpoint\n",
556 USBDEVNAME(sc->sc_dev));
559 if (sc->sc_isoc_size <= 0) {
560 printf("%s: Invalid isoc. packet size=%d\n",
561 USBDEVNAME(sc->sc_dev), sc->sc_isoc_size);
565 error = usbd_set_interface(sc->sc_iface1, alt_no);
567 printf("%s: Could not set alternate configuration " \
568 "%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev),
569 alt_no, usbd_errstr(error), error);
573 /* Allocate USB transfer handles and buffers */
574 sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
575 if (sc->sc_ctrl_xfer == NULL) {
576 printf("%s: Could not allocate control xfer handle\n",
577 USBDEVNAME(sc->sc_dev));
580 sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
581 UBT_CTRL_BUFFER_SIZE);
582 if (sc->sc_ctrl_buffer == NULL) {
583 printf("%s: Could not allocate control buffer\n",
584 USBDEVNAME(sc->sc_dev));
588 sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
589 if (sc->sc_intr_xfer == NULL) {
590 printf("%s: Could not allocate interrupt xfer handle\n",
591 USBDEVNAME(sc->sc_dev));
595 sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
596 if (sc->sc_bulk_in_xfer == NULL) {
597 printf("%s: Could not allocate bulk-in xfer handle\n",
598 USBDEVNAME(sc->sc_dev));
602 sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
603 if (sc->sc_bulk_out_xfer == NULL) {
604 printf("%s: Could not allocate bulk-out xfer handle\n",
605 USBDEVNAME(sc->sc_dev));
608 sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
609 UBT_BULK_BUFFER_SIZE);
610 if (sc->sc_bulk_out_buffer == NULL) {
611 printf("%s: Could not allocate bulk-out buffer\n",
612 USBDEVNAME(sc->sc_dev));
617 * Allocate buffers for isoc. transfers
620 sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
622 sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
623 if (sc->sc_isoc_in_xfer == NULL) {
624 printf("%s: Could not allocate isoc-in xfer handle\n",
625 USBDEVNAME(sc->sc_dev));
628 sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
629 sc->sc_isoc_nframes * sc->sc_isoc_size);
630 if (sc->sc_isoc_in_buffer == NULL) {
631 printf("%s: Could not allocate isoc-in buffer\n",
632 USBDEVNAME(sc->sc_dev));
635 sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
637 if (sc->sc_isoc_in_frlen == NULL) {
638 printf("%s: Could not allocate isoc-in frame sizes buffer\n",
639 USBDEVNAME(sc->sc_dev));
643 sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
644 if (sc->sc_isoc_out_xfer == NULL) {
645 printf("%s: Could not allocate isoc-out xfer handle\n",
646 USBDEVNAME(sc->sc_dev));
649 sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
650 sc->sc_isoc_nframes * sc->sc_isoc_size);
651 if (sc->sc_isoc_out_buffer == NULL) {
652 printf("%s: Could not allocate isoc-out buffer\n",
653 USBDEVNAME(sc->sc_dev));
656 sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
658 if (sc->sc_isoc_out_frlen == NULL) {
659 printf("%s: Could not allocate isoc-out frame sizes buffer\n",
660 USBDEVNAME(sc->sc_dev));
664 printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
665 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
666 USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
667 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
668 (sc->sc_isoc_nframes * sc->sc_isoc_size));
675 error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
676 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
677 if (error != USBD_NORMAL_COMPLETION) {
678 printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
679 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
685 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
686 USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
687 if (error != USBD_NORMAL_COMPLETION) {
688 printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
689 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
695 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
696 USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
697 if (error != USBD_NORMAL_COMPLETION) {
698 printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
699 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
704 #if __broken__ /* XXX FIXME */
706 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
707 USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
708 if (error != USBD_NORMAL_COMPLETION) {
709 printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
710 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
716 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
717 USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
718 if (error != USBD_NORMAL_COMPLETION) {
719 printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
720 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
724 #endif /* __broken__ */
726 /* Create Netgraph node */
727 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
728 printf("%s: Could not create Netgraph node\n",
729 USBDEVNAME(sc->sc_dev));
735 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
736 printf("%s: Could not name Netgraph node\n",
737 USBDEVNAME(sc->sc_dev));
738 NG_NODE_UNREF(sc->sc_node);
743 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
744 NG_NODE_FORCE_WRITER(sc->sc_node);
746 /* Claim all interfaces on the device */
747 for (i = 0; i < uaa->nifaces; i++)
748 uaa->ifaces[i] = NULL;
750 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
753 USB_ATTACH_SUCCESS_RETURN;
757 USB_ATTACH_ERROR_RETURN;
758 } /* USB_ATTACH(ubt) */
766 USB_DETACH_START(ubt, sc);
768 /* Destroy Netgraph node */
769 if (sc->sc_node != NULL) {
770 NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
771 ng_rmnode_self(sc->sc_node);
776 if (sc->sc_intr_pipe != NULL) {
777 usbd_close_pipe(sc->sc_intr_pipe);
778 sc->sc_intr_pipe = NULL;
781 if (sc->sc_bulk_in_pipe != NULL) {
782 usbd_close_pipe(sc->sc_bulk_in_pipe);
783 sc->sc_bulk_in_pipe = NULL;
785 if (sc->sc_bulk_out_pipe != NULL) {
786 usbd_close_pipe(sc->sc_bulk_out_pipe);
787 sc->sc_bulk_out_pipe = NULL;
790 if (sc->sc_isoc_in_pipe != NULL) {
791 usbd_close_pipe(sc->sc_isoc_in_pipe);
792 sc->sc_isoc_in_pipe = NULL;
794 if (sc->sc_isoc_out_pipe != NULL) {
795 usbd_close_pipe(sc->sc_isoc_out_pipe);
796 sc->sc_isoc_out_pipe = NULL;
799 /* Destroy USB transfer handles */
800 if (sc->sc_ctrl_xfer != NULL) {
801 usbd_free_xfer(sc->sc_ctrl_xfer);
802 sc->sc_ctrl_xfer = NULL;
805 if (sc->sc_intr_xfer != NULL) {
806 usbd_free_xfer(sc->sc_intr_xfer);
807 sc->sc_intr_xfer = NULL;
810 if (sc->sc_bulk_in_xfer != NULL) {
811 usbd_free_xfer(sc->sc_bulk_in_xfer);
812 sc->sc_bulk_in_xfer = NULL;
814 if (sc->sc_bulk_out_xfer != NULL) {
815 usbd_free_xfer(sc->sc_bulk_out_xfer);
816 sc->sc_bulk_out_xfer = NULL;
819 if (sc->sc_isoc_in_xfer != NULL) {
820 usbd_free_xfer(sc->sc_isoc_in_xfer);
821 sc->sc_isoc_in_xfer = NULL;
823 if (sc->sc_isoc_out_xfer != NULL) {
824 usbd_free_xfer(sc->sc_isoc_out_xfer);
825 sc->sc_isoc_out_xfer = NULL;
828 /* Destroy isoc. frame size buffers */
829 if (sc->sc_isoc_in_frlen != NULL) {
830 free(sc->sc_isoc_in_frlen, M_USBDEV);
831 sc->sc_isoc_in_frlen = NULL;
833 if (sc->sc_isoc_out_frlen != NULL) {
834 free(sc->sc_isoc_out_frlen, M_USBDEV);
835 sc->sc_isoc_out_frlen = NULL;
839 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
840 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
841 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
843 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
847 } /* USB_DETACH(ubt) */
850 * Start USB control request (HCI command). Must be called with node locked
854 ubt_request_start(ubt_softc_p sc)
856 usb_device_request_t req;
857 struct mbuf *m = NULL;
860 KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
861 "%s: %s - Another control request is pending\n",
862 __func__, USBDEVNAME(sc->sc_dev)));
864 NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
867 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
869 return (USBD_NORMAL_COMPLETION);
873 * Check HCI command frame size and copy it back to
874 * linear USB transfer buffer.
877 if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
879 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
880 __func__, USBDEVNAME(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
883 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
885 /* Initialize a USB control request and then schedule it */
886 bzero(&req, sizeof(req));
887 req.bmRequestType = UBT_HCI_REQUEST;
888 USETW(req.wLength, m->m_pkthdr.len);
891 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
892 __func__, USBDEVNAME(sc->sc_dev), req.bmRequestType,
895 usbd_setup_default_xfer(
898 (usbd_private_handle) sc->sc_node,
899 USBD_DEFAULT_TIMEOUT, /* XXX */
904 ubt_request_complete);
906 NG_NODE_REF(sc->sc_node);
908 status = usbd_transfer(sc->sc_ctrl_xfer);
909 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
911 "%s: %s - Could not start control request. %s (%d)\n",
912 __func__, USBDEVNAME(sc->sc_dev),
913 usbd_errstr(status), status);
915 NG_NODE_UNREF(sc->sc_node);
917 NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
918 NG_UBT_STAT_OERROR(sc->sc_stat);
920 /* XXX FIXME should we try to resubmit another request? */
923 "%s: %s - Control request has been started\n",
924 __func__, USBDEVNAME(sc->sc_dev));
926 sc->sc_flags |= UBT_CMD_XMIT;
927 status = USBD_NORMAL_COMPLETION;
933 } /* ubt_request_start */
936 * USB control request callback
940 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
942 ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
943 NG_NODE_UNREF((node_p) p);
944 } /* ubt_request_complete */
947 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
949 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
950 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
951 usbd_status s = (usbd_status) arg2;
956 KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
957 "%s: %s - No control request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
959 sc->sc_flags &= ~UBT_CMD_XMIT;
961 if (s == USBD_CANCELLED) {
963 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
968 if (s != USBD_NORMAL_COMPLETION) {
970 "%s: %s - Control request failed. %s (%d)\n",
971 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
973 if (s == USBD_STALLED)
974 usbd_clear_endpoint_stall_async(h->pipe);
976 NG_UBT_STAT_OERROR(sc->sc_stat);
979 "%s: %s - Sent %d bytes to control pipe\n",
980 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
982 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
983 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
986 if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
987 ubt_request_start(sc);
988 } /* ubt_request_complete2 */
991 * Start interrupt transfer. Must be called when node is locked
995 ubt_intr_start(ubt_softc_p sc)
997 struct mbuf *m = NULL;
1000 KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1001 "%s: %s - Another interrupt request is pending\n",
1002 __func__, USBDEVNAME(sc->sc_dev)));
1004 /* Allocate new mbuf cluster */
1005 MGETHDR(m, M_DONTWAIT, MT_DATA);
1007 return (USBD_NOMEM);
1009 MCLGET(m, M_DONTWAIT);
1010 if (!(m->m_flags & M_EXT)) {
1012 return (USBD_NOMEM);
1015 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1016 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1017 m->m_pkthdr.len = m->m_len = 1;
1019 m->m_pkthdr.len = m->m_len = 0;
1021 /* Initialize a USB transfer and then schedule it */
1025 (usbd_private_handle) sc->sc_node,
1026 (void *)(mtod(m, u_int8_t *) + m->m_len),
1027 MCLBYTES - m->m_len,
1032 NG_NODE_REF(sc->sc_node);
1034 status = usbd_transfer(sc->sc_intr_xfer);
1035 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1037 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1038 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1041 NG_NODE_UNREF(sc->sc_node);
1048 sc->sc_flags |= UBT_EVT_RECV;
1049 sc->sc_intr_buffer = m;
1051 return (USBD_NORMAL_COMPLETION);
1052 } /* ubt_intr_start */
1055 * Process interrupt from USB device (We got data from interrupt pipe)
1059 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1061 ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1062 NG_NODE_UNREF((node_p) p);
1063 } /* ubt_intr_complete */
1066 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1068 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1069 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1070 usbd_status s = (usbd_status) arg2;
1071 struct mbuf *m = NULL;
1072 ng_hci_event_pkt_t *hdr = NULL;
1078 KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1079 "%s: %s - No interrupt request is pending\n",
1080 __func__, USBDEVNAME(sc->sc_dev)));
1082 sc->sc_flags &= ~UBT_EVT_RECV;
1084 m = sc->sc_intr_buffer;
1085 sc->sc_intr_buffer = NULL;
1087 hdr = mtod(m, ng_hci_event_pkt_t *);
1089 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1091 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1097 if (s == USBD_CANCELLED) {
1099 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1105 if (s != USBD_NORMAL_COMPLETION) {
1107 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1108 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1110 if (s == USBD_STALLED)
1111 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1113 NG_UBT_STAT_IERROR(sc->sc_stat);
1116 return; /* XXX FIXME we should restart after some delay */
1119 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1120 m->m_pkthdr.len += h->actlen;
1121 m->m_len += h->actlen;
1124 "%s: %s - Got %d bytes from interrupt pipe\n",
1125 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1127 if (m->m_pkthdr.len < sizeof(*hdr)) {
1132 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1134 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1135 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1138 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1140 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1142 NG_UBT_STAT_IERROR(sc->sc_stat);
1145 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1146 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1149 NG_UBT_STAT_IERROR(sc->sc_stat);
1154 } /* ubt_intr_complete2 */
1157 * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1161 ubt_bulk_in_start(ubt_softc_p sc)
1163 struct mbuf *m = NULL;
1166 KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1167 "%s: %s - Another bulk-in request is pending\n",
1168 __func__, USBDEVNAME(sc->sc_dev)));
1170 /* Allocate new mbuf cluster */
1171 MGETHDR(m, M_DONTWAIT, MT_DATA);
1173 return (USBD_NOMEM);
1175 MCLGET(m, M_DONTWAIT);
1176 if (!(m->m_flags & M_EXT)) {
1178 return (USBD_NOMEM);
1181 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1182 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1183 m->m_pkthdr.len = m->m_len = 1;
1185 m->m_pkthdr.len = m->m_len = 0;
1187 /* Initialize a bulk-in USB transfer and then schedule it */
1189 sc->sc_bulk_in_xfer,
1190 sc->sc_bulk_in_pipe,
1191 (usbd_private_handle) sc->sc_node,
1192 (void *)(mtod(m, u_int8_t *) + m->m_len),
1193 MCLBYTES - m->m_len,
1196 ubt_bulk_in_complete);
1198 NG_NODE_REF(sc->sc_node);
1200 status = usbd_transfer(sc->sc_bulk_in_xfer);
1201 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1203 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1204 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1207 NG_NODE_UNREF(sc->sc_node);
1214 sc->sc_flags |= UBT_ACL_RECV;
1215 sc->sc_bulk_in_buffer = m;
1217 return (USBD_NORMAL_COMPLETION);
1218 } /* ubt_bulk_in_start */
1221 * USB bulk-in transfer callback
1225 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1227 ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1228 NG_NODE_UNREF((node_p) p);
1229 } /* ubt_bulk_in_complete */
1232 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1234 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1235 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1236 usbd_status s = (usbd_status) arg2;
1237 struct mbuf *m = NULL;
1238 ng_hci_acldata_pkt_t *hdr = NULL;
1244 KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1245 "%s: %s - No bulk-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1247 sc->sc_flags &= ~UBT_ACL_RECV;
1249 m = sc->sc_bulk_in_buffer;
1250 sc->sc_bulk_in_buffer = NULL;
1252 hdr = mtod(m, ng_hci_acldata_pkt_t *);
1254 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1256 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1262 if (s == USBD_CANCELLED) {
1264 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1265 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe);
1271 if (s != USBD_NORMAL_COMPLETION) {
1273 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1274 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1276 if (s == USBD_STALLED)
1277 usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1279 NG_UBT_STAT_IERROR(sc->sc_stat);
1282 return; /* XXX FIXME we should restart after some delay */
1285 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1286 m->m_pkthdr.len += h->actlen;
1287 m->m_len += h->actlen;
1290 "%s: %s - Got %d bytes from bulk-in pipe\n",
1291 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1293 if (m->m_pkthdr.len < sizeof(*hdr)) {
1298 len = le16toh(hdr->length);
1299 if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1301 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1302 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, len);
1304 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1306 NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1308 NG_UBT_STAT_IERROR(sc->sc_stat);
1311 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1312 __func__, USBDEVNAME(sc->sc_dev), len,
1315 NG_UBT_STAT_IERROR(sc->sc_stat);
1319 ubt_bulk_in_start(sc);
1320 } /* ubt_bulk_in_complete2 */
1323 * Start bulk-out USB transfer. Must be called with node locked
1327 ubt_bulk_out_start(ubt_softc_p sc)
1329 struct mbuf *m = NULL;
1332 KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1333 "%s: %s - Another bulk-out request is pending\n",
1334 __func__, USBDEVNAME(sc->sc_dev)));
1336 NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1339 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1341 return (USBD_NORMAL_COMPLETION);
1345 * Check ACL data frame size and copy it back to linear USB
1349 if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1351 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1352 __func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1355 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1357 /* Initialize a bulk-out USB transfer and then schedule it */
1359 sc->sc_bulk_out_xfer,
1360 sc->sc_bulk_out_pipe,
1361 (usbd_private_handle) sc->sc_node,
1362 sc->sc_bulk_out_buffer,
1365 USBD_DEFAULT_TIMEOUT, /* XXX */
1366 ubt_bulk_out_complete);
1368 NG_NODE_REF(sc->sc_node);
1370 status = usbd_transfer(sc->sc_bulk_out_xfer);
1371 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1373 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1374 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1377 NG_NODE_UNREF(sc->sc_node);
1379 NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1380 NG_UBT_STAT_OERROR(sc->sc_stat);
1382 /* XXX FIXME should we try to start another transfer? */
1385 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1386 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len);
1388 sc->sc_flags |= UBT_ACL_XMIT;
1389 status = USBD_NORMAL_COMPLETION;
1395 } /* ubt_bulk_out_start */
1398 * USB bulk-out transfer callback
1402 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1404 ng_send_fn((node_p) p, NULL, ubt_bulk_out_complete2, (void *) h, s);
1405 NG_NODE_UNREF((node_p) p);
1406 } /* ubt_bulk_out_complete */
1409 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1411 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1412 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1413 usbd_status s = (usbd_status) arg2;
1418 KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1419 "%s: %s - No bulk-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1421 sc->sc_flags &= ~UBT_ACL_XMIT;
1423 if (s == USBD_CANCELLED) {
1425 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1426 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_out_pipe);
1431 if (s != USBD_NORMAL_COMPLETION) {
1433 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1434 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1436 if (s == USBD_STALLED)
1437 usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1439 NG_UBT_STAT_OERROR(sc->sc_stat);
1442 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1443 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1445 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1446 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1449 if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1450 ubt_bulk_out_start(sc);
1451 } /* ubt_bulk_out_complete2 */
1454 * Start Isochronous-in USB transfer. Must be called with node locked
1458 ubt_isoc_in_start(ubt_softc_p sc)
1463 KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1464 "%s: %s - Another isoc-in request is pending\n",
1465 __func__, USBDEVNAME(sc->sc_dev)));
1467 /* Initialize a isoc-in USB transfer and then schedule it */
1468 for (i = 0; i < sc->sc_isoc_nframes; i++)
1469 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1471 usbd_setup_isoc_xfer(
1472 sc->sc_isoc_in_xfer,
1473 sc->sc_isoc_in_pipe,
1474 (usbd_private_handle) sc->sc_node,
1475 sc->sc_isoc_in_frlen,
1476 sc->sc_isoc_nframes,
1477 USBD_NO_COPY, /* XXX flags */
1478 ubt_isoc_in_complete);
1480 NG_NODE_REF(sc->sc_node);
1482 status = usbd_transfer(sc->sc_isoc_in_xfer);
1483 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1485 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1486 __func__, USBDEVNAME(sc->sc_dev),
1487 usbd_errstr(status), status);
1489 NG_NODE_UNREF(sc->sc_node);
1494 sc->sc_flags |= UBT_SCO_RECV;
1496 return (USBD_NORMAL_COMPLETION);
1497 } /* ubt_isoc_in_start */
1500 * USB isochronous transfer callback
1504 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1506 ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1507 NG_NODE_UNREF((node_p) p);
1508 } /* ubt_isoc_in_complete */
1511 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1513 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1514 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1515 usbd_status s = (usbd_status) arg2;
1516 struct mbuf *m = NULL;
1517 ng_hci_scodata_pkt_t *hdr = NULL;
1524 KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1525 "%s: %s - No isoc-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1527 sc->sc_flags &= ~UBT_SCO_RECV;
1529 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1531 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1536 if (s == USBD_CANCELLED) {
1538 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1539 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe);
1544 if (s != USBD_NORMAL_COMPLETION) {
1546 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1547 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1549 if (s == USBD_STALLED)
1550 usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1552 NG_UBT_STAT_IERROR(sc->sc_stat);
1554 return; /* XXX FIXME we should restart after some delay */
1557 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1560 "%s: %s - Got %d bytes from isoc-in pipe\n",
1561 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1563 /* Copy SCO data frame to mbuf */
1564 MGETHDR(m, M_DONTWAIT, MT_DATA);
1567 "%s: %s - Could not allocate mbuf\n",
1568 __func__, USBDEVNAME(sc->sc_dev));
1570 NG_UBT_STAT_IERROR(sc->sc_stat);
1574 /* Fix SCO data frame header if required */
1575 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1576 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1577 m->m_pkthdr.len = 1;
1578 m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1580 m->m_pkthdr.len = 0;
1581 m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1585 * XXX FIXME how do we know how many frames we have received?
1586 * XXX use frlen for now. is that correct?
1589 b = (u_int8_t *) sc->sc_isoc_in_buffer;
1591 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1592 b += (i * sc->sc_isoc_size);
1594 if (sc->sc_isoc_in_frlen[i] > 0)
1595 m_copyback(m, m->m_pkthdr.len,
1596 sc->sc_isoc_in_frlen[i], b);
1599 if (m->m_pkthdr.len < sizeof(*hdr))
1602 hdr = mtod(m, ng_hci_scodata_pkt_t *);
1604 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1606 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1607 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1610 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1612 NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1614 NG_UBT_STAT_IERROR(sc->sc_stat);
1617 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1618 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1621 NG_UBT_STAT_IERROR(sc->sc_stat);
1625 ubt_isoc_in_start(sc);
1626 } /* ubt_isoc_in_complete2 */
1629 * Start isochronous-out USB transfer. Must be called with node locked
1633 ubt_isoc_out_start(ubt_softc_p sc)
1635 struct mbuf *m = NULL;
1637 int i, len, nframes;
1640 KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1641 "%s: %s - Another isoc-out request is pending\n",
1642 __func__, USBDEVNAME(sc->sc_dev)));
1644 NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1647 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1649 return (USBD_NORMAL_COMPLETION);
1652 /* Copy entire SCO frame into USB transfer buffer and start transfer */
1653 b = (u_int8_t *) sc->sc_isoc_out_buffer;
1656 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1657 b += (i * sc->sc_isoc_size);
1659 len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1661 m_copydata(m, 0, len, b);
1666 sc->sc_isoc_out_frlen[i] = len;
1669 if (m->m_pkthdr.len > 0)
1671 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1672 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes,
1673 sc->sc_isoc_size, m->m_pkthdr.len);
1677 /* Initialize a isoc-out USB transfer and then schedule it */
1678 usbd_setup_isoc_xfer(
1679 sc->sc_isoc_out_xfer,
1680 sc->sc_isoc_out_pipe,
1681 (usbd_private_handle) sc->sc_node,
1682 sc->sc_isoc_out_frlen,
1685 ubt_isoc_out_complete);
1687 NG_NODE_REF(sc->sc_node);
1689 status = usbd_transfer(sc->sc_isoc_out_xfer);
1690 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1692 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1693 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1696 NG_NODE_UNREF(sc->sc_node);
1698 NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1699 NG_UBT_STAT_OERROR(sc->sc_stat);
1702 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1703 __func__, USBDEVNAME(sc->sc_dev), nframes,
1706 sc->sc_flags |= UBT_SCO_XMIT;
1707 status = USBD_NORMAL_COMPLETION;
1711 } /* ubt_isoc_out_start */
1714 * USB isoc-out. transfer callback
1718 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1720 ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1721 NG_NODE_UNREF((node_p) p);
1722 } /* ubt_isoc_out_complete */
1725 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1727 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1728 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1729 usbd_status s = (usbd_status) arg2;
1734 KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1735 "%s: %s - No isoc-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1737 sc->sc_flags &= ~UBT_SCO_XMIT;
1739 if (s == USBD_CANCELLED) {
1741 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1742 __func__, USBDEVNAME(sc->sc_dev),
1743 sc->sc_isoc_out_pipe);
1748 if (s != USBD_NORMAL_COMPLETION) {
1750 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1751 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1753 if (s == USBD_STALLED)
1754 usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1756 NG_UBT_STAT_OERROR(sc->sc_stat);
1759 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1760 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1762 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1763 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1766 if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1767 ubt_isoc_out_start(sc);
1768 } /* ubt_isoc_out_complete2 */
1771 * Abort transfers on all USB pipes
1775 ubt_reset(ubt_softc_p sc)
1778 if (sc->sc_intr_pipe != NULL)
1779 usbd_abort_pipe(sc->sc_intr_pipe);
1782 if (sc->sc_bulk_in_pipe != NULL)
1783 usbd_abort_pipe(sc->sc_bulk_in_pipe);
1784 if (sc->sc_bulk_out_pipe != NULL)
1785 usbd_abort_pipe(sc->sc_bulk_out_pipe);
1788 if (sc->sc_isoc_in_pipe != NULL)
1789 usbd_abort_pipe(sc->sc_isoc_in_pipe);
1790 if (sc->sc_isoc_out_pipe != NULL)
1791 usbd_abort_pipe(sc->sc_isoc_out_pipe);
1793 /* Cleanup queues */
1794 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1795 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1796 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1799 /****************************************************************************
1800 ****************************************************************************
1801 ** Netgraph specific
1802 ****************************************************************************
1803 ****************************************************************************/
1806 * Netgraph node constructor. Do not allow to create node of this type.
1810 ng_ubt_constructor(node_p node)
1813 } /* ng_ubt_constructor */
1816 * Netgraph node destructor. Destroy node only when device has been detached
1820 ng_ubt_shutdown(node_p node)
1822 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1824 /* Let old node go */
1825 NG_NODE_SET_PRIVATE(node, NULL);
1826 NG_NODE_UNREF(node);
1831 /* Create Netgraph node */
1832 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1833 printf("%s: Could not create Netgraph node\n",
1834 USBDEVNAME(sc->sc_dev));
1840 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
1841 printf("%s: Could not name Netgraph node\n",
1842 USBDEVNAME(sc->sc_dev));
1843 NG_NODE_UNREF(sc->sc_node);
1848 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1849 NG_NODE_FORCE_WRITER(sc->sc_node);
1852 } /* ng_ubt_shutdown */
1855 * Create new hook. There can only be one.
1859 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1861 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1863 if (strcmp(name, NG_UBT_HOOK) != 0)
1866 if (sc->sc_hook != NULL)
1872 } /* ng_ubt_newhook */
1875 * Connect hook. Start incoming USB transfers
1879 ng_ubt_connect(hook_p hook)
1881 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1884 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1886 /* Start intr transfer */
1887 status = ubt_intr_start(sc);
1888 if (status != USBD_NORMAL_COMPLETION) {
1890 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1891 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1896 /* Start bulk-in transfer */
1897 status = ubt_bulk_in_start(sc);
1898 if (status != USBD_NORMAL_COMPLETION) {
1900 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1901 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1906 #if __broken__ /* XXX FIXME */
1907 /* Start isoc-in transfer */
1908 status = ubt_isoc_in_start(sc);
1909 if (status != USBD_NORMAL_COMPLETION) {
1911 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1912 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1916 #endif /* __broken__ */
1924 } /* ng_ubt_connect */
1931 ng_ubt_disconnect(hook_p hook)
1933 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1936 if (hook != sc->sc_hook)
1944 } /* ng_ubt_disconnect */
1947 * Process control message
1951 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
1953 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1954 struct ng_mesg *msg = NULL, *rsp = NULL;
1955 struct ng_bt_mbufq *q = NULL;
1956 int error = 0, queue, qlen;
1963 NGI_GET_MSG(item, msg);
1965 switch (msg->header.typecookie) {
1966 case NGM_GENERIC_COOKIE:
1967 switch (msg->header.cmd) {
1968 case NGM_TEXT_STATUS:
1969 NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
1973 snprintf(rsp->data, NG_TEXTRESPONSE,
1977 "CMD queue: [have:%d,max:%d]\n" \
1978 "ACL queue: [have:%d,max:%d]\n" \
1979 "SCO queue: [have:%d,max:%d]",
1980 (sc->sc_hook != NULL)? NG_UBT_HOOK : "",
1983 NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
1985 NG_BT_MBUFQ_LEN(&sc->sc_aclq),
1987 NG_BT_MBUFQ_LEN(&sc->sc_scoq),
1988 sc->sc_scoq.maxlen);
1997 case NGM_UBT_COOKIE:
1998 switch (msg->header.cmd) {
1999 case NGM_UBT_NODE_SET_DEBUG:
2000 if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2004 *((ng_ubt_node_debug_ep *)(msg->data));
2007 case NGM_UBT_NODE_GET_DEBUG:
2008 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2013 *((ng_ubt_node_debug_ep *)(rsp->data)) =
2017 case NGM_UBT_NODE_SET_QLEN:
2018 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2021 queue = ((ng_ubt_node_qlen_ep *)
2022 (msg->data))->queue;
2023 qlen = ((ng_ubt_node_qlen_ep *)
2032 case NGM_UBT_NODE_QUEUE_CMD:
2036 case NGM_UBT_NODE_QUEUE_ACL:
2040 case NGM_UBT_NODE_QUEUE_SCO:
2055 case NGM_UBT_NODE_GET_QLEN:
2056 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2061 queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2063 case NGM_UBT_NODE_QUEUE_CMD:
2067 case NGM_UBT_NODE_QUEUE_ACL:
2071 case NGM_UBT_NODE_QUEUE_SCO:
2082 NG_MKRESPONSE(rsp, msg,
2083 sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
2089 ((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2091 ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2096 case NGM_UBT_NODE_GET_STAT:
2097 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2102 bcopy(&sc->sc_stat, rsp->data,
2103 sizeof(ng_ubt_node_stat_ep));
2106 case NGM_UBT_NODE_RESET_STAT:
2107 NG_UBT_STAT_RESET(sc->sc_stat);
2121 NG_RESPOND_MSG(error, node, item, rsp);
2125 } /* ng_ubt_rcvmsg */
2132 ng_ubt_rcvdata(hook_p hook, item_p item)
2134 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2135 struct mbuf *m = NULL;
2136 usbd_status (*f)(ubt_softc_p) = NULL;
2137 struct ng_bt_mbufq *q = NULL;
2145 if (hook != sc->sc_hook) {
2150 /* Deatch mbuf and get HCI frame type */
2153 /* Process HCI frame */
2154 switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2155 case NG_HCI_CMD_PKT:
2156 f = ubt_request_start;
2161 case NG_HCI_ACL_DATA_PKT:
2162 f = ubt_bulk_out_start;
2167 #if __broken__ /* XXX FIXME */
2168 case NG_HCI_SCO_DATA_PKT:
2169 f = ubt_isoc_out_start;
2173 #endif /* __broken__ */
2177 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2178 __func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *),
2188 /* Loose frame type, if required */
2189 if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2190 m_adj(m, sizeof(u_int8_t));
2192 if (NG_BT_MBUFQ_FULL(q)) {
2194 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2195 __func__, USBDEVNAME(sc->sc_dev),
2196 *mtod(m, u_int8_t *), m->m_pkthdr.len);
2200 NG_BT_MBUFQ_ENQUEUE(q, m);
2202 if (!(sc->sc_flags & b))
2203 if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2209 } /* ng_ubt_rcvdata */