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. The format is
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 { USB_VENDOR_AVM, 0x2200 }, /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
271 { 0, 0 } /* This should be the last item in the list */
275 * If device violates Bluetooth specification and has bDeviceClass,
276 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
277 * could try to put VendorID/ProductID pair into the list below.
278 * Adding VendorID/ProductID pair into this list forces ng_ubt(4)
279 * to attach to the broken device.
282 Static struct usb_devno const ubt_broken_devices[] = {
283 { USB_VENDOR_AVM, 0x3800 }, /* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
284 { 0, 0 } /* This should be the last item in the list */
287 USB_MATCH_START(ubt, uaa);
289 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
291 if (uaa->iface == NULL ||
292 usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
293 return (UMATCH_NONE);
295 if (dd->bDeviceClass == UDCLASS_WIRELESS &&
296 dd->bDeviceSubClass == UDSUBCLASS_RF &&
297 dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
298 return (UMATCH_DEVCLASS_DEVSUBCLASS);
300 if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
301 return (UMATCH_VENDOR_PRODUCT);
303 return (UMATCH_NONE);
304 } /* USB_MATCH(ubt) */
312 USB_ATTACH_START(ubt, sc, uaa);
313 usb_config_descriptor_t *cd = NULL;
314 usb_interface_descriptor_t *id = NULL;
315 usb_endpoint_descriptor_t *ed = NULL;
318 int i, ai, alt_no, isoc_in, isoc_out,
319 isoc_isize, isoc_osize;
321 /* Get USB device info */
322 sc->sc_udev = uaa->device;
323 usbd_devinfo(sc->sc_udev, 0, devinfo);
325 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
328 * Initialize device softc structure
332 sc->sc_debug = NG_UBT_WARN_LEVEL;
334 NG_UBT_STAT_RESET(sc->sc_stat);
337 sc->sc_iface0 = sc->sc_iface1 = NULL;
341 sc->sc_intr_pipe = NULL;
342 sc->sc_intr_xfer = NULL;
343 sc->sc_intr_buffer = NULL;
346 sc->sc_ctrl_xfer = NULL;
347 sc->sc_ctrl_buffer = NULL;
348 NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
351 sc->sc_bulk_in_ep = -1;
352 sc->sc_bulk_in_pipe = NULL;
353 sc->sc_bulk_in_xfer = NULL;
354 sc->sc_bulk_in_buffer = NULL;
357 sc->sc_bulk_out_ep = -1;
358 sc->sc_bulk_out_pipe = NULL;
359 sc->sc_bulk_out_xfer = NULL;
360 sc->sc_bulk_out_buffer = NULL;
361 NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
364 sc->sc_isoc_in_ep = -1;
365 sc->sc_isoc_in_pipe = NULL;
366 sc->sc_isoc_in_xfer = NULL;
369 sc->sc_isoc_out_ep = -1;
370 sc->sc_isoc_out_pipe = NULL;
371 sc->sc_isoc_out_xfer = NULL;
372 sc->sc_isoc_size = -1;
373 NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
380 * XXX set configuration?
382 * Configure Bluetooth USB device. Discover all required USB interfaces
385 * USB device must present two interfaces:
386 * 1) Interface 0 that has 3 endpoints
387 * 1) Interrupt endpoint to receive HCI events
388 * 2) Bulk IN endpoint to receive ACL data
389 * 3) Bulk OUT endpoint to send ACL data
391 * 2) Interface 1 then has 2 endpoints
392 * 1) Isochronous IN endpoint to receive SCO data
393 * 2) Isochronous OUT endpoint to send SCO data
395 * Interface 1 (with isochronous endpoints) has several alternate
396 * configurations with different packet size.
403 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
404 if (error || sc->sc_iface0 == NULL) {
405 printf("%s: Could not get interface 0 handle. %s (%d), " \
406 "handle=%p\n", USBDEVNAME(sc->sc_dev),
407 usbd_errstr(error), error, sc->sc_iface0);
411 id = usbd_get_interface_descriptor(sc->sc_iface0);
413 printf("%s: Could not get interface 0 descriptor\n",
414 USBDEVNAME(sc->sc_dev));
418 for (i = 0; i < id->bNumEndpoints; i ++) {
419 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
421 printf("%s: Could not read endpoint descriptor for " \
422 "interface 0, i=%d\n", USBDEVNAME(sc->sc_dev),
427 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
429 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
430 sc->sc_bulk_in_ep = ed->bEndpointAddress;
432 sc->sc_bulk_out_ep = ed->bEndpointAddress;
436 sc->sc_intr_ep = ed->bEndpointAddress;
441 /* Check if we got everything we wanted on Interface 0 */
442 if (sc->sc_intr_ep == -1) {
443 printf("%s: Could not detect interrupt endpoint\n",
444 USBDEVNAME(sc->sc_dev));
447 if (sc->sc_bulk_in_ep == -1) {
448 printf("%s: Could not detect bulk-in endpoint\n",
449 USBDEVNAME(sc->sc_dev));
452 if (sc->sc_bulk_out_ep == -1) {
453 printf("%s: Could not detect bulk-out endpoint\n",
454 USBDEVNAME(sc->sc_dev));
458 printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
459 "bulk-out=%#x\n", USBDEVNAME(sc->sc_dev),
460 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
466 cd = usbd_get_config_descriptor(sc->sc_udev);
468 printf("%s: Could not get device configuration descriptor\n",
469 USBDEVNAME(sc->sc_dev));
473 error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
474 if (error || sc->sc_iface1 == NULL) {
475 printf("%s: Could not get interface 1 handle. %s (%d), " \
476 "handle=%p\n", USBDEVNAME(sc->sc_dev),
477 usbd_errstr(error), error, sc->sc_iface1);
481 id = usbd_get_interface_descriptor(sc->sc_iface1);
483 printf("%s: Could not get interface 1 descriptor\n",
484 USBDEVNAME(sc->sc_dev));
489 * Scan all alternate configurations for interface 1
494 for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++) {
495 error = usbd_set_interface(sc->sc_iface1, ai);
497 printf("%s: [SCAN] Could not set alternate " \
498 "configuration %d for interface 1. %s (%d)\n",
499 USBDEVNAME(sc->sc_dev), ai, usbd_errstr(error),
503 id = usbd_get_interface_descriptor(sc->sc_iface1);
505 printf("%s: Could not get interface 1 descriptor for " \
506 "alternate configuration %d\n",
507 USBDEVNAME(sc->sc_dev), ai);
511 isoc_in = isoc_out = -1;
512 isoc_isize = isoc_osize = 0;
514 for (i = 0; i < id->bNumEndpoints; i ++) {
515 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
517 printf("%s: Could not read endpoint " \
518 "descriptor for interface 1, " \
519 "alternate configuration %d, i=%d\n",
520 USBDEVNAME(sc->sc_dev), ai, i);
524 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
527 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
528 isoc_in = ed->bEndpointAddress;
529 isoc_isize = UGETW(ed->wMaxPacketSize);
531 isoc_out = ed->bEndpointAddress;
532 isoc_osize = UGETW(ed->wMaxPacketSize);
537 * Make sure that configuration looks sane and if so
538 * update current settings
541 if (isoc_in != -1 && isoc_out != -1 &&
542 isoc_isize > 0 && isoc_osize > 0 &&
543 isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
544 sc->sc_isoc_in_ep = isoc_in;
545 sc->sc_isoc_out_ep = isoc_out;
546 sc->sc_isoc_size = isoc_isize;
551 /* Check if we got everything we wanted on Interface 0 */
552 if (sc->sc_isoc_in_ep == -1) {
553 printf("%s: Could not detect isoc-in endpoint\n",
554 USBDEVNAME(sc->sc_dev));
557 if (sc->sc_isoc_out_ep == -1) {
558 printf("%s: Could not detect isoc-out endpoint\n",
559 USBDEVNAME(sc->sc_dev));
562 if (sc->sc_isoc_size <= 0) {
563 printf("%s: Invalid isoc. packet size=%d\n",
564 USBDEVNAME(sc->sc_dev), sc->sc_isoc_size);
568 error = usbd_set_interface(sc->sc_iface1, alt_no);
570 printf("%s: Could not set alternate configuration " \
571 "%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev),
572 alt_no, usbd_errstr(error), error);
576 /* Allocate USB transfer handles and buffers */
577 sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
578 if (sc->sc_ctrl_xfer == NULL) {
579 printf("%s: Could not allocate control xfer handle\n",
580 USBDEVNAME(sc->sc_dev));
583 sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
584 UBT_CTRL_BUFFER_SIZE);
585 if (sc->sc_ctrl_buffer == NULL) {
586 printf("%s: Could not allocate control buffer\n",
587 USBDEVNAME(sc->sc_dev));
591 sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
592 if (sc->sc_intr_xfer == NULL) {
593 printf("%s: Could not allocate interrupt xfer handle\n",
594 USBDEVNAME(sc->sc_dev));
598 sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
599 if (sc->sc_bulk_in_xfer == NULL) {
600 printf("%s: Could not allocate bulk-in xfer handle\n",
601 USBDEVNAME(sc->sc_dev));
605 sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
606 if (sc->sc_bulk_out_xfer == NULL) {
607 printf("%s: Could not allocate bulk-out xfer handle\n",
608 USBDEVNAME(sc->sc_dev));
611 sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
612 UBT_BULK_BUFFER_SIZE);
613 if (sc->sc_bulk_out_buffer == NULL) {
614 printf("%s: Could not allocate bulk-out buffer\n",
615 USBDEVNAME(sc->sc_dev));
620 * Allocate buffers for isoc. transfers
623 sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
625 sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
626 if (sc->sc_isoc_in_xfer == NULL) {
627 printf("%s: Could not allocate isoc-in xfer handle\n",
628 USBDEVNAME(sc->sc_dev));
631 sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
632 sc->sc_isoc_nframes * sc->sc_isoc_size);
633 if (sc->sc_isoc_in_buffer == NULL) {
634 printf("%s: Could not allocate isoc-in buffer\n",
635 USBDEVNAME(sc->sc_dev));
638 sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
640 if (sc->sc_isoc_in_frlen == NULL) {
641 printf("%s: Could not allocate isoc-in frame sizes buffer\n",
642 USBDEVNAME(sc->sc_dev));
646 sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
647 if (sc->sc_isoc_out_xfer == NULL) {
648 printf("%s: Could not allocate isoc-out xfer handle\n",
649 USBDEVNAME(sc->sc_dev));
652 sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
653 sc->sc_isoc_nframes * sc->sc_isoc_size);
654 if (sc->sc_isoc_out_buffer == NULL) {
655 printf("%s: Could not allocate isoc-out buffer\n",
656 USBDEVNAME(sc->sc_dev));
659 sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
661 if (sc->sc_isoc_out_frlen == NULL) {
662 printf("%s: Could not allocate isoc-out frame sizes buffer\n",
663 USBDEVNAME(sc->sc_dev));
667 printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
668 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
669 USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
670 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
671 (sc->sc_isoc_nframes * sc->sc_isoc_size));
678 error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
679 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
680 if (error != USBD_NORMAL_COMPLETION) {
681 printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
682 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
688 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
689 USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
690 if (error != USBD_NORMAL_COMPLETION) {
691 printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
692 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
698 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
699 USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
700 if (error != USBD_NORMAL_COMPLETION) {
701 printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
702 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
707 #if __broken__ /* XXX FIXME */
709 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
710 USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
711 if (error != USBD_NORMAL_COMPLETION) {
712 printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
713 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
719 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
720 USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
721 if (error != USBD_NORMAL_COMPLETION) {
722 printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
723 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
727 #endif /* __broken__ */
729 /* Create Netgraph node */
730 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
731 printf("%s: Could not create Netgraph node\n",
732 USBDEVNAME(sc->sc_dev));
738 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
739 printf("%s: Could not name Netgraph node\n",
740 USBDEVNAME(sc->sc_dev));
741 NG_NODE_UNREF(sc->sc_node);
746 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
747 NG_NODE_FORCE_WRITER(sc->sc_node);
749 /* Claim all interfaces on the device */
750 for (i = 0; i < uaa->nifaces; i++)
751 uaa->ifaces[i] = NULL;
753 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
756 USB_ATTACH_SUCCESS_RETURN;
760 USB_ATTACH_ERROR_RETURN;
761 } /* USB_ATTACH(ubt) */
769 USB_DETACH_START(ubt, sc);
771 /* Destroy Netgraph node */
772 if (sc->sc_node != NULL) {
773 NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
774 ng_rmnode_self(sc->sc_node);
779 if (sc->sc_intr_pipe != NULL) {
780 usbd_close_pipe(sc->sc_intr_pipe);
781 sc->sc_intr_pipe = NULL;
784 if (sc->sc_bulk_in_pipe != NULL) {
785 usbd_close_pipe(sc->sc_bulk_in_pipe);
786 sc->sc_bulk_in_pipe = NULL;
788 if (sc->sc_bulk_out_pipe != NULL) {
789 usbd_close_pipe(sc->sc_bulk_out_pipe);
790 sc->sc_bulk_out_pipe = NULL;
793 if (sc->sc_isoc_in_pipe != NULL) {
794 usbd_close_pipe(sc->sc_isoc_in_pipe);
795 sc->sc_isoc_in_pipe = NULL;
797 if (sc->sc_isoc_out_pipe != NULL) {
798 usbd_close_pipe(sc->sc_isoc_out_pipe);
799 sc->sc_isoc_out_pipe = NULL;
802 /* Destroy USB transfer handles */
803 if (sc->sc_ctrl_xfer != NULL) {
804 usbd_free_xfer(sc->sc_ctrl_xfer);
805 sc->sc_ctrl_xfer = NULL;
808 if (sc->sc_intr_xfer != NULL) {
809 usbd_free_xfer(sc->sc_intr_xfer);
810 sc->sc_intr_xfer = NULL;
813 if (sc->sc_bulk_in_xfer != NULL) {
814 usbd_free_xfer(sc->sc_bulk_in_xfer);
815 sc->sc_bulk_in_xfer = NULL;
817 if (sc->sc_bulk_out_xfer != NULL) {
818 usbd_free_xfer(sc->sc_bulk_out_xfer);
819 sc->sc_bulk_out_xfer = NULL;
822 if (sc->sc_isoc_in_xfer != NULL) {
823 usbd_free_xfer(sc->sc_isoc_in_xfer);
824 sc->sc_isoc_in_xfer = NULL;
826 if (sc->sc_isoc_out_xfer != NULL) {
827 usbd_free_xfer(sc->sc_isoc_out_xfer);
828 sc->sc_isoc_out_xfer = NULL;
831 /* Destroy isoc. frame size buffers */
832 if (sc->sc_isoc_in_frlen != NULL) {
833 free(sc->sc_isoc_in_frlen, M_USBDEV);
834 sc->sc_isoc_in_frlen = NULL;
836 if (sc->sc_isoc_out_frlen != NULL) {
837 free(sc->sc_isoc_out_frlen, M_USBDEV);
838 sc->sc_isoc_out_frlen = NULL;
842 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
843 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
844 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
846 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
850 } /* USB_DETACH(ubt) */
853 * Start USB control request (HCI command). Must be called with node locked
857 ubt_request_start(ubt_softc_p sc)
859 usb_device_request_t req;
860 struct mbuf *m = NULL;
863 KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
864 "%s: %s - Another control request is pending\n",
865 __func__, USBDEVNAME(sc->sc_dev)));
867 NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
870 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
872 return (USBD_NORMAL_COMPLETION);
876 * Check HCI command frame size and copy it back to
877 * linear USB transfer buffer.
880 if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
882 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
883 __func__, USBDEVNAME(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
886 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
888 /* Initialize a USB control request and then schedule it */
889 bzero(&req, sizeof(req));
890 req.bmRequestType = UBT_HCI_REQUEST;
891 USETW(req.wLength, m->m_pkthdr.len);
894 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
895 __func__, USBDEVNAME(sc->sc_dev), req.bmRequestType,
898 usbd_setup_default_xfer(
901 (usbd_private_handle) sc->sc_node,
902 USBD_DEFAULT_TIMEOUT, /* XXX */
907 ubt_request_complete);
909 NG_NODE_REF(sc->sc_node);
911 status = usbd_transfer(sc->sc_ctrl_xfer);
912 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
914 "%s: %s - Could not start control request. %s (%d)\n",
915 __func__, USBDEVNAME(sc->sc_dev),
916 usbd_errstr(status), status);
918 NG_NODE_UNREF(sc->sc_node);
920 NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
921 NG_UBT_STAT_OERROR(sc->sc_stat);
923 /* XXX FIXME should we try to resubmit another request? */
926 "%s: %s - Control request has been started\n",
927 __func__, USBDEVNAME(sc->sc_dev));
929 sc->sc_flags |= UBT_CMD_XMIT;
930 status = USBD_NORMAL_COMPLETION;
936 } /* ubt_request_start */
939 * USB control request callback
943 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
945 ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
946 NG_NODE_UNREF((node_p) p);
947 } /* ubt_request_complete */
950 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
952 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
953 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
954 usbd_status s = (usbd_status) arg2;
959 KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
960 "%s: %s - No control request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
962 sc->sc_flags &= ~UBT_CMD_XMIT;
964 if (s == USBD_CANCELLED) {
966 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
971 if (s != USBD_NORMAL_COMPLETION) {
973 "%s: %s - Control request failed. %s (%d)\n",
974 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
976 if (s == USBD_STALLED)
977 usbd_clear_endpoint_stall_async(h->pipe);
979 NG_UBT_STAT_OERROR(sc->sc_stat);
982 "%s: %s - Sent %d bytes to control pipe\n",
983 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
985 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
986 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
989 if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
990 ubt_request_start(sc);
991 } /* ubt_request_complete2 */
994 * Start interrupt transfer. Must be called when node is locked
998 ubt_intr_start(ubt_softc_p sc)
1000 struct mbuf *m = NULL;
1003 KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1004 "%s: %s - Another interrupt request is pending\n",
1005 __func__, USBDEVNAME(sc->sc_dev)));
1007 /* Allocate new mbuf cluster */
1008 MGETHDR(m, M_DONTWAIT, MT_DATA);
1010 return (USBD_NOMEM);
1012 MCLGET(m, M_DONTWAIT);
1013 if (!(m->m_flags & M_EXT)) {
1015 return (USBD_NOMEM);
1018 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1019 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1020 m->m_pkthdr.len = m->m_len = 1;
1022 m->m_pkthdr.len = m->m_len = 0;
1024 /* Initialize a USB transfer and then schedule it */
1028 (usbd_private_handle) sc->sc_node,
1029 (void *)(mtod(m, u_int8_t *) + m->m_len),
1030 MCLBYTES - m->m_len,
1035 NG_NODE_REF(sc->sc_node);
1037 status = usbd_transfer(sc->sc_intr_xfer);
1038 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1040 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1041 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1044 NG_NODE_UNREF(sc->sc_node);
1051 sc->sc_flags |= UBT_EVT_RECV;
1052 sc->sc_intr_buffer = m;
1054 return (USBD_NORMAL_COMPLETION);
1055 } /* ubt_intr_start */
1058 * Process interrupt from USB device (We got data from interrupt pipe)
1062 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1064 ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1065 NG_NODE_UNREF((node_p) p);
1066 } /* ubt_intr_complete */
1069 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1071 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1072 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1073 usbd_status s = (usbd_status) arg2;
1074 struct mbuf *m = NULL;
1075 ng_hci_event_pkt_t *hdr = NULL;
1081 KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1082 "%s: %s - No interrupt request is pending\n",
1083 __func__, USBDEVNAME(sc->sc_dev)));
1085 sc->sc_flags &= ~UBT_EVT_RECV;
1087 m = sc->sc_intr_buffer;
1088 sc->sc_intr_buffer = NULL;
1090 hdr = mtod(m, ng_hci_event_pkt_t *);
1092 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1094 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1100 if (s == USBD_CANCELLED) {
1102 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1108 if (s != USBD_NORMAL_COMPLETION) {
1110 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1111 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1113 if (s == USBD_STALLED)
1114 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1116 NG_UBT_STAT_IERROR(sc->sc_stat);
1119 return; /* XXX FIXME we should restart after some delay */
1122 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1123 m->m_pkthdr.len += h->actlen;
1124 m->m_len += h->actlen;
1127 "%s: %s - Got %d bytes from interrupt pipe\n",
1128 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1130 if (m->m_pkthdr.len < sizeof(*hdr)) {
1135 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1137 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1138 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1141 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1143 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1145 NG_UBT_STAT_IERROR(sc->sc_stat);
1148 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1149 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1152 NG_UBT_STAT_IERROR(sc->sc_stat);
1157 } /* ubt_intr_complete2 */
1160 * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1164 ubt_bulk_in_start(ubt_softc_p sc)
1166 struct mbuf *m = NULL;
1169 KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1170 "%s: %s - Another bulk-in request is pending\n",
1171 __func__, USBDEVNAME(sc->sc_dev)));
1173 /* Allocate new mbuf cluster */
1174 MGETHDR(m, M_DONTWAIT, MT_DATA);
1176 return (USBD_NOMEM);
1178 MCLGET(m, M_DONTWAIT);
1179 if (!(m->m_flags & M_EXT)) {
1181 return (USBD_NOMEM);
1184 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1185 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1186 m->m_pkthdr.len = m->m_len = 1;
1188 m->m_pkthdr.len = m->m_len = 0;
1190 /* Initialize a bulk-in USB transfer and then schedule it */
1192 sc->sc_bulk_in_xfer,
1193 sc->sc_bulk_in_pipe,
1194 (usbd_private_handle) sc->sc_node,
1195 (void *)(mtod(m, u_int8_t *) + m->m_len),
1196 MCLBYTES - m->m_len,
1199 ubt_bulk_in_complete);
1201 NG_NODE_REF(sc->sc_node);
1203 status = usbd_transfer(sc->sc_bulk_in_xfer);
1204 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1206 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1207 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1210 NG_NODE_UNREF(sc->sc_node);
1217 sc->sc_flags |= UBT_ACL_RECV;
1218 sc->sc_bulk_in_buffer = m;
1220 return (USBD_NORMAL_COMPLETION);
1221 } /* ubt_bulk_in_start */
1224 * USB bulk-in transfer callback
1228 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1230 ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1231 NG_NODE_UNREF((node_p) p);
1232 } /* ubt_bulk_in_complete */
1235 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1237 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1238 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1239 usbd_status s = (usbd_status) arg2;
1240 struct mbuf *m = NULL;
1241 ng_hci_acldata_pkt_t *hdr = NULL;
1247 KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1248 "%s: %s - No bulk-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1250 sc->sc_flags &= ~UBT_ACL_RECV;
1252 m = sc->sc_bulk_in_buffer;
1253 sc->sc_bulk_in_buffer = NULL;
1255 hdr = mtod(m, ng_hci_acldata_pkt_t *);
1257 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1259 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1265 if (s == USBD_CANCELLED) {
1267 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1268 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe);
1274 if (s != USBD_NORMAL_COMPLETION) {
1276 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1277 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1279 if (s == USBD_STALLED)
1280 usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1282 NG_UBT_STAT_IERROR(sc->sc_stat);
1285 return; /* XXX FIXME we should restart after some delay */
1288 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1289 m->m_pkthdr.len += h->actlen;
1290 m->m_len += h->actlen;
1293 "%s: %s - Got %d bytes from bulk-in pipe\n",
1294 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1296 if (m->m_pkthdr.len < sizeof(*hdr)) {
1301 len = le16toh(hdr->length);
1302 if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1304 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1305 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, len);
1307 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1309 NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1311 NG_UBT_STAT_IERROR(sc->sc_stat);
1314 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1315 __func__, USBDEVNAME(sc->sc_dev), len,
1318 NG_UBT_STAT_IERROR(sc->sc_stat);
1322 ubt_bulk_in_start(sc);
1323 } /* ubt_bulk_in_complete2 */
1326 * Start bulk-out USB transfer. Must be called with node locked
1330 ubt_bulk_out_start(ubt_softc_p sc)
1332 struct mbuf *m = NULL;
1335 KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1336 "%s: %s - Another bulk-out request is pending\n",
1337 __func__, USBDEVNAME(sc->sc_dev)));
1339 NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1342 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1344 return (USBD_NORMAL_COMPLETION);
1348 * Check ACL data frame size and copy it back to linear USB
1352 if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1354 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1355 __func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1358 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1360 /* Initialize a bulk-out USB transfer and then schedule it */
1362 sc->sc_bulk_out_xfer,
1363 sc->sc_bulk_out_pipe,
1364 (usbd_private_handle) sc->sc_node,
1365 sc->sc_bulk_out_buffer,
1368 USBD_DEFAULT_TIMEOUT, /* XXX */
1369 ubt_bulk_out_complete);
1371 NG_NODE_REF(sc->sc_node);
1373 status = usbd_transfer(sc->sc_bulk_out_xfer);
1374 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1376 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1377 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1380 NG_NODE_UNREF(sc->sc_node);
1382 NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1383 NG_UBT_STAT_OERROR(sc->sc_stat);
1385 /* XXX FIXME should we try to start another transfer? */
1388 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1389 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len);
1391 sc->sc_flags |= UBT_ACL_XMIT;
1392 status = USBD_NORMAL_COMPLETION;
1398 } /* ubt_bulk_out_start */
1401 * USB bulk-out transfer callback
1405 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1407 ng_send_fn((node_p) p, NULL, ubt_bulk_out_complete2, (void *) h, s);
1408 NG_NODE_UNREF((node_p) p);
1409 } /* ubt_bulk_out_complete */
1412 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1414 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1415 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1416 usbd_status s = (usbd_status) arg2;
1421 KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1422 "%s: %s - No bulk-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1424 sc->sc_flags &= ~UBT_ACL_XMIT;
1426 if (s == USBD_CANCELLED) {
1428 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1429 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_out_pipe);
1434 if (s != USBD_NORMAL_COMPLETION) {
1436 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1437 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1439 if (s == USBD_STALLED)
1440 usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1442 NG_UBT_STAT_OERROR(sc->sc_stat);
1445 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1446 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1448 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1449 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1452 if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1453 ubt_bulk_out_start(sc);
1454 } /* ubt_bulk_out_complete2 */
1457 * Start Isochronous-in USB transfer. Must be called with node locked
1461 ubt_isoc_in_start(ubt_softc_p sc)
1466 KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1467 "%s: %s - Another isoc-in request is pending\n",
1468 __func__, USBDEVNAME(sc->sc_dev)));
1470 /* Initialize a isoc-in USB transfer and then schedule it */
1471 for (i = 0; i < sc->sc_isoc_nframes; i++)
1472 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1474 usbd_setup_isoc_xfer(
1475 sc->sc_isoc_in_xfer,
1476 sc->sc_isoc_in_pipe,
1477 (usbd_private_handle) sc->sc_node,
1478 sc->sc_isoc_in_frlen,
1479 sc->sc_isoc_nframes,
1480 USBD_NO_COPY, /* XXX flags */
1481 ubt_isoc_in_complete);
1483 NG_NODE_REF(sc->sc_node);
1485 status = usbd_transfer(sc->sc_isoc_in_xfer);
1486 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1488 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1489 __func__, USBDEVNAME(sc->sc_dev),
1490 usbd_errstr(status), status);
1492 NG_NODE_UNREF(sc->sc_node);
1497 sc->sc_flags |= UBT_SCO_RECV;
1499 return (USBD_NORMAL_COMPLETION);
1500 } /* ubt_isoc_in_start */
1503 * USB isochronous transfer callback
1507 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1509 ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1510 NG_NODE_UNREF((node_p) p);
1511 } /* ubt_isoc_in_complete */
1514 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1516 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1517 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1518 usbd_status s = (usbd_status) arg2;
1519 struct mbuf *m = NULL;
1520 ng_hci_scodata_pkt_t *hdr = NULL;
1527 KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1528 "%s: %s - No isoc-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1530 sc->sc_flags &= ~UBT_SCO_RECV;
1532 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1534 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1539 if (s == USBD_CANCELLED) {
1541 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1542 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe);
1547 if (s != USBD_NORMAL_COMPLETION) {
1549 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1550 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1552 if (s == USBD_STALLED)
1553 usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1555 NG_UBT_STAT_IERROR(sc->sc_stat);
1557 return; /* XXX FIXME we should restart after some delay */
1560 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1563 "%s: %s - Got %d bytes from isoc-in pipe\n",
1564 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1566 /* Copy SCO data frame to mbuf */
1567 MGETHDR(m, M_DONTWAIT, MT_DATA);
1570 "%s: %s - Could not allocate mbuf\n",
1571 __func__, USBDEVNAME(sc->sc_dev));
1573 NG_UBT_STAT_IERROR(sc->sc_stat);
1577 /* Fix SCO data frame header if required */
1578 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1579 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1580 m->m_pkthdr.len = 1;
1581 m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1583 m->m_pkthdr.len = 0;
1584 m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1588 * XXX FIXME how do we know how many frames we have received?
1589 * XXX use frlen for now. is that correct?
1592 b = (u_int8_t *) sc->sc_isoc_in_buffer;
1594 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1595 b += (i * sc->sc_isoc_size);
1597 if (sc->sc_isoc_in_frlen[i] > 0)
1598 m_copyback(m, m->m_pkthdr.len,
1599 sc->sc_isoc_in_frlen[i], b);
1602 if (m->m_pkthdr.len < sizeof(*hdr))
1605 hdr = mtod(m, ng_hci_scodata_pkt_t *);
1607 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1609 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1610 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1613 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1615 NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1617 NG_UBT_STAT_IERROR(sc->sc_stat);
1620 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1621 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1624 NG_UBT_STAT_IERROR(sc->sc_stat);
1628 ubt_isoc_in_start(sc);
1629 } /* ubt_isoc_in_complete2 */
1632 * Start isochronous-out USB transfer. Must be called with node locked
1636 ubt_isoc_out_start(ubt_softc_p sc)
1638 struct mbuf *m = NULL;
1640 int i, len, nframes;
1643 KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1644 "%s: %s - Another isoc-out request is pending\n",
1645 __func__, USBDEVNAME(sc->sc_dev)));
1647 NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1650 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1652 return (USBD_NORMAL_COMPLETION);
1655 /* Copy entire SCO frame into USB transfer buffer and start transfer */
1656 b = (u_int8_t *) sc->sc_isoc_out_buffer;
1659 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1660 b += (i * sc->sc_isoc_size);
1662 len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1664 m_copydata(m, 0, len, b);
1669 sc->sc_isoc_out_frlen[i] = len;
1672 if (m->m_pkthdr.len > 0)
1674 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1675 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes,
1676 sc->sc_isoc_size, m->m_pkthdr.len);
1680 /* Initialize a isoc-out USB transfer and then schedule it */
1681 usbd_setup_isoc_xfer(
1682 sc->sc_isoc_out_xfer,
1683 sc->sc_isoc_out_pipe,
1684 (usbd_private_handle) sc->sc_node,
1685 sc->sc_isoc_out_frlen,
1688 ubt_isoc_out_complete);
1690 NG_NODE_REF(sc->sc_node);
1692 status = usbd_transfer(sc->sc_isoc_out_xfer);
1693 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1695 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1696 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1699 NG_NODE_UNREF(sc->sc_node);
1701 NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1702 NG_UBT_STAT_OERROR(sc->sc_stat);
1705 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1706 __func__, USBDEVNAME(sc->sc_dev), nframes,
1709 sc->sc_flags |= UBT_SCO_XMIT;
1710 status = USBD_NORMAL_COMPLETION;
1714 } /* ubt_isoc_out_start */
1717 * USB isoc-out. transfer callback
1721 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1723 ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1724 NG_NODE_UNREF((node_p) p);
1725 } /* ubt_isoc_out_complete */
1728 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1730 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1731 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1732 usbd_status s = (usbd_status) arg2;
1737 KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1738 "%s: %s - No isoc-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1740 sc->sc_flags &= ~UBT_SCO_XMIT;
1742 if (s == USBD_CANCELLED) {
1744 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1745 __func__, USBDEVNAME(sc->sc_dev),
1746 sc->sc_isoc_out_pipe);
1751 if (s != USBD_NORMAL_COMPLETION) {
1753 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1754 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1756 if (s == USBD_STALLED)
1757 usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1759 NG_UBT_STAT_OERROR(sc->sc_stat);
1762 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1763 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1765 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1766 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1769 if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1770 ubt_isoc_out_start(sc);
1771 } /* ubt_isoc_out_complete2 */
1774 * Abort transfers on all USB pipes
1778 ubt_reset(ubt_softc_p sc)
1781 if (sc->sc_intr_pipe != NULL)
1782 usbd_abort_pipe(sc->sc_intr_pipe);
1785 if (sc->sc_bulk_in_pipe != NULL)
1786 usbd_abort_pipe(sc->sc_bulk_in_pipe);
1787 if (sc->sc_bulk_out_pipe != NULL)
1788 usbd_abort_pipe(sc->sc_bulk_out_pipe);
1791 if (sc->sc_isoc_in_pipe != NULL)
1792 usbd_abort_pipe(sc->sc_isoc_in_pipe);
1793 if (sc->sc_isoc_out_pipe != NULL)
1794 usbd_abort_pipe(sc->sc_isoc_out_pipe);
1796 /* Cleanup queues */
1797 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1798 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1799 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1802 /****************************************************************************
1803 ****************************************************************************
1804 ** Netgraph specific
1805 ****************************************************************************
1806 ****************************************************************************/
1809 * Netgraph node constructor. Do not allow to create node of this type.
1813 ng_ubt_constructor(node_p node)
1816 } /* ng_ubt_constructor */
1819 * Netgraph node destructor. Destroy node only when device has been detached
1823 ng_ubt_shutdown(node_p node)
1825 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1827 /* Let old node go */
1828 NG_NODE_SET_PRIVATE(node, NULL);
1829 NG_NODE_UNREF(node);
1834 /* Create Netgraph node */
1835 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1836 printf("%s: Could not create Netgraph node\n",
1837 USBDEVNAME(sc->sc_dev));
1843 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
1844 printf("%s: Could not name Netgraph node\n",
1845 USBDEVNAME(sc->sc_dev));
1846 NG_NODE_UNREF(sc->sc_node);
1851 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1852 NG_NODE_FORCE_WRITER(sc->sc_node);
1855 } /* ng_ubt_shutdown */
1858 * Create new hook. There can only be one.
1862 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1864 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1866 if (strcmp(name, NG_UBT_HOOK) != 0)
1869 if (sc->sc_hook != NULL)
1875 } /* ng_ubt_newhook */
1878 * Connect hook. Start incoming USB transfers
1882 ng_ubt_connect(hook_p hook)
1884 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1887 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1889 /* Start intr transfer */
1890 status = ubt_intr_start(sc);
1891 if (status != USBD_NORMAL_COMPLETION) {
1893 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1894 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1899 /* Start bulk-in transfer */
1900 status = ubt_bulk_in_start(sc);
1901 if (status != USBD_NORMAL_COMPLETION) {
1903 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1904 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1909 #if __broken__ /* XXX FIXME */
1910 /* Start isoc-in transfer */
1911 status = ubt_isoc_in_start(sc);
1912 if (status != USBD_NORMAL_COMPLETION) {
1914 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1915 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1919 #endif /* __broken__ */
1927 } /* ng_ubt_connect */
1934 ng_ubt_disconnect(hook_p hook)
1936 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1939 if (hook != sc->sc_hook)
1947 } /* ng_ubt_disconnect */
1950 * Process control message
1954 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
1956 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1957 struct ng_mesg *msg = NULL, *rsp = NULL;
1958 struct ng_bt_mbufq *q = NULL;
1959 int error = 0, queue, qlen;
1966 NGI_GET_MSG(item, msg);
1968 switch (msg->header.typecookie) {
1969 case NGM_GENERIC_COOKIE:
1970 switch (msg->header.cmd) {
1971 case NGM_TEXT_STATUS:
1972 NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
1976 snprintf(rsp->data, NG_TEXTRESPONSE,
1980 "CMD queue: [have:%d,max:%d]\n" \
1981 "ACL queue: [have:%d,max:%d]\n" \
1982 "SCO queue: [have:%d,max:%d]",
1983 (sc->sc_hook != NULL)? NG_UBT_HOOK : "",
1986 NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
1988 NG_BT_MBUFQ_LEN(&sc->sc_aclq),
1990 NG_BT_MBUFQ_LEN(&sc->sc_scoq),
1991 sc->sc_scoq.maxlen);
2000 case NGM_UBT_COOKIE:
2001 switch (msg->header.cmd) {
2002 case NGM_UBT_NODE_SET_DEBUG:
2003 if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2007 *((ng_ubt_node_debug_ep *)(msg->data));
2010 case NGM_UBT_NODE_GET_DEBUG:
2011 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2016 *((ng_ubt_node_debug_ep *)(rsp->data)) =
2020 case NGM_UBT_NODE_SET_QLEN:
2021 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2024 queue = ((ng_ubt_node_qlen_ep *)
2025 (msg->data))->queue;
2026 qlen = ((ng_ubt_node_qlen_ep *)
2035 case NGM_UBT_NODE_QUEUE_CMD:
2039 case NGM_UBT_NODE_QUEUE_ACL:
2043 case NGM_UBT_NODE_QUEUE_SCO:
2058 case NGM_UBT_NODE_GET_QLEN:
2059 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2064 queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2066 case NGM_UBT_NODE_QUEUE_CMD:
2070 case NGM_UBT_NODE_QUEUE_ACL:
2074 case NGM_UBT_NODE_QUEUE_SCO:
2085 NG_MKRESPONSE(rsp, msg,
2086 sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
2092 ((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2094 ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2099 case NGM_UBT_NODE_GET_STAT:
2100 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2105 bcopy(&sc->sc_stat, rsp->data,
2106 sizeof(ng_ubt_node_stat_ep));
2109 case NGM_UBT_NODE_RESET_STAT:
2110 NG_UBT_STAT_RESET(sc->sc_stat);
2124 NG_RESPOND_MSG(error, node, item, rsp);
2128 } /* ng_ubt_rcvmsg */
2135 ng_ubt_rcvdata(hook_p hook, item_p item)
2137 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2138 struct mbuf *m = NULL;
2139 usbd_status (*f)(ubt_softc_p) = NULL;
2140 struct ng_bt_mbufq *q = NULL;
2148 if (hook != sc->sc_hook) {
2153 /* Deatch mbuf and get HCI frame type */
2156 /* Process HCI frame */
2157 switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2158 case NG_HCI_CMD_PKT:
2159 f = ubt_request_start;
2164 case NG_HCI_ACL_DATA_PKT:
2165 f = ubt_bulk_out_start;
2170 #if __broken__ /* XXX FIXME */
2171 case NG_HCI_SCO_DATA_PKT:
2172 f = ubt_isoc_out_start;
2176 #endif /* __broken__ */
2180 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2181 __func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *),
2191 /* Loose frame type, if required */
2192 if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2193 m_adj(m, sizeof(u_int8_t));
2195 if (NG_BT_MBUFQ_FULL(q)) {
2197 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2198 __func__, USBDEVNAME(sc->sc_dev),
2199 *mtod(m, u_int8_t *), m->m_pkthdr.len);
2203 NG_BT_MBUFQ_ENQUEUE(q, m);
2205 if (!(sc->sc_flags & b))
2206 if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2212 } /* ng_ubt_rcvdata */