4 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $Id: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
36 #include <sys/endian.h>
37 #include <sys/filio.h>
38 #include <sys/fcntl.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
45 #include <machine/bus.h>
47 #include <dev/usb/usb.h>
48 #include <dev/usb/usbdi.h>
49 #include <dev/usb/usbdi_util.h>
50 #include <dev/usb/usbdivar.h>
52 #include <netgraph/ng_message.h>
53 #include <netgraph/netgraph.h>
54 #include <netgraph/ng_parse.h>
55 #include <netgraph/bluetooth/include/ng_bluetooth.h>
56 #include <netgraph/bluetooth/include/ng_hci.h>
57 #include <netgraph/bluetooth/include/ng_ubt.h>
58 #include <netgraph/bluetooth/drivers/ubt/ng_ubt_var.h>
66 USB_DECLARE_DRIVER(ubt);
68 Static int ubt_modevent (module_t, int, void *);
70 Static usbd_status ubt_request_start (ubt_softc_p);
71 Static void ubt_request_complete (usbd_xfer_handle,
72 usbd_private_handle, usbd_status);
73 Static void ubt_request_complete2 (node_p, hook_p, void *, int);
75 Static usbd_status ubt_intr_start (ubt_softc_p);
76 Static void ubt_intr_complete (usbd_xfer_handle,
77 usbd_private_handle, usbd_status);
78 Static void ubt_intr_complete2 (node_p, hook_p, void *, int);
80 Static usbd_status ubt_bulk_in_start (ubt_softc_p);
81 Static void ubt_bulk_in_complete (usbd_xfer_handle,
82 usbd_private_handle, usbd_status);
83 Static void ubt_bulk_in_complete2 (node_p, hook_p, void *, int);
85 Static usbd_status ubt_bulk_out_start (ubt_softc_p);
86 Static void ubt_bulk_out_complete (usbd_xfer_handle,
87 usbd_private_handle, usbd_status);
88 Static void ubt_bulk_out_complete2 (node_p, hook_p, void *, int);
90 Static usbd_status ubt_isoc_in_start (ubt_softc_p);
91 Static void ubt_isoc_in_complete (usbd_xfer_handle,
92 usbd_private_handle, usbd_status);
93 Static void ubt_isoc_in_complete2 (node_p, hook_p, void *, int);
95 Static usbd_status ubt_isoc_out_start (ubt_softc_p);
96 Static void ubt_isoc_out_complete (usbd_xfer_handle,
97 usbd_private_handle, usbd_status);
98 Static void ubt_isoc_out_complete2 (node_p, hook_p, void *, int);
100 Static void ubt_reset (ubt_softc_p);
106 Static ng_constructor_t ng_ubt_constructor;
107 Static ng_shutdown_t ng_ubt_shutdown;
108 Static ng_newhook_t ng_ubt_newhook;
109 Static ng_connect_t ng_ubt_connect;
110 Static ng_disconnect_t ng_ubt_disconnect;
111 Static ng_rcvmsg_t ng_ubt_rcvmsg;
112 Static ng_rcvdata_t ng_ubt_rcvdata;
115 Static const struct ng_parse_struct_field ng_ubt_node_qlen_type_fields[] =
117 { "queue", &ng_parse_int32_type, },
118 { "qlen", &ng_parse_int32_type, },
121 Static const struct ng_parse_type ng_ubt_node_qlen_type = {
122 &ng_parse_struct_type,
123 &ng_ubt_node_qlen_type_fields
127 Static const struct ng_parse_struct_field ng_ubt_node_stat_type_fields[] =
129 { "pckts_recv", &ng_parse_uint32_type, },
130 { "bytes_recv", &ng_parse_uint32_type, },
131 { "pckts_sent", &ng_parse_uint32_type, },
132 { "bytes_sent", &ng_parse_uint32_type, },
133 { "oerrors", &ng_parse_uint32_type, },
134 { "ierrors", &ng_parse_uint32_type, },
137 Static const struct ng_parse_type ng_ubt_node_stat_type = {
138 &ng_parse_struct_type,
139 &ng_ubt_node_stat_type_fields
142 /* Netgraph node command list */
143 Static const struct ng_cmdlist ng_ubt_cmdlist[] = {
146 NGM_UBT_NODE_SET_DEBUG,
148 &ng_parse_uint16_type,
153 NGM_UBT_NODE_GET_DEBUG,
156 &ng_parse_uint16_type
160 NGM_UBT_NODE_SET_QLEN,
162 &ng_ubt_node_qlen_type,
167 NGM_UBT_NODE_GET_QLEN,
169 &ng_ubt_node_qlen_type,
170 &ng_ubt_node_qlen_type
174 NGM_UBT_NODE_GET_STAT,
177 &ng_ubt_node_stat_type
181 NGM_UBT_NODE_RESET_STAT,
189 /* Netgraph node type */
190 Static struct ng_type typestruct = {
191 .version = NG_ABI_VERSION,
192 .name = NG_UBT_NODE_TYPE,
193 .constructor = ng_ubt_constructor,
194 .rcvmsg = ng_ubt_rcvmsg,
195 .shutdown = ng_ubt_shutdown,
196 .newhook = ng_ubt_newhook,
197 .connect = ng_ubt_connect,
198 .rcvdata = ng_ubt_rcvdata,
199 .disconnect = ng_ubt_disconnect,
200 .cmdlist = ng_ubt_cmdlist
207 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
208 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
209 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
211 /****************************************************************************
212 ****************************************************************************
214 ****************************************************************************
215 ****************************************************************************/
218 * Load/Unload the driver module
222 ubt_modevent(module_t mod, int event, void *data)
228 error = ng_newtype(&typestruct);
231 "%s: Could not register Netgraph node type, error=%d\n",
232 NG_UBT_NODE_TYPE, error);
234 error = usbd_driver_load(mod, event, data);
238 error = ng_rmtype(&typestruct);
240 error = usbd_driver_load(mod, event, data);
252 * Probe for a USB Bluetooth device
258 * If for some reason device should not be attached then put
259 * VendorID/ProductID pair into the list below. Currently I
260 * do not know of any such devices. The format is as follows:
262 * { VENDOR_ID, PRODUCT_ID },
264 * where VENDOR_ID and PRODUCT_ID are hex numbers.
267 Static struct usb_devno const ubt_ignored_devices[] = {
268 { 0, 0 } /* This should be the last item in the list */
272 * If device violates Bluetooth specification and has bDeviceClass,
273 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
274 * could try to put VendorID/ProductID pair into the list below.
275 * Currently I do not know of any such devices.
278 Static struct usb_devno const ubt_broken_devices[] = {
279 { 0, 0 } /* This should be the last item in the list */
282 USB_MATCH_START(ubt, uaa);
284 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
286 if (uaa->iface == NULL ||
287 usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
288 return (UMATCH_NONE);
290 if (dd->bDeviceClass == UDCLASS_WIRELESS &&
291 dd->bDeviceSubClass == UDSUBCLASS_RF &&
292 dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
293 return (UMATCH_DEVCLASS_DEVSUBCLASS);
295 if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
296 return (UMATCH_VENDOR_PRODUCT);
298 return (UMATCH_NONE);
299 } /* USB_MATCH(ubt) */
307 USB_ATTACH_START(ubt, sc, uaa);
308 usb_config_descriptor_t *cd = NULL;
309 usb_interface_descriptor_t *id = NULL;
310 usb_endpoint_descriptor_t *ed = NULL;
313 int i, ai, alt_no, isoc_in, isoc_out,
314 isoc_isize, isoc_osize;
316 /* Get USB device info */
317 sc->sc_udev = uaa->device;
318 usbd_devinfo(sc->sc_udev, 0, devinfo);
320 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
323 * Initialize device softc structure
327 sc->sc_debug = NG_UBT_WARN_LEVEL;
329 NG_UBT_STAT_RESET(sc->sc_stat);
332 sc->sc_iface0 = sc->sc_iface1 = NULL;
336 sc->sc_intr_pipe = NULL;
337 sc->sc_intr_xfer = NULL;
338 sc->sc_intr_buffer = NULL;
341 sc->sc_ctrl_xfer = NULL;
342 sc->sc_ctrl_buffer = NULL;
343 NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
346 sc->sc_bulk_in_ep = -1;
347 sc->sc_bulk_in_pipe = NULL;
348 sc->sc_bulk_in_xfer = NULL;
349 sc->sc_bulk_in_buffer = NULL;
352 sc->sc_bulk_out_ep = -1;
353 sc->sc_bulk_out_pipe = NULL;
354 sc->sc_bulk_out_xfer = NULL;
355 sc->sc_bulk_out_buffer = NULL;
356 NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
359 sc->sc_isoc_in_ep = -1;
360 sc->sc_isoc_in_pipe = NULL;
361 sc->sc_isoc_in_xfer = NULL;
364 sc->sc_isoc_out_ep = -1;
365 sc->sc_isoc_out_pipe = NULL;
366 sc->sc_isoc_out_xfer = NULL;
367 sc->sc_isoc_size = -1;
368 NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
375 * XXX set configuration?
377 * Configure Bluetooth USB device. Discover all required USB interfaces
380 * USB device must present two interfaces:
381 * 1) Interface 0 that has 3 endpoints
382 * 1) Interrupt endpoint to receive HCI events
383 * 2) Bulk IN endpoint to receive ACL data
384 * 3) Bulk OUT endpoint to send ACL data
386 * 2) Interface 1 then has 2 endpoints
387 * 1) Isochronous IN endpoint to receive SCO data
388 * 2) Isochronous OUT endpoint to send SCO data
390 * Interface 1 (with isochronous endpoints) has several alternate
391 * configurations with different packet size.
398 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
399 if (error || sc->sc_iface0 == NULL) {
400 printf("%s: Could not get interface 0 handle. %s (%d), " \
401 "handle=%p\n", USBDEVNAME(sc->sc_dev),
402 usbd_errstr(error), error, sc->sc_iface0);
406 id = usbd_get_interface_descriptor(sc->sc_iface0);
408 printf("%s: Could not get interface 0 descriptor\n",
409 USBDEVNAME(sc->sc_dev));
413 for (i = 0; i < id->bNumEndpoints; i ++) {
414 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
416 printf("%s: Could not read endpoint descriptor for " \
417 "interface 0, i=%d\n", USBDEVNAME(sc->sc_dev),
422 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
424 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
425 sc->sc_bulk_in_ep = ed->bEndpointAddress;
427 sc->sc_bulk_out_ep = ed->bEndpointAddress;
431 sc->sc_intr_ep = ed->bEndpointAddress;
436 /* Check if we got everything we wanted on Interface 0 */
437 if (sc->sc_intr_ep == -1) {
438 printf("%s: Could not detect interrupt endpoint\n",
439 USBDEVNAME(sc->sc_dev));
442 if (sc->sc_bulk_in_ep == -1) {
443 printf("%s: Could not detect bulk-in endpoint\n",
444 USBDEVNAME(sc->sc_dev));
447 if (sc->sc_bulk_out_ep == -1) {
448 printf("%s: Could not detect bulk-out endpoint\n",
449 USBDEVNAME(sc->sc_dev));
453 printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
454 "bulk-out=%#x\n", USBDEVNAME(sc->sc_dev),
455 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
461 cd = usbd_get_config_descriptor(sc->sc_udev);
463 printf("%s: Could not get device configuration descriptor\n",
464 USBDEVNAME(sc->sc_dev));
468 error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
469 if (error || sc->sc_iface1 == NULL) {
470 printf("%s: Could not get interface 1 handle. %s (%d), " \
471 "handle=%p\n", USBDEVNAME(sc->sc_dev),
472 usbd_errstr(error), error, sc->sc_iface1);
476 id = usbd_get_interface_descriptor(sc->sc_iface1);
478 printf("%s: Could not get interface 1 descriptor\n",
479 USBDEVNAME(sc->sc_dev));
484 * Scan all alternate configurations for interface 1
489 for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++) {
490 error = usbd_set_interface(sc->sc_iface1, ai);
492 printf("%s: [SCAN] Could not set alternate " \
493 "configuration %d for interface 1. %s (%d)\n",
494 USBDEVNAME(sc->sc_dev), ai, usbd_errstr(error),
498 id = usbd_get_interface_descriptor(sc->sc_iface1);
500 printf("%s: Could not get interface 1 descriptor for " \
501 "alternate configuration %d\n",
502 USBDEVNAME(sc->sc_dev), ai);
506 isoc_in = isoc_out = -1;
507 isoc_isize = isoc_osize = 0;
509 for (i = 0; i < id->bNumEndpoints; i ++) {
510 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
512 printf("%s: Could not read endpoint " \
513 "descriptor for interface 1, " \
514 "alternate configuration %d, i=%d\n",
515 USBDEVNAME(sc->sc_dev), ai, i);
519 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
522 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
523 isoc_in = ed->bEndpointAddress;
524 isoc_isize = UGETW(ed->wMaxPacketSize);
526 isoc_out = ed->bEndpointAddress;
527 isoc_osize = UGETW(ed->wMaxPacketSize);
532 * Make sure that configuration looks sane and if so
533 * update current settings
536 if (isoc_in != -1 && isoc_out != -1 &&
537 isoc_isize > 0 && isoc_osize > 0 &&
538 isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
539 sc->sc_isoc_in_ep = isoc_in;
540 sc->sc_isoc_out_ep = isoc_out;
541 sc->sc_isoc_size = isoc_isize;
546 /* Check if we got everything we wanted on Interface 0 */
547 if (sc->sc_isoc_in_ep == -1) {
548 printf("%s: Could not detect isoc-in endpoint\n",
549 USBDEVNAME(sc->sc_dev));
552 if (sc->sc_isoc_out_ep == -1) {
553 printf("%s: Could not detect isoc-out endpoint\n",
554 USBDEVNAME(sc->sc_dev));
557 if (sc->sc_isoc_size <= 0) {
558 printf("%s: Invalid isoc. packet size=%d\n",
559 USBDEVNAME(sc->sc_dev), sc->sc_isoc_size);
563 error = usbd_set_interface(sc->sc_iface1, alt_no);
565 printf("%s: Could not set alternate configuration " \
566 "%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev),
567 alt_no, usbd_errstr(error), error);
571 /* Allocate USB transfer handles and buffers */
572 sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
573 if (sc->sc_ctrl_xfer == NULL) {
574 printf("%s: Could not allocate control xfer handle\n",
575 USBDEVNAME(sc->sc_dev));
578 sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
579 UBT_CTRL_BUFFER_SIZE);
580 if (sc->sc_ctrl_buffer == NULL) {
581 printf("%s: Could not allocate control buffer\n",
582 USBDEVNAME(sc->sc_dev));
586 sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
587 if (sc->sc_intr_xfer == NULL) {
588 printf("%s: Could not allocate interrupt xfer handle\n",
589 USBDEVNAME(sc->sc_dev));
593 sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
594 if (sc->sc_bulk_in_xfer == NULL) {
595 printf("%s: Could not allocate bulk-in xfer handle\n",
596 USBDEVNAME(sc->sc_dev));
600 sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
601 if (sc->sc_bulk_out_xfer == NULL) {
602 printf("%s: Could not allocate bulk-out xfer handle\n",
603 USBDEVNAME(sc->sc_dev));
606 sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
607 UBT_BULK_BUFFER_SIZE);
608 if (sc->sc_bulk_out_buffer == NULL) {
609 printf("%s: Could not allocate bulk-out buffer\n",
610 USBDEVNAME(sc->sc_dev));
615 * Allocate buffers for isoc. transfers
618 sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
620 sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
621 if (sc->sc_isoc_in_xfer == NULL) {
622 printf("%s: Could not allocate isoc-in xfer handle\n",
623 USBDEVNAME(sc->sc_dev));
626 sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
627 sc->sc_isoc_nframes * sc->sc_isoc_size);
628 if (sc->sc_isoc_in_buffer == NULL) {
629 printf("%s: Could not allocate isoc-in buffer\n",
630 USBDEVNAME(sc->sc_dev));
633 sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
635 if (sc->sc_isoc_in_frlen == NULL) {
636 printf("%s: Could not allocate isoc-in frame sizes buffer\n",
637 USBDEVNAME(sc->sc_dev));
641 sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
642 if (sc->sc_isoc_out_xfer == NULL) {
643 printf("%s: Could not allocate isoc-out xfer handle\n",
644 USBDEVNAME(sc->sc_dev));
647 sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
648 sc->sc_isoc_nframes * sc->sc_isoc_size);
649 if (sc->sc_isoc_out_buffer == NULL) {
650 printf("%s: Could not allocate isoc-out buffer\n",
651 USBDEVNAME(sc->sc_dev));
654 sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
656 if (sc->sc_isoc_out_frlen == NULL) {
657 printf("%s: Could not allocate isoc-out frame sizes buffer\n",
658 USBDEVNAME(sc->sc_dev));
662 printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
663 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
664 USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
665 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
666 (sc->sc_isoc_nframes * sc->sc_isoc_size));
673 error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
674 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
675 if (error != USBD_NORMAL_COMPLETION) {
676 printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
677 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
683 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
684 USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
685 if (error != USBD_NORMAL_COMPLETION) {
686 printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
687 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
693 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
694 USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
695 if (error != USBD_NORMAL_COMPLETION) {
696 printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
697 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
702 #if __broken__ /* XXX FIXME */
704 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
705 USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
706 if (error != USBD_NORMAL_COMPLETION) {
707 printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
708 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
714 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
715 USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
716 if (error != USBD_NORMAL_COMPLETION) {
717 printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
718 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
722 #endif /* __broken__ */
724 /* Create Netgraph node */
725 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
726 printf("%s: Could not create Netgraph node\n",
727 USBDEVNAME(sc->sc_dev));
733 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
734 printf("%s: Could not name Netgraph node\n",
735 USBDEVNAME(sc->sc_dev));
736 NG_NODE_UNREF(sc->sc_node);
741 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
742 NG_NODE_FORCE_WRITER(sc->sc_node);
744 /* Claim all interfaces on the device */
745 for (i = 0; i < uaa->nifaces; i++)
746 uaa->ifaces[i] = NULL;
748 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
751 USB_ATTACH_SUCCESS_RETURN;
755 USB_ATTACH_ERROR_RETURN;
756 } /* USB_ATTACH(ubt) */
764 USB_DETACH_START(ubt, sc);
766 /* Destroy Netgraph node */
767 if (sc->sc_node != NULL) {
768 NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
769 ng_rmnode_self(sc->sc_node);
774 if (sc->sc_intr_pipe != NULL) {
775 usbd_close_pipe(sc->sc_intr_pipe);
776 sc->sc_intr_pipe = NULL;
779 if (sc->sc_bulk_in_pipe != NULL) {
780 usbd_close_pipe(sc->sc_bulk_in_pipe);
781 sc->sc_bulk_in_pipe = NULL;
783 if (sc->sc_bulk_out_pipe != NULL) {
784 usbd_close_pipe(sc->sc_bulk_out_pipe);
785 sc->sc_bulk_out_pipe = NULL;
788 if (sc->sc_isoc_in_pipe != NULL) {
789 usbd_close_pipe(sc->sc_isoc_in_pipe);
790 sc->sc_isoc_in_pipe = NULL;
792 if (sc->sc_isoc_out_pipe != NULL) {
793 usbd_close_pipe(sc->sc_isoc_out_pipe);
794 sc->sc_isoc_out_pipe = NULL;
797 /* Destroy USB transfer handles */
798 if (sc->sc_ctrl_xfer != NULL) {
799 usbd_free_xfer(sc->sc_ctrl_xfer);
800 sc->sc_ctrl_xfer = NULL;
803 if (sc->sc_intr_xfer != NULL) {
804 usbd_free_xfer(sc->sc_intr_xfer);
805 sc->sc_intr_xfer = NULL;
808 if (sc->sc_bulk_in_xfer != NULL) {
809 usbd_free_xfer(sc->sc_bulk_in_xfer);
810 sc->sc_bulk_in_xfer = NULL;
812 if (sc->sc_bulk_out_xfer != NULL) {
813 usbd_free_xfer(sc->sc_bulk_out_xfer);
814 sc->sc_bulk_out_xfer = NULL;
817 if (sc->sc_isoc_in_xfer != NULL) {
818 usbd_free_xfer(sc->sc_isoc_in_xfer);
819 sc->sc_isoc_in_xfer = NULL;
821 if (sc->sc_isoc_out_xfer != NULL) {
822 usbd_free_xfer(sc->sc_isoc_out_xfer);
823 sc->sc_isoc_out_xfer = NULL;
826 /* Destroy isoc. frame size buffers */
827 if (sc->sc_isoc_in_frlen != NULL) {
828 free(sc->sc_isoc_in_frlen, M_USBDEV);
829 sc->sc_isoc_in_frlen = NULL;
831 if (sc->sc_isoc_out_frlen != NULL) {
832 free(sc->sc_isoc_out_frlen, M_USBDEV);
833 sc->sc_isoc_out_frlen = NULL;
837 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
838 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
839 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
841 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
845 } /* USB_DETACH(ubt) */
848 * Start USB control request (HCI command). Must be called with node locked
852 ubt_request_start(ubt_softc_p sc)
854 usb_device_request_t req;
855 struct mbuf *m = NULL;
858 KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
859 "%s: %s - Another control request is pending\n",
860 __func__, USBDEVNAME(sc->sc_dev)));
862 NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
865 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
867 return (USBD_NORMAL_COMPLETION);
871 * Check HCI command frame size and copy it back to
872 * linear USB transfer buffer.
875 if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
877 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
878 __func__, USBDEVNAME(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
881 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
883 /* Initialize a USB control request and then schedule it */
884 bzero(&req, sizeof(req));
885 req.bmRequestType = UBT_HCI_REQUEST;
886 USETW(req.wLength, m->m_pkthdr.len);
889 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
890 __func__, USBDEVNAME(sc->sc_dev), req.bmRequestType,
893 usbd_setup_default_xfer(
896 (usbd_private_handle) sc->sc_node,
897 USBD_DEFAULT_TIMEOUT, /* XXX */
902 ubt_request_complete);
904 NG_NODE_REF(sc->sc_node);
906 status = usbd_transfer(sc->sc_ctrl_xfer);
907 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
909 "%s: %s - Could not start control request. %s (%d)\n",
910 __func__, USBDEVNAME(sc->sc_dev),
911 usbd_errstr(status), status);
913 NG_NODE_UNREF(sc->sc_node);
915 NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
916 NG_UBT_STAT_OERROR(sc->sc_stat);
918 /* XXX FIXME should we try to resubmit another request? */
921 "%s: %s - Control request has been started\n",
922 __func__, USBDEVNAME(sc->sc_dev));
924 sc->sc_flags |= UBT_CMD_XMIT;
925 status = USBD_NORMAL_COMPLETION;
931 } /* ubt_request_start */
934 * USB control request callback
938 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
940 ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
941 NG_NODE_UNREF((node_p) p);
942 } /* ubt_request_complete */
945 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
947 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
948 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
949 usbd_status s = (usbd_status) arg2;
954 KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
955 "%s: %s - No control request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
957 sc->sc_flags &= ~UBT_CMD_XMIT;
959 if (s == USBD_CANCELLED) {
961 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
966 if (s != USBD_NORMAL_COMPLETION) {
968 "%s: %s - Control request failed. %s (%d)\n",
969 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
971 if (s == USBD_STALLED)
972 usbd_clear_endpoint_stall_async(h->pipe);
974 NG_UBT_STAT_OERROR(sc->sc_stat);
977 "%s: %s - Sent %d bytes to control pipe\n",
978 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
980 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
981 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
984 if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
985 ubt_request_start(sc);
986 } /* ubt_request_complete2 */
989 * Start interrupt transfer. Must be called when node is locked
993 ubt_intr_start(ubt_softc_p sc)
995 struct mbuf *m = NULL;
998 KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
999 "%s: %s - Another interrupt request is pending\n",
1000 __func__, USBDEVNAME(sc->sc_dev)));
1002 /* Allocate new mbuf cluster */
1003 MGETHDR(m, M_DONTWAIT, MT_DATA);
1005 return (USBD_NOMEM);
1007 MCLGET(m, M_DONTWAIT);
1008 if (!(m->m_flags & M_EXT)) {
1010 return (USBD_NOMEM);
1013 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1014 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1015 m->m_pkthdr.len = m->m_len = 1;
1017 m->m_pkthdr.len = m->m_len = 0;
1019 /* Initialize a USB transfer and then schedule it */
1023 (usbd_private_handle) sc->sc_node,
1024 (void *)(mtod(m, u_int8_t *) + m->m_len),
1025 MCLBYTES - m->m_len,
1030 NG_NODE_REF(sc->sc_node);
1032 status = usbd_transfer(sc->sc_intr_xfer);
1033 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1035 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1036 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1039 NG_NODE_UNREF(sc->sc_node);
1046 sc->sc_flags |= UBT_EVT_RECV;
1047 sc->sc_intr_buffer = m;
1049 return (USBD_NORMAL_COMPLETION);
1050 } /* ubt_intr_start */
1053 * Process interrupt from USB device (We got data from interrupt pipe)
1057 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1059 ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1060 NG_NODE_UNREF((node_p) p);
1061 } /* ubt_intr_complete */
1064 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1066 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1067 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1068 usbd_status s = (usbd_status) arg2;
1069 struct mbuf *m = NULL;
1070 ng_hci_event_pkt_t *hdr = NULL;
1076 KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1077 "%s: %s - No interrupt request is pending\n",
1078 __func__, USBDEVNAME(sc->sc_dev)));
1080 sc->sc_flags &= ~UBT_EVT_RECV;
1082 m = sc->sc_intr_buffer;
1083 sc->sc_intr_buffer = NULL;
1085 hdr = mtod(m, ng_hci_event_pkt_t *);
1087 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1089 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1095 if (s == USBD_CANCELLED) {
1097 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1103 if (s != USBD_NORMAL_COMPLETION) {
1105 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1106 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1108 if (s == USBD_STALLED)
1109 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1111 NG_UBT_STAT_IERROR(sc->sc_stat);
1114 return; /* XXX FIXME we should restart after some delay */
1117 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1118 m->m_pkthdr.len += h->actlen;
1119 m->m_len += h->actlen;
1122 "%s: %s - Got %d bytes from interrupt pipe\n",
1123 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1125 if (m->m_pkthdr.len < sizeof(*hdr)) {
1130 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1132 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1133 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1136 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1138 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1140 NG_UBT_STAT_IERROR(sc->sc_stat);
1143 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1144 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1147 NG_UBT_STAT_IERROR(sc->sc_stat);
1152 } /* ubt_intr_complete2 */
1155 * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1159 ubt_bulk_in_start(ubt_softc_p sc)
1161 struct mbuf *m = NULL;
1164 KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1165 "%s: %s - Another bulk-in request is pending\n",
1166 __func__, USBDEVNAME(sc->sc_dev)));
1168 /* Allocate new mbuf cluster */
1169 MGETHDR(m, M_DONTWAIT, MT_DATA);
1171 return (USBD_NOMEM);
1173 MCLGET(m, M_DONTWAIT);
1174 if (!(m->m_flags & M_EXT)) {
1176 return (USBD_NOMEM);
1179 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1180 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1181 m->m_pkthdr.len = m->m_len = 1;
1183 m->m_pkthdr.len = m->m_len = 0;
1185 /* Initialize a bulk-in USB transfer and then schedule it */
1187 sc->sc_bulk_in_xfer,
1188 sc->sc_bulk_in_pipe,
1189 (usbd_private_handle) sc->sc_node,
1190 (void *)(mtod(m, u_int8_t *) + m->m_len),
1191 MCLBYTES - m->m_len,
1194 ubt_bulk_in_complete);
1196 NG_NODE_REF(sc->sc_node);
1198 status = usbd_transfer(sc->sc_bulk_in_xfer);
1199 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1201 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1202 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1205 NG_NODE_UNREF(sc->sc_node);
1212 sc->sc_flags |= UBT_ACL_RECV;
1213 sc->sc_bulk_in_buffer = m;
1215 return (USBD_NORMAL_COMPLETION);
1216 } /* ubt_bulk_in_start */
1219 * USB bulk-in transfer callback
1223 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1225 ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1226 NG_NODE_UNREF((node_p) p);
1227 } /* ubt_bulk_in_complete */
1230 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1232 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1233 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1234 usbd_status s = (usbd_status) arg2;
1235 struct mbuf *m = NULL;
1236 ng_hci_acldata_pkt_t *hdr = NULL;
1242 KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1243 "%s: %s - No bulk-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1245 sc->sc_flags &= ~UBT_ACL_RECV;
1247 m = sc->sc_bulk_in_buffer;
1248 sc->sc_bulk_in_buffer = NULL;
1250 hdr = mtod(m, ng_hci_acldata_pkt_t *);
1252 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1254 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1260 if (s == USBD_CANCELLED) {
1262 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1263 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe);
1269 if (s != USBD_NORMAL_COMPLETION) {
1271 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1272 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1274 if (s == USBD_STALLED)
1275 usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1277 NG_UBT_STAT_IERROR(sc->sc_stat);
1280 return; /* XXX FIXME we should restart after some delay */
1283 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1284 m->m_pkthdr.len += h->actlen;
1285 m->m_len += h->actlen;
1288 "%s: %s - Got %d bytes from bulk-in pipe\n",
1289 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1291 if (m->m_pkthdr.len < sizeof(*hdr)) {
1296 len = le16toh(hdr->length);
1297 if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1299 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1300 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, len);
1302 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1304 NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1306 NG_UBT_STAT_IERROR(sc->sc_stat);
1309 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1310 __func__, USBDEVNAME(sc->sc_dev), len,
1313 NG_UBT_STAT_IERROR(sc->sc_stat);
1317 ubt_bulk_in_start(sc);
1318 } /* ubt_bulk_in_complete2 */
1321 * Start bulk-out USB transfer. Must be called with node locked
1325 ubt_bulk_out_start(ubt_softc_p sc)
1327 struct mbuf *m = NULL;
1330 KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1331 "%s: %s - Another bulk-out request is pending\n",
1332 __func__, USBDEVNAME(sc->sc_dev)));
1334 NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1337 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1339 return (USBD_NORMAL_COMPLETION);
1343 * Check ACL data frame size and copy it back to linear USB
1347 if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1349 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1350 __func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1353 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1355 /* Initialize a bulk-out USB transfer and then schedule it */
1357 sc->sc_bulk_out_xfer,
1358 sc->sc_bulk_out_pipe,
1359 (usbd_private_handle) sc->sc_node,
1360 sc->sc_bulk_out_buffer,
1363 USBD_DEFAULT_TIMEOUT, /* XXX */
1364 ubt_bulk_out_complete);
1366 NG_NODE_REF(sc->sc_node);
1368 status = usbd_transfer(sc->sc_bulk_out_xfer);
1369 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1371 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1372 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1375 NG_NODE_UNREF(sc->sc_node);
1377 NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1378 NG_UBT_STAT_OERROR(sc->sc_stat);
1380 /* XXX FIXME should we try to start another transfer? */
1383 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1384 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len);
1386 sc->sc_flags |= UBT_ACL_XMIT;
1387 status = USBD_NORMAL_COMPLETION;
1393 } /* ubt_bulk_out_start */
1396 * USB bulk-out transfer callback
1400 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1402 ng_send_fn((node_p) p, NULL, ubt_bulk_out_complete2, (void *) h, s);
1403 NG_NODE_UNREF((node_p) p);
1404 } /* ubt_bulk_out_complete */
1407 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1409 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1410 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1411 usbd_status s = (usbd_status) arg2;
1416 KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1417 "%s: %s - No bulk-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1419 sc->sc_flags &= ~UBT_ACL_XMIT;
1421 if (s == USBD_CANCELLED) {
1423 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1424 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_out_pipe);
1429 if (s != USBD_NORMAL_COMPLETION) {
1431 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1432 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1434 if (s == USBD_STALLED)
1435 usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1437 NG_UBT_STAT_OERROR(sc->sc_stat);
1440 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1441 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1443 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1444 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1447 if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1448 ubt_bulk_out_start(sc);
1449 } /* ubt_bulk_out_complete2 */
1452 * Start Isochronous-in USB transfer. Must be called with node locked
1456 ubt_isoc_in_start(ubt_softc_p sc)
1461 KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1462 "%s: %s - Another isoc-in request is pending\n",
1463 __func__, USBDEVNAME(sc->sc_dev)));
1465 /* Initialize a isoc-in USB transfer and then schedule it */
1466 for (i = 0; i < sc->sc_isoc_nframes; i++)
1467 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1469 usbd_setup_isoc_xfer(
1470 sc->sc_isoc_in_xfer,
1471 sc->sc_isoc_in_pipe,
1472 (usbd_private_handle) sc->sc_node,
1473 sc->sc_isoc_in_frlen,
1474 sc->sc_isoc_nframes,
1475 USBD_NO_COPY, /* XXX flags */
1476 ubt_isoc_in_complete);
1478 NG_NODE_REF(sc->sc_node);
1480 status = usbd_transfer(sc->sc_isoc_in_xfer);
1481 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1483 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1484 __func__, USBDEVNAME(sc->sc_dev),
1485 usbd_errstr(status), status);
1487 NG_NODE_UNREF(sc->sc_node);
1492 sc->sc_flags |= UBT_SCO_RECV;
1494 return (USBD_NORMAL_COMPLETION);
1495 } /* ubt_isoc_in_start */
1498 * USB isochronous transfer callback
1502 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1504 ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1505 NG_NODE_UNREF((node_p) p);
1506 } /* ubt_isoc_in_complete */
1509 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1511 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1512 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1513 usbd_status s = (usbd_status) arg2;
1514 struct mbuf *m = NULL;
1515 ng_hci_scodata_pkt_t *hdr = NULL;
1522 KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1523 "%s: %s - No isoc-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1525 sc->sc_flags &= ~UBT_SCO_RECV;
1527 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1529 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1534 if (s == USBD_CANCELLED) {
1536 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1537 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe);
1542 if (s != USBD_NORMAL_COMPLETION) {
1544 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1545 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1547 if (s == USBD_STALLED)
1548 usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1550 NG_UBT_STAT_IERROR(sc->sc_stat);
1552 return; /* XXX FIXME we should restart after some delay */
1555 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1558 "%s: %s - Got %d bytes from isoc-in pipe\n",
1559 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1561 /* Copy SCO data frame to mbuf */
1562 MGETHDR(m, M_DONTWAIT, MT_DATA);
1565 "%s: %s - Could not allocate mbuf\n",
1566 __func__, USBDEVNAME(sc->sc_dev));
1568 NG_UBT_STAT_IERROR(sc->sc_stat);
1572 /* Fix SCO data frame header if required */
1573 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1574 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1575 m->m_pkthdr.len = 1;
1576 m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1578 m->m_pkthdr.len = 0;
1579 m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1583 * XXX FIXME how do we know how many frames we have received?
1584 * XXX use frlen for now. is that correct?
1587 b = (u_int8_t *) sc->sc_isoc_in_buffer;
1589 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1590 b += (i * sc->sc_isoc_size);
1592 if (sc->sc_isoc_in_frlen[i] > 0)
1593 m_copyback(m, m->m_pkthdr.len,
1594 sc->sc_isoc_in_frlen[i], b);
1597 if (m->m_pkthdr.len < sizeof(*hdr))
1600 hdr = mtod(m, ng_hci_scodata_pkt_t *);
1602 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1604 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1605 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1608 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1610 NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1612 NG_UBT_STAT_IERROR(sc->sc_stat);
1615 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1616 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1619 NG_UBT_STAT_IERROR(sc->sc_stat);
1623 ubt_isoc_in_start(sc);
1624 } /* ubt_isoc_in_complete2 */
1627 * Start isochronous-out USB transfer. Must be called with node locked
1631 ubt_isoc_out_start(ubt_softc_p sc)
1633 struct mbuf *m = NULL;
1635 int i, len, nframes;
1638 KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1639 "%s: %s - Another isoc-out request is pending\n",
1640 __func__, USBDEVNAME(sc->sc_dev)));
1642 NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1645 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1647 return (USBD_NORMAL_COMPLETION);
1650 /* Copy entire SCO frame into USB transfer buffer and start transfer */
1651 b = (u_int8_t *) sc->sc_isoc_out_buffer;
1654 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1655 b += (i * sc->sc_isoc_size);
1657 len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1659 m_copydata(m, 0, len, b);
1664 sc->sc_isoc_out_frlen[i] = len;
1667 if (m->m_pkthdr.len > 0)
1669 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1670 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes,
1671 sc->sc_isoc_size, m->m_pkthdr.len);
1675 /* Initialize a isoc-out USB transfer and then schedule it */
1676 usbd_setup_isoc_xfer(
1677 sc->sc_isoc_out_xfer,
1678 sc->sc_isoc_out_pipe,
1679 (usbd_private_handle) sc->sc_node,
1680 sc->sc_isoc_out_frlen,
1683 ubt_isoc_out_complete);
1685 NG_NODE_REF(sc->sc_node);
1687 status = usbd_transfer(sc->sc_isoc_out_xfer);
1688 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1690 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1691 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1694 NG_NODE_UNREF(sc->sc_node);
1696 NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1697 NG_UBT_STAT_OERROR(sc->sc_stat);
1700 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1701 __func__, USBDEVNAME(sc->sc_dev), nframes,
1704 sc->sc_flags |= UBT_SCO_XMIT;
1705 status = USBD_NORMAL_COMPLETION;
1709 } /* ubt_isoc_out_start */
1712 * USB isoc-out. transfer callback
1716 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1718 ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1719 NG_NODE_UNREF((node_p) p);
1720 } /* ubt_isoc_out_complete */
1723 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1725 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1726 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1727 usbd_status s = (usbd_status) arg2;
1732 KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1733 "%s: %s - No isoc-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1735 sc->sc_flags &= ~UBT_SCO_XMIT;
1737 if (s == USBD_CANCELLED) {
1739 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1740 __func__, USBDEVNAME(sc->sc_dev),
1741 sc->sc_isoc_out_pipe);
1746 if (s != USBD_NORMAL_COMPLETION) {
1748 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1749 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1751 if (s == USBD_STALLED)
1752 usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1754 NG_UBT_STAT_OERROR(sc->sc_stat);
1757 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1758 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1760 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1761 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1764 if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1765 ubt_isoc_out_start(sc);
1766 } /* ubt_isoc_out_complete2 */
1769 * Abort transfers on all USB pipes
1773 ubt_reset(ubt_softc_p sc)
1776 if (sc->sc_intr_pipe != NULL)
1777 usbd_abort_pipe(sc->sc_intr_pipe);
1780 if (sc->sc_bulk_in_pipe != NULL)
1781 usbd_abort_pipe(sc->sc_bulk_in_pipe);
1782 if (sc->sc_bulk_out_pipe != NULL)
1783 usbd_abort_pipe(sc->sc_bulk_out_pipe);
1786 if (sc->sc_isoc_in_pipe != NULL)
1787 usbd_abort_pipe(sc->sc_isoc_in_pipe);
1788 if (sc->sc_isoc_out_pipe != NULL)
1789 usbd_abort_pipe(sc->sc_isoc_out_pipe);
1791 /* Cleanup queues */
1792 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1793 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1794 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1797 /****************************************************************************
1798 ****************************************************************************
1799 ** Netgraph specific
1800 ****************************************************************************
1801 ****************************************************************************/
1804 * Netgraph node constructor. Do not allow to create node of this type.
1808 ng_ubt_constructor(node_p node)
1811 } /* ng_ubt_constructor */
1814 * Netgraph node destructor. Destroy node only when device has been detached
1818 ng_ubt_shutdown(node_p node)
1820 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1822 /* Let old node go */
1823 NG_NODE_SET_PRIVATE(node, NULL);
1824 NG_NODE_UNREF(node);
1829 /* Create Netgraph node */
1830 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1831 printf("%s: Could not create Netgraph node\n",
1832 USBDEVNAME(sc->sc_dev));
1838 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
1839 printf("%s: Could not name Netgraph node\n",
1840 USBDEVNAME(sc->sc_dev));
1841 NG_NODE_UNREF(sc->sc_node);
1846 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1847 NG_NODE_FORCE_WRITER(sc->sc_node);
1850 } /* ng_ubt_shutdown */
1853 * Create new hook. There can only be one.
1857 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1859 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1861 if (strcmp(name, NG_UBT_HOOK) != 0)
1864 if (sc->sc_hook != NULL)
1870 } /* ng_ubt_newhook */
1873 * Connect hook. Start incoming USB transfers
1877 ng_ubt_connect(hook_p hook)
1879 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1882 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1884 /* Start intr transfer */
1885 status = ubt_intr_start(sc);
1886 if (status != USBD_NORMAL_COMPLETION) {
1888 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1889 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1894 /* Start bulk-in transfer */
1895 status = ubt_bulk_in_start(sc);
1896 if (status != USBD_NORMAL_COMPLETION) {
1898 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1899 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1904 #if __broken__ /* XXX FIXME */
1905 /* Start isoc-in transfer */
1906 status = ubt_isoc_in_start(sc);
1907 if (status != USBD_NORMAL_COMPLETION) {
1909 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1910 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1914 #endif /* __broken__ */
1922 } /* ng_ubt_connect */
1929 ng_ubt_disconnect(hook_p hook)
1931 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1934 if (hook != sc->sc_hook)
1942 } /* ng_ubt_disconnect */
1945 * Process control message
1949 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
1951 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1952 struct ng_mesg *msg = NULL, *rsp = NULL;
1953 struct ng_bt_mbufq *q = NULL;
1954 int error = 0, queue, qlen;
1961 NGI_GET_MSG(item, msg);
1963 switch (msg->header.typecookie) {
1964 case NGM_GENERIC_COOKIE:
1965 switch (msg->header.cmd) {
1966 case NGM_TEXT_STATUS:
1967 NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
1971 snprintf(rsp->data, NG_TEXTRESPONSE,
1975 "CMD queue: [have:%d,max:%d]\n" \
1976 "ACL queue: [have:%d,max:%d]\n" \
1977 "SCO queue: [have:%d,max:%d]",
1978 (sc->sc_hook != NULL)? NG_UBT_HOOK : "",
1981 NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
1983 NG_BT_MBUFQ_LEN(&sc->sc_aclq),
1985 NG_BT_MBUFQ_LEN(&sc->sc_scoq),
1986 sc->sc_scoq.maxlen);
1995 case NGM_UBT_COOKIE:
1996 switch (msg->header.cmd) {
1997 case NGM_UBT_NODE_SET_DEBUG:
1998 if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2002 *((ng_ubt_node_debug_ep *)(msg->data));
2005 case NGM_UBT_NODE_GET_DEBUG:
2006 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2011 *((ng_ubt_node_debug_ep *)(rsp->data)) =
2015 case NGM_UBT_NODE_SET_QLEN:
2016 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2019 queue = ((ng_ubt_node_qlen_ep *)
2020 (msg->data))->queue;
2021 qlen = ((ng_ubt_node_qlen_ep *)
2030 case NGM_UBT_NODE_QUEUE_CMD:
2034 case NGM_UBT_NODE_QUEUE_ACL:
2038 case NGM_UBT_NODE_QUEUE_SCO:
2053 case NGM_UBT_NODE_GET_QLEN:
2054 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2059 queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2061 case NGM_UBT_NODE_QUEUE_CMD:
2065 case NGM_UBT_NODE_QUEUE_ACL:
2069 case NGM_UBT_NODE_QUEUE_SCO:
2080 NG_MKRESPONSE(rsp, msg,
2081 sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
2087 ((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2089 ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2094 case NGM_UBT_NODE_GET_STAT:
2095 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2100 bcopy(&sc->sc_stat, rsp->data,
2101 sizeof(ng_ubt_node_stat_ep));
2104 case NGM_UBT_NODE_RESET_STAT:
2105 NG_UBT_STAT_RESET(sc->sc_stat);
2119 NG_RESPOND_MSG(error, node, item, rsp);
2123 } /* ng_ubt_rcvmsg */
2130 ng_ubt_rcvdata(hook_p hook, item_p item)
2132 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2133 struct mbuf *m = NULL;
2134 usbd_status (*f)(ubt_softc_p) = NULL;
2135 struct ng_bt_mbufq *q = NULL;
2143 if (hook != sc->sc_hook) {
2148 /* Deatch mbuf and get HCI frame type */
2151 /* Process HCI frame */
2152 switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2153 case NG_HCI_CMD_PKT:
2154 f = ubt_request_start;
2159 case NG_HCI_ACL_DATA_PKT:
2160 f = ubt_bulk_out_start;
2165 #if __broken__ /* XXX FIXME */
2166 case NG_HCI_SCO_DATA_PKT:
2167 f = ubt_isoc_out_start;
2171 #endif /* __broken__ */
2175 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2176 __func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *),
2186 /* Loose frame type, if required */
2187 if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2188 m_adj(m, sizeof(u_int8_t));
2190 if (NG_BT_MBUFQ_FULL(q)) {
2192 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2193 __func__, USBDEVNAME(sc->sc_dev),
2194 *mtod(m, u_int8_t *), m->m_pkthdr.len);
2198 NG_BT_MBUFQ_ENQUEUE(q, m);
2200 if (!(sc->sc_flags & b))
2201 if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2207 } /* ng_ubt_rcvdata */