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,
188 NGM_UBT_NODE_DEV_NODES,
190 &ng_parse_uint16_type,
196 /* Netgraph node type */
197 Static struct ng_type typestruct = {
198 .version = NG_ABI_VERSION,
199 .name = NG_UBT_NODE_TYPE,
200 .constructor = ng_ubt_constructor,
201 .rcvmsg = ng_ubt_rcvmsg,
202 .shutdown = ng_ubt_shutdown,
203 .newhook = ng_ubt_newhook,
204 .connect = ng_ubt_connect,
205 .rcvdata = ng_ubt_rcvdata,
206 .disconnect = ng_ubt_disconnect,
207 .cmdlist = ng_ubt_cmdlist
214 #define UBT_UNIT(n) ((minor(n) >> 4) & 0xf)
215 #define UBT_ENDPOINT(n) (minor(n) & 0xf)
216 #define UBT_MINOR(u, e) (((u) << 4) | (e))
217 #define UBT_BSIZE 1024
219 Static d_open_t ubt_open;
220 Static d_close_t ubt_close;
221 Static d_read_t ubt_read;
222 Static d_write_t ubt_write;
223 Static d_ioctl_t ubt_ioctl;
224 Static d_poll_t ubt_poll;
225 Static void ubt_create_device_nodes (ubt_softc_p);
226 Static void ubt_destroy_device_nodes (ubt_softc_p);
228 Static struct cdevsw ubt_cdevsw = {
229 .d_version = D_VERSION,
230 .d_flags = D_NEEDGIANT,
232 .d_close = ubt_close,
234 .d_write = ubt_write,
235 .d_ioctl = ubt_ioctl,
244 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
245 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
246 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
248 /****************************************************************************
249 ****************************************************************************
251 ****************************************************************************
252 ****************************************************************************/
255 * Load/Unload the driver module
259 ubt_modevent(module_t mod, int event, void *data)
265 error = ng_newtype(&typestruct);
268 "%s: Could not register Netgraph node type, error=%d\n",
269 NG_UBT_NODE_TYPE, error);
271 error = usbd_driver_load(mod, event, data);
275 error = ng_rmtype(&typestruct);
277 error = usbd_driver_load(mod, event, data);
289 * Probe for a USB Bluetooth device
295 * If for some reason device should not be attached then put
296 * VendorID/ProductID pair into the list below. Currently I
297 * do not know of any such devices. The format is as follows:
299 * { VENDOR_ID, PRODUCT_ID },
301 * where VENDOR_ID and PRODUCT_ID are hex numbers.
304 Static struct usb_devno const ubt_ignored_devices[] = {
305 { 0, 0 } /* This should be the last item in the list */
309 * If device violates Bluetooth specification and has bDeviceClass,
310 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
311 * could try to put VendorID/ProductID pair into the list below.
312 * Currently I do not know of any such devices.
315 Static struct usb_devno const ubt_broken_devices[] = {
316 { 0, 0 } /* This should be the last item in the list */
319 USB_MATCH_START(ubt, uaa);
321 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
323 if (uaa->iface == NULL ||
324 usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
325 return (UMATCH_NONE);
327 if (dd->bDeviceClass == UDCLASS_WIRELESS &&
328 dd->bDeviceSubClass == UDSUBCLASS_RF &&
329 dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
330 return (UMATCH_DEVCLASS_DEVSUBCLASS);
332 if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
333 return (UMATCH_VENDOR_PRODUCT);
335 return (UMATCH_NONE);
336 } /* USB_MATCH(ubt) */
344 USB_ATTACH_START(ubt, sc, uaa);
345 usb_config_descriptor_t *cd = NULL;
346 usb_interface_descriptor_t *id = NULL;
347 usb_endpoint_descriptor_t *ed = NULL;
348 char devinfo[UBT_BSIZE];
350 int i, ai, alt_no, isoc_in, isoc_out,
351 isoc_isize, isoc_osize;
353 /* Get USB device info */
354 sc->sc_udev = uaa->device;
355 usbd_devinfo(sc->sc_udev, 0, devinfo);
357 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
360 * Initialize device softc structure
364 sc->sc_debug = NG_UBT_WARN_LEVEL;
366 NG_UBT_STAT_RESET(sc->sc_stat);
369 sc->sc_iface0 = sc->sc_iface1 = NULL;
373 sc->sc_intr_pipe = NULL;
374 sc->sc_intr_xfer = NULL;
375 sc->sc_intr_buffer = NULL;
378 sc->sc_ctrl_xfer = NULL;
379 sc->sc_ctrl_buffer = NULL;
380 NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
383 sc->sc_bulk_in_ep = -1;
384 sc->sc_bulk_in_pipe = NULL;
385 sc->sc_bulk_in_xfer = NULL;
386 sc->sc_bulk_in_buffer = NULL;
389 sc->sc_bulk_out_ep = -1;
390 sc->sc_bulk_out_pipe = NULL;
391 sc->sc_bulk_out_xfer = NULL;
392 sc->sc_bulk_out_buffer = NULL;
393 NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
396 sc->sc_isoc_in_ep = -1;
397 sc->sc_isoc_in_pipe = NULL;
398 sc->sc_isoc_in_xfer = NULL;
401 sc->sc_isoc_out_ep = -1;
402 sc->sc_isoc_out_pipe = NULL;
403 sc->sc_isoc_out_xfer = NULL;
404 sc->sc_isoc_size = -1;
405 NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
412 sc->sc_ctrl_dev = sc->sc_intr_dev = sc->sc_bulk_dev = NULL;
413 sc->sc_refcnt = sc->sc_dying = 0;
416 * XXX set configuration?
418 * Configure Bluetooth USB device. Discover all required USB interfaces
421 * USB device must present two interfaces:
422 * 1) Interface 0 that has 3 endpoints
423 * 1) Interrupt endpoint to receive HCI events
424 * 2) Bulk IN endpoint to receive ACL data
425 * 3) Bulk OUT endpoint to send ACL data
427 * 2) Interface 1 then has 2 endpoints
428 * 1) Isochronous IN endpoint to receive SCO data
429 * 2) Isochronous OUT endpoint to send SCO data
431 * Interface 1 (with isochronous endpoints) has several alternate
432 * configurations with different packet size.
439 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
440 if (error || sc->sc_iface0 == NULL) {
441 printf("%s: Could not get interface 0 handle. %s (%d), " \
442 "handle=%p\n", USBDEVNAME(sc->sc_dev),
443 usbd_errstr(error), error, sc->sc_iface0);
447 id = usbd_get_interface_descriptor(sc->sc_iface0);
449 printf("%s: Could not get interface 0 descriptor\n",
450 USBDEVNAME(sc->sc_dev));
454 for (i = 0; i < id->bNumEndpoints; i ++) {
455 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
457 printf("%s: Could not read endpoint descriptor for " \
458 "interface 0, i=%d\n", USBDEVNAME(sc->sc_dev),
463 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
465 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
466 sc->sc_bulk_in_ep = ed->bEndpointAddress;
468 sc->sc_bulk_out_ep = ed->bEndpointAddress;
472 sc->sc_intr_ep = ed->bEndpointAddress;
477 /* Check if we got everything we wanted on Interface 0 */
478 if (sc->sc_intr_ep == -1) {
479 printf("%s: Could not detect interrupt endpoint\n",
480 USBDEVNAME(sc->sc_dev));
483 if (sc->sc_bulk_in_ep == -1) {
484 printf("%s: Could not detect bulk-in endpoint\n",
485 USBDEVNAME(sc->sc_dev));
488 if (sc->sc_bulk_out_ep == -1) {
489 printf("%s: Could not detect bulk-out endpoint\n",
490 USBDEVNAME(sc->sc_dev));
494 printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
495 "bulk-out=%#x\n", USBDEVNAME(sc->sc_dev),
496 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
502 cd = usbd_get_config_descriptor(sc->sc_udev);
504 printf("%s: Could not get device configuration descriptor\n",
505 USBDEVNAME(sc->sc_dev));
509 error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
510 if (error || sc->sc_iface1 == NULL) {
511 printf("%s: Could not get interface 1 handle. %s (%d), " \
512 "handle=%p\n", USBDEVNAME(sc->sc_dev),
513 usbd_errstr(error), error, sc->sc_iface1);
517 id = usbd_get_interface_descriptor(sc->sc_iface1);
519 printf("%s: Could not get interface 1 descriptor\n",
520 USBDEVNAME(sc->sc_dev));
525 * Scan all alternate configurations for interface 1
530 for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++) {
531 error = usbd_set_interface(sc->sc_iface1, ai);
533 printf("%s: [SCAN] Could not set alternate " \
534 "configuration %d for interface 1. %s (%d)\n",
535 USBDEVNAME(sc->sc_dev), ai, usbd_errstr(error),
539 id = usbd_get_interface_descriptor(sc->sc_iface1);
541 printf("%s: Could not get interface 1 descriptor for " \
542 "alternate configuration %d\n",
543 USBDEVNAME(sc->sc_dev), ai);
547 isoc_in = isoc_out = -1;
548 isoc_isize = isoc_osize = 0;
550 for (i = 0; i < id->bNumEndpoints; i ++) {
551 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
553 printf("%s: Could not read endpoint " \
554 "descriptor for interface 1, " \
555 "alternate configuration %d, i=%d\n",
556 USBDEVNAME(sc->sc_dev), ai, i);
560 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
563 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
564 isoc_in = ed->bEndpointAddress;
565 isoc_isize = UGETW(ed->wMaxPacketSize);
567 isoc_out = ed->bEndpointAddress;
568 isoc_osize = UGETW(ed->wMaxPacketSize);
573 * Make sure that configuration looks sane and if so
574 * update current settings
577 if (isoc_in != -1 && isoc_out != -1 &&
578 isoc_isize > 0 && isoc_osize > 0 &&
579 isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
580 sc->sc_isoc_in_ep = isoc_in;
581 sc->sc_isoc_out_ep = isoc_out;
582 sc->sc_isoc_size = isoc_isize;
587 /* Check if we got everything we wanted on Interface 0 */
588 if (sc->sc_isoc_in_ep == -1) {
589 printf("%s: Could not detect isoc-in endpoint\n",
590 USBDEVNAME(sc->sc_dev));
593 if (sc->sc_isoc_out_ep == -1) {
594 printf("%s: Could not detect isoc-out endpoint\n",
595 USBDEVNAME(sc->sc_dev));
598 if (sc->sc_isoc_size <= 0) {
599 printf("%s: Invalid isoc. packet size=%d\n",
600 USBDEVNAME(sc->sc_dev), sc->sc_isoc_size);
604 error = usbd_set_interface(sc->sc_iface1, alt_no);
606 printf("%s: Could not set alternate configuration " \
607 "%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev),
608 alt_no, usbd_errstr(error), error);
612 /* Allocate USB transfer handles and buffers */
613 sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
614 if (sc->sc_ctrl_xfer == NULL) {
615 printf("%s: Could not allocate control xfer handle\n",
616 USBDEVNAME(sc->sc_dev));
619 sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
620 UBT_CTRL_BUFFER_SIZE);
621 if (sc->sc_ctrl_buffer == NULL) {
622 printf("%s: Could not allocate control buffer\n",
623 USBDEVNAME(sc->sc_dev));
627 sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
628 if (sc->sc_intr_xfer == NULL) {
629 printf("%s: Could not allocate interrupt xfer handle\n",
630 USBDEVNAME(sc->sc_dev));
634 sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
635 if (sc->sc_bulk_in_xfer == NULL) {
636 printf("%s: Could not allocate bulk-in xfer handle\n",
637 USBDEVNAME(sc->sc_dev));
641 sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
642 if (sc->sc_bulk_out_xfer == NULL) {
643 printf("%s: Could not allocate bulk-out xfer handle\n",
644 USBDEVNAME(sc->sc_dev));
647 sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
648 UBT_BULK_BUFFER_SIZE);
649 if (sc->sc_bulk_out_buffer == NULL) {
650 printf("%s: Could not allocate bulk-out buffer\n",
651 USBDEVNAME(sc->sc_dev));
656 * Allocate buffers for isoc. transfers
659 sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
661 sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
662 if (sc->sc_isoc_in_xfer == NULL) {
663 printf("%s: Could not allocate isoc-in xfer handle\n",
664 USBDEVNAME(sc->sc_dev));
667 sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
668 sc->sc_isoc_nframes * sc->sc_isoc_size);
669 if (sc->sc_isoc_in_buffer == NULL) {
670 printf("%s: Could not allocate isoc-in buffer\n",
671 USBDEVNAME(sc->sc_dev));
674 sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
676 if (sc->sc_isoc_in_frlen == NULL) {
677 printf("%s: Could not allocate isoc-in frame sizes buffer\n",
678 USBDEVNAME(sc->sc_dev));
682 sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
683 if (sc->sc_isoc_out_xfer == NULL) {
684 printf("%s: Could not allocate isoc-out xfer handle\n",
685 USBDEVNAME(sc->sc_dev));
688 sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
689 sc->sc_isoc_nframes * sc->sc_isoc_size);
690 if (sc->sc_isoc_out_buffer == NULL) {
691 printf("%s: Could not allocate isoc-out buffer\n",
692 USBDEVNAME(sc->sc_dev));
695 sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
697 if (sc->sc_isoc_out_frlen == NULL) {
698 printf("%s: Could not allocate isoc-out frame sizes buffer\n",
699 USBDEVNAME(sc->sc_dev));
703 printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
704 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
705 USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
706 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
707 (sc->sc_isoc_nframes * sc->sc_isoc_size));
714 error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
715 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
716 if (error != USBD_NORMAL_COMPLETION) {
717 printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
718 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
724 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
725 USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
726 if (error != USBD_NORMAL_COMPLETION) {
727 printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
728 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
734 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
735 USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
736 if (error != USBD_NORMAL_COMPLETION) {
737 printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
738 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
743 #if __broken__ /* XXX FIXME */
745 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
746 USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
747 if (error != USBD_NORMAL_COMPLETION) {
748 printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
749 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
755 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
756 USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
757 if (error != USBD_NORMAL_COMPLETION) {
758 printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
759 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
763 #endif /* __broken__ */
765 /* Create Netgraph node */
766 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
767 printf("%s: Could not create Netgraph node\n",
768 USBDEVNAME(sc->sc_dev));
774 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
775 printf("%s: Could not name Netgraph node\n",
776 USBDEVNAME(sc->sc_dev));
777 NG_NODE_UNREF(sc->sc_node);
782 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
783 NG_NODE_FORCE_WRITER(sc->sc_node);
785 /* Claim all interfaces on the device */
786 for (i = 0; i < uaa->nifaces; i++)
787 uaa->ifaces[i] = NULL;
789 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
792 USB_ATTACH_SUCCESS_RETURN;
796 USB_ATTACH_ERROR_RETURN;
797 } /* USB_ATTACH(ubt) */
805 USB_DETACH_START(ubt, sc);
809 ubt_destroy_device_nodes(sc); /* XXX FIXME locking? */
811 /* Destroy Netgraph node */
812 if (sc->sc_node != NULL) {
813 NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
814 ng_rmnode_self(sc->sc_node);
819 if (sc->sc_intr_pipe != NULL) {
820 usbd_close_pipe(sc->sc_intr_pipe);
821 sc->sc_intr_pipe = NULL;
824 if (sc->sc_bulk_in_pipe != NULL) {
825 usbd_close_pipe(sc->sc_bulk_in_pipe);
826 sc->sc_bulk_in_pipe = NULL;
828 if (sc->sc_bulk_out_pipe != NULL) {
829 usbd_close_pipe(sc->sc_bulk_out_pipe);
830 sc->sc_bulk_out_pipe = NULL;
833 if (sc->sc_isoc_in_pipe != NULL) {
834 usbd_close_pipe(sc->sc_isoc_in_pipe);
835 sc->sc_isoc_in_pipe = NULL;
837 if (sc->sc_isoc_out_pipe != NULL) {
838 usbd_close_pipe(sc->sc_isoc_out_pipe);
839 sc->sc_isoc_out_pipe = NULL;
842 /* Destroy USB transfer handles */
843 if (sc->sc_ctrl_xfer != NULL) {
844 usbd_free_xfer(sc->sc_ctrl_xfer);
845 sc->sc_ctrl_xfer = NULL;
848 if (sc->sc_intr_xfer != NULL) {
849 usbd_free_xfer(sc->sc_intr_xfer);
850 sc->sc_intr_xfer = NULL;
853 if (sc->sc_bulk_in_xfer != NULL) {
854 usbd_free_xfer(sc->sc_bulk_in_xfer);
855 sc->sc_bulk_in_xfer = NULL;
857 if (sc->sc_bulk_out_xfer != NULL) {
858 usbd_free_xfer(sc->sc_bulk_out_xfer);
859 sc->sc_bulk_out_xfer = NULL;
862 if (sc->sc_isoc_in_xfer != NULL) {
863 usbd_free_xfer(sc->sc_isoc_in_xfer);
864 sc->sc_isoc_in_xfer = NULL;
866 if (sc->sc_isoc_out_xfer != NULL) {
867 usbd_free_xfer(sc->sc_isoc_out_xfer);
868 sc->sc_isoc_out_xfer = NULL;
871 /* Destroy isoc. frame size buffers */
872 if (sc->sc_isoc_in_frlen != NULL) {
873 free(sc->sc_isoc_in_frlen, M_USBDEV);
874 sc->sc_isoc_in_frlen = NULL;
876 if (sc->sc_isoc_out_frlen != NULL) {
877 free(sc->sc_isoc_out_frlen, M_USBDEV);
878 sc->sc_isoc_out_frlen = NULL;
882 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
883 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
884 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
886 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
890 } /* USB_DETACH(ubt) */
893 * Start USB control request (HCI command). Must be called with node locked
897 ubt_request_start(ubt_softc_p sc)
899 usb_device_request_t req;
900 struct mbuf *m = NULL;
903 KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
904 "%s: %s - Another control request is pending\n",
905 __func__, USBDEVNAME(sc->sc_dev)));
907 NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
910 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
912 return (USBD_NORMAL_COMPLETION);
916 * Check HCI command frame size and copy it back to
917 * linear USB transfer buffer.
920 if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
922 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
923 __func__, USBDEVNAME(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
926 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
928 /* Initialize a USB control request and then schedule it */
929 bzero(&req, sizeof(req));
930 req.bmRequestType = UBT_HCI_REQUEST;
931 USETW(req.wLength, m->m_pkthdr.len);
934 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
935 __func__, USBDEVNAME(sc->sc_dev), req.bmRequestType,
938 usbd_setup_default_xfer(
941 (usbd_private_handle) sc->sc_node,
942 USBD_DEFAULT_TIMEOUT, /* XXX */
947 ubt_request_complete);
949 NG_NODE_REF(sc->sc_node);
951 status = usbd_transfer(sc->sc_ctrl_xfer);
952 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
954 "%s: %s - Could not start control request. %s (%d)\n",
955 __func__, USBDEVNAME(sc->sc_dev),
956 usbd_errstr(status), status);
958 NG_NODE_UNREF(sc->sc_node);
960 NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
961 NG_UBT_STAT_OERROR(sc->sc_stat);
963 /* XXX FIXME should we try to resubmit another request? */
966 "%s: %s - Control request has been started\n",
967 __func__, USBDEVNAME(sc->sc_dev));
969 sc->sc_flags |= UBT_CMD_XMIT;
970 status = USBD_NORMAL_COMPLETION;
976 } /* ubt_request_start */
979 * USB control request callback
983 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
985 ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
986 NG_NODE_UNREF((node_p) p);
987 } /* ubt_request_complete */
990 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
992 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
993 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
994 usbd_status s = (usbd_status) arg2;
999 KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
1000 "%s: %s - No control request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1002 sc->sc_flags &= ~UBT_CMD_XMIT;
1004 if (s == USBD_CANCELLED) {
1006 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1011 if (s != USBD_NORMAL_COMPLETION) {
1013 "%s: %s - Control request failed. %s (%d)\n",
1014 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1016 if (s == USBD_STALLED)
1017 usbd_clear_endpoint_stall_async(h->pipe);
1019 NG_UBT_STAT_OERROR(sc->sc_stat);
1022 "%s: %s - Sent %d bytes to control pipe\n",
1023 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1025 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1026 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1029 if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
1030 ubt_request_start(sc);
1031 } /* ubt_request_complete2 */
1034 * Start interrupt transfer. Must be called when node is locked
1038 ubt_intr_start(ubt_softc_p sc)
1040 struct mbuf *m = NULL;
1043 KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1044 "%s: %s - Another interrupt request is pending\n",
1045 __func__, USBDEVNAME(sc->sc_dev)));
1047 /* Allocate new mbuf cluster */
1048 MGETHDR(m, M_DONTWAIT, MT_DATA);
1050 return (USBD_NOMEM);
1052 MCLGET(m, M_DONTWAIT);
1053 if (!(m->m_flags & M_EXT)) {
1055 return (USBD_NOMEM);
1058 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1059 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1060 m->m_pkthdr.len = m->m_len = 1;
1062 m->m_pkthdr.len = m->m_len = 0;
1064 /* Initialize a USB transfer and then schedule it */
1068 (usbd_private_handle) sc->sc_node,
1069 (void *)(mtod(m, u_int8_t *) + m->m_len),
1070 MCLBYTES - m->m_len,
1075 NG_NODE_REF(sc->sc_node);
1077 status = usbd_transfer(sc->sc_intr_xfer);
1078 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1080 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1081 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1084 NG_NODE_UNREF(sc->sc_node);
1091 sc->sc_flags |= UBT_EVT_RECV;
1092 sc->sc_intr_buffer = m;
1094 return (USBD_NORMAL_COMPLETION);
1095 } /* ubt_intr_start */
1098 * Process interrupt from USB device (We got data from interrupt pipe)
1102 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1104 ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1105 NG_NODE_UNREF((node_p) p);
1106 } /* ubt_intr_complete */
1109 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1111 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1112 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1113 usbd_status s = (usbd_status) arg2;
1114 struct mbuf *m = NULL;
1115 ng_hci_event_pkt_t *hdr = NULL;
1121 KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1122 "%s: %s - No interrupt request is pending\n",
1123 __func__, USBDEVNAME(sc->sc_dev)));
1125 sc->sc_flags &= ~UBT_EVT_RECV;
1127 m = sc->sc_intr_buffer;
1128 sc->sc_intr_buffer = NULL;
1130 hdr = mtod(m, ng_hci_event_pkt_t *);
1132 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1134 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1140 if (s == USBD_CANCELLED) {
1142 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1148 if (s != USBD_NORMAL_COMPLETION) {
1150 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1151 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1153 if (s == USBD_STALLED)
1154 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1156 NG_UBT_STAT_IERROR(sc->sc_stat);
1159 return; /* XXX FIXME we should restart after some delay */
1162 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1163 m->m_pkthdr.len += h->actlen;
1164 m->m_len += h->actlen;
1167 "%s: %s - Got %d bytes from interrupt pipe\n",
1168 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1170 if (m->m_pkthdr.len < sizeof(*hdr)) {
1175 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1177 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1178 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1181 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1183 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1185 NG_UBT_STAT_IERROR(sc->sc_stat);
1188 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1189 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1192 NG_UBT_STAT_IERROR(sc->sc_stat);
1197 } /* ubt_intr_complete2 */
1200 * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1204 ubt_bulk_in_start(ubt_softc_p sc)
1206 struct mbuf *m = NULL;
1209 KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1210 "%s: %s - Another bulk-in request is pending\n",
1211 __func__, USBDEVNAME(sc->sc_dev)));
1213 /* Allocate new mbuf cluster */
1214 MGETHDR(m, M_DONTWAIT, MT_DATA);
1216 return (USBD_NOMEM);
1218 MCLGET(m, M_DONTWAIT);
1219 if (!(m->m_flags & M_EXT)) {
1221 return (USBD_NOMEM);
1224 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1225 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1226 m->m_pkthdr.len = m->m_len = 1;
1228 m->m_pkthdr.len = m->m_len = 0;
1230 /* Initialize a bulk-in USB transfer and then schedule it */
1232 sc->sc_bulk_in_xfer,
1233 sc->sc_bulk_in_pipe,
1234 (usbd_private_handle) sc->sc_node,
1235 (void *)(mtod(m, u_int8_t *) + m->m_len),
1236 MCLBYTES - m->m_len,
1239 ubt_bulk_in_complete);
1241 NG_NODE_REF(sc->sc_node);
1243 status = usbd_transfer(sc->sc_bulk_in_xfer);
1244 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1246 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1247 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1250 NG_NODE_UNREF(sc->sc_node);
1257 sc->sc_flags |= UBT_ACL_RECV;
1258 sc->sc_bulk_in_buffer = m;
1260 return (USBD_NORMAL_COMPLETION);
1261 } /* ubt_bulk_in_start */
1264 * USB bulk-in transfer callback
1268 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1270 ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1271 NG_NODE_UNREF((node_p) p);
1272 } /* ubt_bulk_in_complete */
1275 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1277 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1278 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1279 usbd_status s = (usbd_status) arg2;
1280 struct mbuf *m = NULL;
1281 ng_hci_acldata_pkt_t *hdr = NULL;
1287 KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1288 "%s: %s - No bulk-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1290 sc->sc_flags &= ~UBT_ACL_RECV;
1292 m = sc->sc_bulk_in_buffer;
1293 sc->sc_bulk_in_buffer = NULL;
1295 hdr = mtod(m, ng_hci_acldata_pkt_t *);
1297 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1299 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1305 if (s == USBD_CANCELLED) {
1307 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1308 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe);
1314 if (s != USBD_NORMAL_COMPLETION) {
1316 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1317 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1319 if (s == USBD_STALLED)
1320 usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1322 NG_UBT_STAT_IERROR(sc->sc_stat);
1325 return; /* XXX FIXME we should restart after some delay */
1328 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1329 m->m_pkthdr.len += h->actlen;
1330 m->m_len += h->actlen;
1333 "%s: %s - Got %d bytes from bulk-in pipe\n",
1334 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1336 if (m->m_pkthdr.len < sizeof(*hdr)) {
1341 len = le16toh(hdr->length);
1342 if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1344 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1345 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, len);
1347 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1349 NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1351 NG_UBT_STAT_IERROR(sc->sc_stat);
1354 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1355 __func__, USBDEVNAME(sc->sc_dev), len,
1358 NG_UBT_STAT_IERROR(sc->sc_stat);
1362 ubt_bulk_in_start(sc);
1363 } /* ubt_bulk_in_complete2 */
1366 * Start bulk-out USB transfer. Must be called with node locked
1370 ubt_bulk_out_start(ubt_softc_p sc)
1372 struct mbuf *m = NULL;
1375 KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1376 "%s: %s - Another bulk-out request is pending\n",
1377 __func__, USBDEVNAME(sc->sc_dev)));
1379 NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1382 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1384 return (USBD_NORMAL_COMPLETION);
1388 * Check ACL data frame size and copy it back to linear USB
1392 if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1394 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1395 __func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1398 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1400 /* Initialize a bulk-out USB transfer and then schedule it */
1402 sc->sc_bulk_out_xfer,
1403 sc->sc_bulk_out_pipe,
1404 (usbd_private_handle) sc->sc_node,
1405 sc->sc_bulk_out_buffer,
1408 USBD_DEFAULT_TIMEOUT, /* XXX */
1409 ubt_bulk_out_complete);
1411 NG_NODE_REF(sc->sc_node);
1413 status = usbd_transfer(sc->sc_bulk_out_xfer);
1414 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1416 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1417 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1420 NG_NODE_UNREF(sc->sc_node);
1422 NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1423 NG_UBT_STAT_OERROR(sc->sc_stat);
1425 /* XXX FIXME should we try to start another transfer? */
1428 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1429 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len);
1431 sc->sc_flags |= UBT_ACL_XMIT;
1432 status = USBD_NORMAL_COMPLETION;
1438 } /* ubt_bulk_out_start */
1441 * USB bulk-out transfer callback
1445 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1447 ng_send_fn((node_p) p, NULL, ubt_bulk_out_complete2, (void *) h, s);
1448 NG_NODE_UNREF((node_p) p);
1449 } /* ubt_bulk_out_complete */
1452 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1454 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1455 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1456 usbd_status s = (usbd_status) arg2;
1461 KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1462 "%s: %s - No bulk-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1464 sc->sc_flags &= ~UBT_ACL_XMIT;
1466 if (s == USBD_CANCELLED) {
1468 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1469 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_out_pipe);
1474 if (s != USBD_NORMAL_COMPLETION) {
1476 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1477 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1479 if (s == USBD_STALLED)
1480 usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1482 NG_UBT_STAT_OERROR(sc->sc_stat);
1485 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1486 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1488 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1489 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1492 if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1493 ubt_bulk_out_start(sc);
1494 } /* ubt_bulk_out_complete2 */
1497 * Start Isochronous-in USB transfer. Must be called with node locked
1501 ubt_isoc_in_start(ubt_softc_p sc)
1506 KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1507 "%s: %s - Another isoc-in request is pending\n",
1508 __func__, USBDEVNAME(sc->sc_dev)));
1510 /* Initialize a isoc-in USB transfer and then schedule it */
1511 for (i = 0; i < sc->sc_isoc_nframes; i++)
1512 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1514 usbd_setup_isoc_xfer(
1515 sc->sc_isoc_in_xfer,
1516 sc->sc_isoc_in_pipe,
1517 (usbd_private_handle) sc->sc_node,
1518 sc->sc_isoc_in_frlen,
1519 sc->sc_isoc_nframes,
1520 USBD_NO_COPY, /* XXX flags */
1521 ubt_isoc_in_complete);
1523 NG_NODE_REF(sc->sc_node);
1525 status = usbd_transfer(sc->sc_isoc_in_xfer);
1526 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1528 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1529 __func__, USBDEVNAME(sc->sc_dev),
1530 usbd_errstr(status), status);
1532 NG_NODE_UNREF(sc->sc_node);
1537 sc->sc_flags |= UBT_SCO_RECV;
1539 return (USBD_NORMAL_COMPLETION);
1540 } /* ubt_isoc_in_start */
1543 * USB isochronous transfer callback
1547 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1549 ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1550 NG_NODE_UNREF((node_p) p);
1551 } /* ubt_isoc_in_complete */
1554 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1556 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1557 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1558 usbd_status s = (usbd_status) arg2;
1559 struct mbuf *m = NULL;
1560 ng_hci_scodata_pkt_t *hdr = NULL;
1567 KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1568 "%s: %s - No isoc-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1570 sc->sc_flags &= ~UBT_SCO_RECV;
1572 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1574 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1579 if (s == USBD_CANCELLED) {
1581 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1582 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe);
1587 if (s != USBD_NORMAL_COMPLETION) {
1589 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1590 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1592 if (s == USBD_STALLED)
1593 usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1595 NG_UBT_STAT_IERROR(sc->sc_stat);
1597 return; /* XXX FIXME we should restart after some delay */
1600 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1603 "%s: %s - Got %d bytes from isoc-in pipe\n",
1604 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1606 /* Copy SCO data frame to mbuf */
1607 MGETHDR(m, M_DONTWAIT, MT_DATA);
1610 "%s: %s - Could not allocate mbuf\n",
1611 __func__, USBDEVNAME(sc->sc_dev));
1613 NG_UBT_STAT_IERROR(sc->sc_stat);
1617 /* Fix SCO data frame header if required */
1618 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1619 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1620 m->m_pkthdr.len = 1;
1621 m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1623 m->m_pkthdr.len = 0;
1624 m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1628 * XXX FIXME how do we know how many frames we have received?
1629 * XXX use frlen for now. is that correct?
1632 b = (u_int8_t *) sc->sc_isoc_in_buffer;
1634 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1635 b += (i * sc->sc_isoc_size);
1637 if (sc->sc_isoc_in_frlen[i] > 0)
1638 m_copyback(m, m->m_pkthdr.len,
1639 sc->sc_isoc_in_frlen[i], b);
1642 if (m->m_pkthdr.len < sizeof(*hdr))
1645 hdr = mtod(m, ng_hci_scodata_pkt_t *);
1647 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1649 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1650 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1653 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1655 NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1657 NG_UBT_STAT_IERROR(sc->sc_stat);
1660 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1661 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1664 NG_UBT_STAT_IERROR(sc->sc_stat);
1668 ubt_isoc_in_start(sc);
1669 } /* ubt_isoc_in_complete2 */
1672 * Start isochronous-out USB transfer. Must be called with node locked
1676 ubt_isoc_out_start(ubt_softc_p sc)
1678 struct mbuf *m = NULL;
1680 int i, len, nframes;
1683 KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1684 "%s: %s - Another isoc-out request is pending\n",
1685 __func__, USBDEVNAME(sc->sc_dev)));
1687 NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1690 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1692 return (USBD_NORMAL_COMPLETION);
1695 /* Copy entire SCO frame into USB transfer buffer and start transfer */
1696 b = (u_int8_t *) sc->sc_isoc_out_buffer;
1699 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1700 b += (i * sc->sc_isoc_size);
1702 len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1704 m_copydata(m, 0, len, b);
1709 sc->sc_isoc_out_frlen[i] = len;
1712 if (m->m_pkthdr.len > 0)
1714 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1715 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes,
1716 sc->sc_isoc_size, m->m_pkthdr.len);
1720 /* Initialize a isoc-out USB transfer and then schedule it */
1721 usbd_setup_isoc_xfer(
1722 sc->sc_isoc_out_xfer,
1723 sc->sc_isoc_out_pipe,
1724 (usbd_private_handle) sc->sc_node,
1725 sc->sc_isoc_out_frlen,
1728 ubt_isoc_out_complete);
1730 NG_NODE_REF(sc->sc_node);
1732 status = usbd_transfer(sc->sc_isoc_out_xfer);
1733 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1735 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1736 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1739 NG_NODE_UNREF(sc->sc_node);
1741 NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1742 NG_UBT_STAT_OERROR(sc->sc_stat);
1745 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1746 __func__, USBDEVNAME(sc->sc_dev), nframes,
1749 sc->sc_flags |= UBT_SCO_XMIT;
1750 status = USBD_NORMAL_COMPLETION;
1754 } /* ubt_isoc_out_start */
1757 * USB isoc-out. transfer callback
1761 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1763 ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1764 NG_NODE_UNREF((node_p) p);
1765 } /* ubt_isoc_out_complete */
1768 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1770 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1771 usbd_xfer_handle h = (usbd_xfer_handle) arg1;
1772 usbd_status s = (usbd_status) arg2;
1777 KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1778 "%s: %s - No isoc-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1780 sc->sc_flags &= ~UBT_SCO_XMIT;
1782 if (s == USBD_CANCELLED) {
1784 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1785 __func__, USBDEVNAME(sc->sc_dev),
1786 sc->sc_isoc_out_pipe);
1791 if (s != USBD_NORMAL_COMPLETION) {
1793 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1794 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1796 if (s == USBD_STALLED)
1797 usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1799 NG_UBT_STAT_OERROR(sc->sc_stat);
1802 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1803 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1805 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1806 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1809 if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1810 ubt_isoc_out_start(sc);
1811 } /* ubt_isoc_out_complete2 */
1814 * Abort transfers on all USB pipes
1818 ubt_reset(ubt_softc_p sc)
1821 if (sc->sc_intr_pipe != NULL)
1822 usbd_abort_pipe(sc->sc_intr_pipe);
1825 if (sc->sc_bulk_in_pipe != NULL)
1826 usbd_abort_pipe(sc->sc_bulk_in_pipe);
1827 if (sc->sc_bulk_out_pipe != NULL)
1828 usbd_abort_pipe(sc->sc_bulk_out_pipe);
1831 if (sc->sc_isoc_in_pipe != NULL)
1832 usbd_abort_pipe(sc->sc_isoc_in_pipe);
1833 if (sc->sc_isoc_out_pipe != NULL)
1834 usbd_abort_pipe(sc->sc_isoc_out_pipe);
1836 /* Cleanup queues */
1837 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1838 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1839 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1842 /****************************************************************************
1843 ****************************************************************************
1844 ** Netgraph specific
1845 ****************************************************************************
1846 ****************************************************************************/
1849 * Netgraph node constructor. Do not allow to create node of this type.
1853 ng_ubt_constructor(node_p node)
1856 } /* ng_ubt_constructor */
1859 * Netgraph node destructor. Destroy node only when device has been detached
1863 ng_ubt_shutdown(node_p node)
1865 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1867 /* Let old node go */
1868 NG_NODE_SET_PRIVATE(node, NULL);
1869 NG_NODE_UNREF(node);
1874 /* Create Netgraph node */
1875 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1876 printf("%s: Could not create Netgraph node\n",
1877 USBDEVNAME(sc->sc_dev));
1883 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
1884 printf("%s: Could not name Netgraph node\n",
1885 USBDEVNAME(sc->sc_dev));
1886 NG_NODE_UNREF(sc->sc_node);
1891 NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1892 NG_NODE_FORCE_WRITER(sc->sc_node);
1895 } /* ng_ubt_shutdown */
1898 * Create new hook. There can only be one.
1902 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1904 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1906 /* Refuse to create new hook if device interface is active */
1907 if (sc->sc_ctrl_dev != NULL || sc->sc_intr_dev != NULL ||
1908 sc->sc_bulk_dev != NULL)
1911 if (strcmp(name, NG_UBT_HOOK) != 0)
1914 if (sc->sc_hook != NULL)
1920 } /* ng_ubt_newhook */
1923 * Connect hook. Start incoming USB transfers
1927 ng_ubt_connect(hook_p hook)
1929 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1932 /* Refuse to connect hook if device interface is active */
1933 if (sc->sc_ctrl_dev != NULL || sc->sc_intr_dev != NULL ||
1934 sc->sc_bulk_dev != NULL)
1937 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1939 /* Start intr transfer */
1940 status = ubt_intr_start(sc);
1941 if (status != USBD_NORMAL_COMPLETION) {
1943 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1944 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1949 /* Start bulk-in transfer */
1950 status = ubt_bulk_in_start(sc);
1951 if (status != USBD_NORMAL_COMPLETION) {
1953 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1954 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1959 #if __broken__ /* XXX FIXME */
1960 /* Start isoc-in transfer */
1961 status = ubt_isoc_in_start(sc);
1962 if (status != USBD_NORMAL_COMPLETION) {
1964 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1965 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1969 #endif /* __broken__ */
1977 } /* ng_ubt_connect */
1984 ng_ubt_disconnect(hook_p hook)
1986 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1989 if (hook != sc->sc_hook)
1997 } /* ng_ubt_disconnect */
2000 * Process control message
2004 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
2006 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
2007 struct ng_mesg *msg = NULL, *rsp = NULL;
2008 struct ng_bt_mbufq *q = NULL;
2009 int error = 0, queue, qlen;
2016 NGI_GET_MSG(item, msg);
2018 switch (msg->header.typecookie) {
2019 case NGM_GENERIC_COOKIE:
2020 switch (msg->header.cmd) {
2021 case NGM_TEXT_STATUS:
2022 NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
2026 snprintf(rsp->data, NG_TEXTRESPONSE,
2030 "CMD queue: [have:%d,max:%d]\n" \
2031 "ACL queue: [have:%d,max:%d]\n" \
2032 "SCO queue: [have:%d,max:%d]",
2033 (sc->sc_hook != NULL)? NG_UBT_HOOK : "",
2036 NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
2038 NG_BT_MBUFQ_LEN(&sc->sc_aclq),
2040 NG_BT_MBUFQ_LEN(&sc->sc_scoq),
2041 sc->sc_scoq.maxlen);
2050 case NGM_UBT_COOKIE:
2051 switch (msg->header.cmd) {
2052 case NGM_UBT_NODE_SET_DEBUG:
2053 if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2057 *((ng_ubt_node_debug_ep *)(msg->data));
2060 case NGM_UBT_NODE_GET_DEBUG:
2061 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2066 *((ng_ubt_node_debug_ep *)(rsp->data)) =
2070 case NGM_UBT_NODE_SET_QLEN:
2071 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2074 queue = ((ng_ubt_node_qlen_ep *)
2075 (msg->data))->queue;
2076 qlen = ((ng_ubt_node_qlen_ep *)
2085 case NGM_UBT_NODE_QUEUE_CMD:
2089 case NGM_UBT_NODE_QUEUE_ACL:
2093 case NGM_UBT_NODE_QUEUE_SCO:
2108 case NGM_UBT_NODE_GET_QLEN:
2109 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2114 queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2116 case NGM_UBT_NODE_QUEUE_CMD:
2120 case NGM_UBT_NODE_QUEUE_ACL:
2124 case NGM_UBT_NODE_QUEUE_SCO:
2135 NG_MKRESPONSE(rsp, msg,
2136 sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
2142 ((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2144 ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2149 case NGM_UBT_NODE_GET_STAT:
2150 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2155 bcopy(&sc->sc_stat, rsp->data,
2156 sizeof(ng_ubt_node_stat_ep));
2159 case NGM_UBT_NODE_RESET_STAT:
2160 NG_UBT_STAT_RESET(sc->sc_stat);
2163 case NGM_UBT_NODE_DEV_NODES:
2164 if (msg->header.arglen !=
2165 sizeof(ng_ubt_node_dev_nodes_ep)) {
2170 if ((sc->sc_flags & UBT_ANY_DEV) ||
2171 sc->sc_hook != NULL) {
2176 if (*((ng_ubt_node_dev_nodes_ep *)(msg->data)))
2177 ubt_create_device_nodes(sc);
2179 ubt_destroy_device_nodes(sc);
2193 NG_RESPOND_MSG(error, node, item, rsp);
2197 } /* ng_ubt_rcvmsg */
2204 ng_ubt_rcvdata(hook_p hook, item_p item)
2206 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2207 struct mbuf *m = NULL;
2208 usbd_status (*f)(ubt_softc_p) = NULL;
2209 struct ng_bt_mbufq *q = NULL;
2217 if (hook != sc->sc_hook) {
2222 /* Deatch mbuf and get HCI frame type */
2225 /* Process HCI frame */
2226 switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2227 case NG_HCI_CMD_PKT:
2228 f = ubt_request_start;
2233 case NG_HCI_ACL_DATA_PKT:
2234 f = ubt_bulk_out_start;
2239 #if __broken__ /* XXX FIXME */
2240 case NG_HCI_SCO_DATA_PKT:
2241 f = ubt_isoc_out_start;
2245 #endif /* __broken__ */
2249 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2250 __func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *),
2260 /* Loose frame type, if required */
2261 if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2262 m_adj(m, sizeof(u_int8_t));
2264 if (NG_BT_MBUFQ_FULL(q)) {
2266 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2267 __func__, USBDEVNAME(sc->sc_dev),
2268 *mtod(m, u_int8_t *), m->m_pkthdr.len);
2272 NG_BT_MBUFQ_ENQUEUE(q, m);
2274 if (!(sc->sc_flags & b))
2275 if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2281 } /* ng_ubt_rcvdata */
2283 /****************************************************************************
2284 ****************************************************************************
2286 ****************************************************************************
2287 ****************************************************************************/
2290 * Open endpoint device
2291 * XXX FIXME softc locking
2295 ubt_open(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
2297 ubt_softc_p sc = NULL;
2298 int ep = UBT_ENDPOINT(dev);
2300 USB_GET_SC_OPEN(ubt, UBT_UNIT(dev), sc); /* check for sc != NULL */
2304 if (ep == USB_CONTROL_ENDPOINT) {
2305 if (sc->sc_flags & UBT_CTRL_DEV)
2308 sc->sc_flags |= UBT_CTRL_DEV;
2309 } else if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2310 if (sc->sc_flags & UBT_INTR_DEV)
2312 if (sc->sc_intr_pipe == NULL)
2315 sc->sc_flags |= UBT_INTR_DEV;
2316 } else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2317 if (sc->sc_flags & UBT_BULK_DEV)
2319 if (sc->sc_bulk_in_pipe == NULL || sc->sc_bulk_out_pipe == NULL)
2322 sc->sc_flags |= UBT_BULK_DEV;
2330 * Close endpoint device
2331 * XXX FIXME softc locking
2335 ubt_close(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
2337 ubt_softc_p sc = NULL;
2338 int ep = UBT_ENDPOINT(dev);
2340 USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2344 if (ep == USB_CONTROL_ENDPOINT)
2345 sc->sc_flags &= ~UBT_CTRL_DEV;
2346 else if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2347 if (sc->sc_intr_pipe != NULL)
2348 usbd_abort_pipe(sc->sc_intr_pipe);
2350 sc->sc_flags &= ~UBT_INTR_DEV;
2351 } else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2352 /* Close both in and out bulk pipes */
2353 if (sc->sc_bulk_in_pipe != NULL)
2354 usbd_abort_pipe(sc->sc_bulk_in_pipe);
2356 if (sc->sc_bulk_out_pipe != NULL)
2357 usbd_abort_pipe(sc->sc_bulk_out_pipe);
2359 sc->sc_flags &= ~UBT_BULK_DEV;
2367 * Read from the endpoint device
2368 * XXX FIXME softc locking
2372 ubt_read(struct cdev *dev, struct uio *uio, int flag)
2374 ubt_softc_p sc = NULL;
2375 int error = 0, n, tn, ep = UBT_ENDPOINT(dev);
2377 usbd_pipe_handle pipe = NULL;
2378 usbd_xfer_handle xfer = NULL;
2379 u_int8_t buf[UBT_BSIZE];
2381 USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2382 if (sc == NULL || sc->sc_dying)
2385 if (ep == USB_CONTROL_ENDPOINT)
2386 return (EOPNOTSUPP);
2388 if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2389 pipe = sc->sc_intr_pipe;
2390 xfer = sc->sc_intr_xfer;
2391 } else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2392 pipe = sc->sc_bulk_in_pipe;
2393 xfer = sc->sc_bulk_in_xfer;
2397 if (pipe == NULL || xfer == NULL)
2402 while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
2404 status = usbd_bulk_transfer(xfer, pipe, USBD_SHORT_XFER_OK,
2405 USBD_DEFAULT_TIMEOUT, buf, &tn, "ubtrd");
2407 case USBD_NORMAL_COMPLETION:
2408 error = uiomove(buf, tn, uio);
2411 case USBD_INTERRUPTED:
2424 if (error != 0 || tn < n)
2428 if (-- sc->sc_refcnt < 0)
2429 usb_detach_wakeup(USBDEV(sc->sc_dev));
2435 * Write into the endpoint device
2436 * XXX FIXME softc locking
2440 ubt_write(struct cdev *dev, struct uio *uio, int flag)
2442 ubt_softc_p sc = NULL;
2443 int error = 0, n, ep = UBT_ENDPOINT(dev);
2445 u_int8_t buf[UBT_BSIZE];
2447 USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2448 if (sc == NULL || sc->sc_dying)
2451 if (ep == USB_CONTROL_ENDPOINT || ep == UE_GET_ADDR(sc->sc_intr_ep))
2452 return (EOPNOTSUPP);
2453 if (ep != UE_GET_ADDR(sc->sc_bulk_in_ep))
2458 while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
2459 error = uiomove(buf, n, uio);
2463 status = usbd_bulk_transfer(sc->sc_bulk_out_xfer,
2464 sc->sc_bulk_out_pipe, 0, USBD_DEFAULT_TIMEOUT,
2467 case USBD_NORMAL_COMPLETION:
2470 case USBD_INTERRUPTED:
2487 if (-- sc->sc_refcnt < 0)
2488 usb_detach_wakeup(USBDEV(sc->sc_dev));
2494 * Process ioctl on the endpoint device. Mostly stolen from ugen(4)
2495 * XXX FIXME softc locking
2499 ubt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
2501 ubt_softc_p sc = NULL;
2502 int len, error = 0, ep = UBT_ENDPOINT(dev);
2504 struct usb_string_desc *si = NULL;
2505 struct usb_ctl_request *ur = NULL;
2510 USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2511 if (sc == NULL || sc->sc_dying)
2514 if (ep != USB_CONTROL_ENDPOINT)
2515 return (EOPNOTSUPP);
2520 case USB_GET_DEVICE_DESC:
2521 *(usb_device_descriptor_t *) data =
2522 *usbd_get_device_descriptor(sc->sc_udev);
2525 case USB_GET_STRING_DESC:
2526 si = (struct usb_string_desc *) data;
2527 status = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
2528 si->usd_language_id, &si->usd_desc, &len);
2529 if (status != USBD_NORMAL_COMPLETION)
2533 case USB_DO_REQUEST:
2535 len = UGETW(ur->ucr_request.wLength);
2537 if (!(flag & FWRITE)) {
2542 /* Avoid requests that would damage the bus integrity. */
2543 if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
2544 ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
2545 (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
2546 ur->ucr_request.bRequest == UR_SET_CONFIG) ||
2547 (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
2548 ur->ucr_request.bRequest == UR_SET_INTERFACE) ||
2549 len < 0 || len > 32767) {
2555 iov.iov_base = (caddr_t) ur->ucr_data;
2560 uio.uio_resid = len;
2562 uio.uio_segflg = UIO_USERSPACE;
2563 uio.uio_rw = ur->ucr_request.bmRequestType & UT_READ ?
2564 UIO_READ : UIO_WRITE;
2567 ptr = malloc(len, M_TEMP, M_WAITOK);
2568 if (uio.uio_rw == UIO_WRITE) {
2569 error = uiomove(ptr, len, &uio);
2575 status = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
2576 ptr, ur->ucr_flags, &ur->ucr_actlen,
2577 USBD_DEFAULT_TIMEOUT);
2578 if (status != USBD_NORMAL_COMPLETION) {
2584 if (uio.uio_rw == UIO_READ) {
2585 error = uiomove(ptr, len, &uio);
2595 case USB_GET_DEVICEINFO:
2596 usbd_fill_deviceinfo(sc->sc_udev,
2597 (struct usb_device_info *) data, 1);
2605 if (-- sc->sc_refcnt < 0)
2606 usb_detach_wakeup(USBDEV(sc->sc_dev));
2612 * Poll the endpoint device
2613 * XXX FIXME softc locking
2617 ubt_poll(struct cdev *dev, int events, usb_proc_ptr p)
2619 ubt_softc_p sc = NULL;
2620 int revents = 0, ep = UBT_ENDPOINT(dev);
2622 USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2623 if (sc == NULL || sc->sc_dying)
2626 if (ep == USB_CONTROL_ENDPOINT)
2627 return (EOPNOTSUPP);
2629 if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2630 if (sc->sc_intr_pipe != NULL)
2631 revents |= events & (POLLIN | POLLRDNORM);
2634 } else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2635 if (sc->sc_bulk_in_pipe != NULL)
2636 revents |= events & (POLLIN | POLLRDNORM);
2638 if (sc->sc_bulk_out_pipe != NULL)
2639 revents |= events & (POLLOUT | POLLWRNORM);
2642 revents = EIO; /* both pipes closed */
2650 * Create device nodes for all endpoints. Must be called with node locked.
2654 ubt_create_device_nodes(ubt_softc_p sc)
2658 KASSERT((sc->sc_hook == NULL), (
2659 "%s: %s - hook != NULL!\n", __func__, USBDEVNAME(sc->sc_dev)));
2661 /* Control device */
2662 if (sc->sc_ctrl_dev == NULL)
2663 sc->sc_ctrl_dev = make_dev(&ubt_cdevsw,
2664 UBT_MINOR(USBDEVUNIT(sc->sc_dev), 0),
2665 UID_ROOT, GID_OPERATOR, 0644,
2666 "%s", USBDEVNAME(sc->sc_dev));
2668 /* Interrupt device */
2669 if (sc->sc_intr_dev == NULL && sc->sc_intr_ep != -1) {
2670 ep = UE_GET_ADDR(sc->sc_intr_ep);
2671 sc->sc_intr_dev = make_dev(&ubt_cdevsw,
2672 UBT_MINOR(USBDEVUNIT(sc->sc_dev), ep),
2673 UID_ROOT, GID_OPERATOR, 0644,
2674 "%s.%d", USBDEVNAME(sc->sc_dev), ep);
2678 * Bulk-in and bulk-out device
2679 * XXX will create one device for both in and out endpoints.
2680 * XXX note that address of the in and out endpoint should be the same
2683 if (sc->sc_bulk_dev == NULL &&
2684 sc->sc_bulk_in_ep != -1 && sc->sc_bulk_out_ep != -1 &&
2685 UE_GET_ADDR(sc->sc_bulk_in_ep) == UE_GET_ADDR(sc->sc_bulk_out_ep)) {
2686 ep = UE_GET_ADDR(sc->sc_bulk_in_ep);
2687 sc->sc_bulk_dev = make_dev(&ubt_cdevsw,
2688 UBT_MINOR(USBDEVUNIT(sc->sc_dev), ep),
2689 UID_ROOT, GID_OPERATOR, 0644,
2690 "%s.%d", USBDEVNAME(sc->sc_dev), ep);
2692 } /* ubt_create_device_nodes */
2695 * Destroy device nodes for all endpoints
2700 ubt_destroy_device_nodes(ubt_softc_p sc)
2703 * Wait for processes to go away. This should be safe as we will not
2704 * call ubt_destroy_device_nodes() from Netgraph unless all devices
2705 * were closed (and thus no active processes).
2708 if (-- sc->sc_refcnt >= 0) {
2710 usb_detach_wait(USBDEV(sc->sc_dev));
2715 /* Destroy device nodes */
2716 if (sc->sc_bulk_dev != NULL) {
2717 destroy_dev(sc->sc_bulk_dev);
2718 sc->sc_bulk_dev = NULL;
2721 if (sc->sc_intr_dev != NULL) {
2722 destroy_dev(sc->sc_intr_dev);
2723 sc->sc_intr_dev = NULL;
2726 if (sc->sc_ctrl_dev != NULL) {
2727 destroy_dev(sc->sc_ctrl_dev);
2728 sc->sc_ctrl_dev = NULL;
2730 } /* ubt_destroy_device_nodes */