1 /* 2 * ng_ubt.c 3 * 4 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 15 * 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 26 * SUCH DAMAGE. 27 * 28 * $Id: ng_ubt.c,v 1.1 2002/11/09 19:09:02 max Exp $ 29 * $FreeBSD$ 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/endian.h> 36 #include <sys/interrupt.h> 37 #include <sys/mbuf.h> 38 #include <sys/malloc.h> 39 #include <sys/kernel.h> 40 41 #include <sys/socket.h> 42 #include <net/if.h> 43 #include <net/if_var.h> 44 45 #include <dev/usb/usb.h> 46 #include <dev/usb/usbdi.h> 47 #include <dev/usb/usbdi_util.h> 48 #include <dev/usb/usbdivar.h> 49 #include <dev/usb/usbdevs.h> 50 51 #include <netgraph/ng_message.h> 52 #include <netgraph/netgraph.h> 53 #include <netgraph/ng_parse.h> 54 #include <ng_bluetooth.h> 55 #include <ng_hci.h> 56 #include "ng_ubt.h" 57 #include "ng_ubt_var.h" 58 59 /* 60 * USB methods 61 */ 62 63 USB_DECLARE_DRIVER(ubt); 64 65 Static int ubt_modevent (module_t, int, void *); 66 67 Static usbd_status ubt_request_start (ubt_softc_p, struct mbuf *); 68 Static void ubt_request_complete (usbd_xfer_handle, 69 usbd_private_handle, usbd_status); 70 71 Static usbd_status ubt_intr_start (ubt_softc_p); 72 Static void ubt_intr_complete (usbd_xfer_handle, 73 usbd_private_handle, usbd_status); 74 75 Static usbd_status ubt_bulk_in_start (ubt_softc_p); 76 Static void ubt_bulk_in_complete (usbd_xfer_handle, 77 usbd_private_handle, usbd_status); 78 79 Static usbd_status ubt_bulk_out_start (ubt_softc_p, struct mbuf *); 80 Static void ubt_bulk_out_complete (usbd_xfer_handle, 81 usbd_private_handle, usbd_status); 82 83 Static usbd_status ubt_isoc_in_start (ubt_softc_p); 84 Static void ubt_isoc_in_complete (usbd_xfer_handle, 85 usbd_private_handle, usbd_status); 86 87 Static usbd_status ubt_isoc_out_start (ubt_softc_p, struct mbuf *); 88 Static void ubt_isoc_out_complete (usbd_xfer_handle, 89 usbd_private_handle, usbd_status); 90 91 Static void ubt_swi_intr (void *); 92 93 /* 94 * Netgraph methods 95 */ 96 97 Static ng_constructor_t ng_ubt_constructor; 98 Static ng_shutdown_t ng_ubt_shutdown; 99 Static ng_newhook_t ng_ubt_newhook; 100 Static ng_connect_t ng_ubt_connect; 101 Static ng_disconnect_t ng_ubt_disconnect; 102 Static ng_rcvmsg_t ng_ubt_rcvmsg; 103 Static ng_rcvdata_t ng_ubt_rcvdata; 104 Static void ng_ubt_reset (ubt_softc_p); 105 106 /* Queue length */ 107 Static const struct ng_parse_struct_field ng_ubt_node_qlen_type_fields[] = 108 { 109 { "queue", &ng_parse_int32_type, }, 110 { "qlen", &ng_parse_int32_type, }, 111 { NULL, } 112 }; 113 Static const struct ng_parse_type ng_ubt_node_qlen_type = { 114 &ng_parse_struct_type, 115 &ng_ubt_node_qlen_type_fields 116 }; 117 118 /* Stat info */ 119 Static const struct ng_parse_struct_field ng_ubt_node_stat_type_fields[] = 120 { 121 { "pckts_recv", &ng_parse_uint32_type, }, 122 { "bytes_recv", &ng_parse_uint32_type, }, 123 { "pckts_sent", &ng_parse_uint32_type, }, 124 { "bytes_sent", &ng_parse_uint32_type, }, 125 { "oerrors", &ng_parse_uint32_type, }, 126 { "ierrors", &ng_parse_uint32_type, }, 127 { NULL, } 128 }; 129 Static const struct ng_parse_type ng_ubt_node_stat_type = { 130 &ng_parse_struct_type, 131 &ng_ubt_node_stat_type_fields 132 }; 133 134 /* Netgraph node command list */ 135 Static const struct ng_cmdlist ng_ubt_cmdlist[] = { 136 { 137 NGM_UBT_COOKIE, 138 NGM_UBT_NODE_SET_DEBUG, 139 "set_debug", 140 &ng_parse_uint16_type, 141 NULL 142 }, 143 { 144 NGM_UBT_COOKIE, 145 NGM_UBT_NODE_GET_DEBUG, 146 "get_debug", 147 NULL, 148 &ng_parse_uint16_type 149 }, 150 { 151 NGM_UBT_COOKIE, 152 NGM_UBT_NODE_SET_QLEN, 153 "set_qlen", 154 &ng_ubt_node_qlen_type, 155 NULL 156 }, 157 { 158 NGM_UBT_COOKIE, 159 NGM_UBT_NODE_GET_QLEN, 160 "get_qlen", 161 &ng_ubt_node_qlen_type, 162 &ng_ubt_node_qlen_type 163 }, 164 { 165 NGM_UBT_COOKIE, 166 NGM_UBT_NODE_GET_STAT, 167 "get_stat", 168 NULL, 169 &ng_ubt_node_stat_type 170 }, 171 { 172 NGM_UBT_COOKIE, 173 NGM_UBT_NODE_RESET_STAT, 174 "reset_stat", 175 NULL, 176 NULL 177 }, 178 { 0, } 179 }; 180 181 /* Netgraph node type */ 182 Static struct ng_type typestruct = { 183 NG_ABI_VERSION, 184 NG_UBT_NODE_TYPE, /* typename */ 185 NULL, /* modevent */ 186 ng_ubt_constructor, /* constructor */ 187 ng_ubt_rcvmsg, /* control message */ 188 ng_ubt_shutdown, /* destructor */ 189 ng_ubt_newhook, /* new hook */ 190 NULL, /* find hook */ 191 ng_ubt_connect, /* connect hook */ 192 ng_ubt_rcvdata, /* data */ 193 ng_ubt_disconnect, /* disconnect hook */ 194 ng_ubt_cmdlist /* node command list */ 195 }; 196 197 /* 198 * Module 199 */ 200 201 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0); 202 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION); 203 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); 204 205 /**************************************************************************** 206 **************************************************************************** 207 ** USB specific 208 **************************************************************************** 209 ****************************************************************************/ 210 211 /* 212 * Load/Unload the driver module 213 */ 214 215 Static int 216 ubt_modevent(module_t mod, int event, void *data) 217 { 218 int error; 219 220 switch (event) { 221 case MOD_LOAD: 222 error = ng_newtype(&typestruct); 223 if (error != 0) 224 printf("%s: Could not register Netgraph node type, " \ 225 "error=%d\n", NG_UBT_NODE_TYPE, error); 226 else 227 error = usbd_driver_load(mod, event, data); 228 break; 229 230 case MOD_UNLOAD: 231 error = ng_rmtype(&typestruct); 232 if (error == 0) 233 error = usbd_driver_load(mod, event, data); 234 break; 235 236 default: 237 error = EOPNOTSUPP; 238 break; 239 } 240 241 return (error); 242 } /* ubt_modevent */ 243 244 /* 245 * Probe for a USB Bluetooth device 246 */ 247 248 USB_MATCH(ubt) 249 { 250 Static struct usb_devno const ubt_devices[] = { 251 { USB_VENDOR_3COM, USB_PRODUCT_3COM_3CREB96 }, 252 { USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_BT_DONGLE }, 253 { USB_VENDOR_TDK, USB_PRODUCT_TDK_BT_DONGLE }, 254 { USB_VENDOR_MSI, USB_PRODUCT_MSI_BT_DONGLE }, 255 { USB_VENDOR_BROADCOM, USB_PRODUCT_DBW_120M_BT_DONGLE }, 256 { USB_VENDOR_EPOX, USB_PRODUCT_BT_DG02_DONGLE }, 257 { 0, 0 } 258 }; 259 260 USB_MATCH_START(ubt, uaa); 261 262 if (uaa->iface == NULL || 263 usb_lookup(ubt_devices, uaa->vendor, uaa->product) == NULL) 264 return (UMATCH_NONE); 265 266 return (UMATCH_VENDOR_PRODUCT); 267 } /* USB_MATCH(ubt) */ 268 269 /* 270 * Attach the device 271 */ 272 273 USB_ATTACH(ubt) 274 { 275 USB_ATTACH_START(ubt, sc, uaa); 276 usb_config_descriptor_t *cd = NULL; 277 usb_interface_descriptor_t *id = NULL; 278 usb_endpoint_descriptor_t *ed = NULL; 279 char devinfo[1024]; 280 usbd_status error; 281 int i, ai, alt_no, isoc_in, isoc_out, 282 isoc_isize, isoc_osize; 283 284 /* Get USB device info */ 285 sc->sc_udev = uaa->device; 286 usbd_devinfo(sc->sc_udev, 0, devinfo); 287 USB_ATTACH_SETUP; 288 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); 289 290 /* 291 * Initialize device softc structure 292 */ 293 294 /* State */ 295 sc->sc_debug = NG_UBT_WARN_LEVEL; 296 sc->sc_flags = 0; 297 NG_UBT_STAT_RESET(sc->sc_stat); 298 299 /* Interfaces */ 300 sc->sc_iface0 = sc->sc_iface1 = NULL; 301 302 /* Input queue */ 303 bzero(&sc->sc_inq, sizeof(sc->sc_inq)); 304 sc->sc_inq.ifq_maxlen = UBT_DEFAULT_QLEN; 305 mtx_init(&sc->sc_inq.ifq_mtx, "UBT inq", NULL, MTX_DEF); 306 307 /* Interrupt pipe */ 308 sc->sc_intr_ep = -1; 309 sc->sc_intr_pipe = NULL; 310 sc->sc_intr_xfer = NULL; 311 sc->sc_intr_buffer = NULL; 312 313 /* Control pipe */ 314 sc->sc_ctrl_xfer = NULL; 315 sc->sc_ctrl_buffer = NULL; 316 bzero(&sc->sc_cmdq, sizeof(sc->sc_cmdq)); 317 sc->sc_cmdq.ifq_maxlen = UBT_DEFAULT_QLEN; 318 mtx_init(&sc->sc_cmdq.ifq_mtx, "UBT cmdq", NULL, MTX_DEF); 319 320 /* Bulk-in pipe */ 321 sc->sc_bulk_in_ep = -1; 322 sc->sc_bulk_in_pipe = NULL; 323 sc->sc_bulk_in_xfer = NULL; 324 sc->sc_bulk_in_buffer = NULL; 325 326 /* Bulk-out pipe */ 327 sc->sc_bulk_out_ep = -1; 328 sc->sc_bulk_out_pipe = NULL; 329 sc->sc_bulk_out_xfer = NULL; 330 sc->sc_bulk_out_buffer = NULL; 331 bzero(&sc->sc_aclq, sizeof(sc->sc_aclq)); 332 sc->sc_aclq.ifq_maxlen = UBT_DEFAULT_QLEN; 333 mtx_init(&sc->sc_aclq.ifq_mtx, "UBT aclq", NULL, MTX_DEF); 334 335 /* Isoc-in pipe */ 336 sc->sc_isoc_in_ep = -1; 337 sc->sc_isoc_in_pipe = NULL; 338 sc->sc_isoc_in_xfer = NULL; 339 340 /* Isoc-out pipe */ 341 sc->sc_isoc_out_ep = -1; 342 sc->sc_isoc_out_pipe = NULL; 343 sc->sc_isoc_out_xfer = NULL; 344 sc->sc_isoc_size = -1; 345 bzero(&sc->sc_scoq, sizeof(sc->sc_scoq)); 346 sc->sc_scoq.ifq_maxlen = UBT_DEFAULT_QLEN; 347 mtx_init(&sc->sc_scoq.ifq_mtx, "UBT scoq", NULL, MTX_DEF); 348 349 /* Netgraph part */ 350 sc->sc_node = NULL; 351 sc->sc_hook = NULL; 352 353 /* Attach SWI handler to TTY SWI thread */ 354 sc->sc_ith = NULL; 355 if (swi_add(&tty_ithd, USBDEVNAME(sc->sc_dev), 356 ubt_swi_intr, sc, SWI_TTY, 0, &sc->sc_ith) < 0) { 357 printf("%s: Could not setup SWI ISR\n", USBDEVNAME(sc->sc_dev)); 358 goto bad; 359 } 360 361 /* 362 * XXX set configuration? 363 * 364 * Configure Bluetooth USB device. Discover all required USB interfaces 365 * and endpoints. 366 * 367 * USB device must present two interfaces: 368 * 1) Interface 0 that has 3 endpoints 369 * 1) Interrupt endpoint to receive HCI events 370 * 2) Bulk IN endpoint to receive ACL data 371 * 3) Bulk OUT endpoint to send ACL data 372 * 373 * 2) Interface 1 then has 2 endpoints 374 * 1) Isochronous IN endpoint to receive SCO data 375 * 2) Isochronous OUT endpoint to send SCO data 376 * 377 * Interface 1 (with isochronous endpoints) has several alternate 378 * configurations with different packet size. 379 */ 380 381 /* 382 * Interface 0 383 */ 384 385 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0); 386 if (error || sc->sc_iface0 == NULL) { 387 printf("%s: Could not get interface 0 handle. %s (%d), " \ 388 "handle=%p\n", USBDEVNAME(sc->sc_dev), 389 usbd_errstr(error), error, sc->sc_iface0); 390 goto bad; 391 } 392 393 id = usbd_get_interface_descriptor(sc->sc_iface0); 394 if (id == NULL) { 395 printf("%s: Could not get interface 0 descriptor\n", 396 USBDEVNAME(sc->sc_dev)); 397 goto bad; 398 } 399 if (id->bInterfaceClass != UICLASS_WIRELESS_CONTROLLER || 400 id->bInterfaceSubClass != UISUBCLASS_RF_CONTROLLER || 401 id->bInterfaceProtocol != UIPROTO_BLUETOOTH) { 402 printf("%s: Interface 0 is not supported, " \ 403 "bInterfaceClass=%#x, bInterfaceSubClass=%#x, "\ 404 "bInterfaceProtocol=%#x\n", USBDEVNAME(sc->sc_dev), 405 id->bInterfaceClass, id->bInterfaceSubClass, 406 id->bInterfaceProtocol); 407 goto bad; 408 } 409 410 for (i = 0; i < id->bNumEndpoints; i ++) { 411 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i); 412 if (ed == NULL) { 413 printf("%s: Could not read endpoint descriptor for " \ 414 "interface 0, i=%d\n", USBDEVNAME(sc->sc_dev), 415 i); 416 goto bad; 417 } 418 419 switch (UE_GET_XFERTYPE(ed->bmAttributes)) { 420 case UE_BULK: 421 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) 422 sc->sc_bulk_in_ep = ed->bEndpointAddress; 423 else 424 sc->sc_bulk_out_ep = ed->bEndpointAddress; 425 break; 426 427 case UE_INTERRUPT: 428 sc->sc_intr_ep = ed->bEndpointAddress; 429 break; 430 } 431 } 432 433 /* Check if we got everything we wanted on Interface 0 */ 434 if (sc->sc_intr_ep == -1) { 435 printf("%s: Could not detect interrupt endpoint\n", 436 USBDEVNAME(sc->sc_dev)); 437 goto bad; 438 } 439 if (sc->sc_bulk_in_ep == -1) { 440 printf("%s: Could not detect bulk-in endpoint\n", 441 USBDEVNAME(sc->sc_dev)); 442 goto bad; 443 } 444 if (sc->sc_bulk_out_ep == -1) { 445 printf("%s: Could not detect bulk-out endpoint\n", 446 USBDEVNAME(sc->sc_dev)); 447 goto bad; 448 } 449 450 printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \ 451 "bulk-out=%#x\n", USBDEVNAME(sc->sc_dev), 452 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep); 453 454 /* 455 * Interface 1 456 */ 457 458 cd = usbd_get_config_descriptor(sc->sc_udev); 459 if (cd == NULL) { 460 printf("%s: Could not get device configuration descriptor\n", 461 USBDEVNAME(sc->sc_dev)); 462 goto bad; 463 } 464 465 error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1); 466 if (error || sc->sc_iface1 == NULL) { 467 printf("%s: Could not get interface 1 handle. %s (%d), " \ 468 "handle=%p\n", USBDEVNAME(sc->sc_dev), 469 usbd_errstr(error), error, sc->sc_iface1); 470 goto bad; 471 } 472 473 id = usbd_get_interface_descriptor(sc->sc_iface1); 474 if (id == NULL) { 475 printf("%s: Could not get interface 1 descriptor\n", 476 USBDEVNAME(sc->sc_dev)); 477 goto bad; 478 } 479 if (id->bInterfaceClass != UICLASS_WIRELESS_CONTROLLER || 480 id->bInterfaceSubClass != UISUBCLASS_RF_CONTROLLER || 481 id->bInterfaceProtocol != UIPROTO_BLUETOOTH) { 482 printf("%s: Interface 1 is not supported, " \ 483 "bInterfaceClass=%#x, bInterfaceSubClass=%#x, "\ 484 "bInterfaceProtocol=%#x\n", USBDEVNAME(sc->sc_dev), 485 id->bInterfaceClass, id->bInterfaceSubClass, 486 id->bInterfaceProtocol); 487 goto bad; 488 } 489 490 /* 491 * Scan all alternate configurations for interface 1 492 */ 493 494 alt_no = -1; 495 496 for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++) { 497 error = usbd_set_interface(sc->sc_iface1, ai); 498 if (error) { 499 printf("%s: [SCAN] Could not set alternate " \ 500 "configuration %d for interface 1. %s (%d)\n", 501 USBDEVNAME(sc->sc_dev), ai, usbd_errstr(error), 502 error); 503 goto bad; 504 } 505 id = usbd_get_interface_descriptor(sc->sc_iface1); 506 if (id == NULL) { 507 printf("%s: Could not get interface 1 descriptor for " \ 508 "alternate configuration %d\n", 509 USBDEVNAME(sc->sc_dev), ai); 510 goto bad; 511 } 512 513 isoc_in = isoc_out = -1; 514 isoc_isize = isoc_osize = 0; 515 516 for (i = 0; i < id->bNumEndpoints; i ++) { 517 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i); 518 if (ed == NULL) { 519 printf("%s: Could not read endpoint " \ 520 "descriptor for interface 1, " \ 521 "alternate configuration %d, i=%d\n", 522 USBDEVNAME(sc->sc_dev), ai, i); 523 goto bad; 524 } 525 526 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS) 527 continue; 528 529 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) { 530 isoc_in = ed->bEndpointAddress; 531 isoc_isize = UGETW(ed->wMaxPacketSize); 532 } else { 533 isoc_out = ed->bEndpointAddress; 534 isoc_osize = UGETW(ed->wMaxPacketSize); 535 } 536 } 537 538 /* 539 * Make sure that configuration looks sane and if so 540 * update current settings 541 */ 542 543 if (isoc_in != -1 && isoc_out != -1 && 544 isoc_isize > 0 && isoc_osize > 0 && 545 isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) { 546 sc->sc_isoc_in_ep = isoc_in; 547 sc->sc_isoc_out_ep = isoc_out; 548 sc->sc_isoc_size = isoc_isize; 549 alt_no = ai; 550 } 551 } 552 553 /* Check if we got everything we wanted on Interface 0 */ 554 if (sc->sc_isoc_in_ep == -1) { 555 printf("%s: Could not detect isoc-in endpoint\n", 556 USBDEVNAME(sc->sc_dev)); 557 goto bad; 558 } 559 if (sc->sc_isoc_out_ep == -1) { 560 printf("%s: Could not detect isoc-out endpoint\n", 561 USBDEVNAME(sc->sc_dev)); 562 goto bad; 563 } 564 if (sc->sc_isoc_size <= 0) { 565 printf("%s: Invalid isoc. packet size=%d\n", 566 USBDEVNAME(sc->sc_dev), sc->sc_isoc_size); 567 goto bad; 568 } 569 570 error = usbd_set_interface(sc->sc_iface1, alt_no); 571 if (error) { 572 printf("%s: Could not set alternate configuration " \ 573 "%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev), 574 alt_no, usbd_errstr(error), error); 575 goto bad; 576 } 577 578 /* Allocate USB transfer handles and buffers */ 579 sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev); 580 if (sc->sc_ctrl_xfer == NULL) { 581 printf("%s: Could not allocate control xfer handle\n", 582 USBDEVNAME(sc->sc_dev)); 583 goto bad; 584 } 585 sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer, 586 UBT_CTRL_BUFFER_SIZE); 587 if (sc->sc_ctrl_buffer == NULL) { 588 printf("%s: Could not allocate control buffer\n", 589 USBDEVNAME(sc->sc_dev)); 590 goto bad; 591 } 592 593 sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev); 594 if (sc->sc_intr_xfer == NULL) { 595 printf("%s: Could not allocate interrupt xfer handle\n", 596 USBDEVNAME(sc->sc_dev)); 597 goto bad; 598 } 599 sc->sc_intr_buffer = usbd_alloc_buffer(sc->sc_intr_xfer, 600 UBT_INTR_BUFFER_SIZE); 601 if (sc->sc_intr_buffer == NULL) { 602 printf("%s: Could not allocate interrupt buffer\n", 603 USBDEVNAME(sc->sc_dev)); 604 goto bad; 605 } 606 607 sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev); 608 if (sc->sc_bulk_in_xfer == NULL) { 609 printf("%s: Could not allocate bulk-in xfer handle\n", 610 USBDEVNAME(sc->sc_dev)); 611 goto bad; 612 } 613 sc->sc_bulk_in_buffer = usbd_alloc_buffer(sc->sc_bulk_in_xfer, 614 UBT_BULK_BUFFER_SIZE); 615 if (sc->sc_bulk_in_buffer == NULL) { 616 printf("%s: Could not allocate bulk-in buffer\n", 617 USBDEVNAME(sc->sc_dev)); 618 goto bad; 619 } 620 621 sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev); 622 if (sc->sc_bulk_out_xfer == NULL) { 623 printf("%s: Could not allocate bulk-out xfer handle\n", 624 USBDEVNAME(sc->sc_dev)); 625 goto bad; 626 } 627 sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer, 628 UBT_BULK_BUFFER_SIZE); 629 if (sc->sc_bulk_out_buffer == NULL) { 630 printf("%s: Could not allocate bulk-out buffer\n", 631 USBDEVNAME(sc->sc_dev)); 632 goto bad; 633 } 634 635 /* 636 * Allocate buffers for isoc. transfers 637 */ 638 639 sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1; 640 641 sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev); 642 if (sc->sc_isoc_in_xfer == NULL) { 643 printf("%s: Could not allocate isoc-in xfer handle\n", 644 USBDEVNAME(sc->sc_dev)); 645 goto bad; 646 } 647 sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer, 648 sc->sc_isoc_nframes * sc->sc_isoc_size); 649 if (sc->sc_isoc_in_buffer == NULL) { 650 printf("%s: Could not allocate isoc-in buffer\n", 651 USBDEVNAME(sc->sc_dev)); 652 goto bad; 653 } 654 sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes, 655 M_USBDEV, M_NOWAIT); 656 if (sc->sc_isoc_in_frlen == NULL) { 657 printf("%s: Could not allocate isoc-in frame sizes buffer\n", 658 USBDEVNAME(sc->sc_dev)); 659 goto bad; 660 } 661 662 sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev); 663 if (sc->sc_isoc_out_xfer == NULL) { 664 printf("%s: Could not allocate isoc-out xfer handle\n", 665 USBDEVNAME(sc->sc_dev)); 666 goto bad; 667 } 668 sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer, 669 sc->sc_isoc_nframes * sc->sc_isoc_size); 670 if (sc->sc_isoc_out_buffer == NULL) { 671 printf("%s: Could not allocate isoc-out buffer\n", 672 USBDEVNAME(sc->sc_dev)); 673 goto bad; 674 } 675 sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes, 676 M_USBDEV, M_NOWAIT); 677 if (sc->sc_isoc_out_frlen == NULL) { 678 printf("%s: Could not allocate isoc-out frame sizes buffer\n", 679 USBDEVNAME(sc->sc_dev)); 680 goto bad; 681 } 682 683 printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \ 684 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n", 685 USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep, 686 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes, 687 (sc->sc_isoc_nframes * sc->sc_isoc_size)); 688 689 /* Create Netgraph node */ 690 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) { 691 printf("%s: Could not create Netgraph node\n", 692 USBDEVNAME(sc->sc_dev)); 693 sc->sc_node = NULL; 694 goto bad; 695 } 696 697 /* Name node */ 698 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) { 699 printf("%s: Could not name Netgraph node\n", 700 USBDEVNAME(sc->sc_dev)); 701 NG_NODE_UNREF(sc->sc_node); 702 sc->sc_node = NULL; 703 goto bad; 704 } 705 706 NG_NODE_SET_PRIVATE(sc->sc_node, sc); 707 708 /* 709 * XXX Is that correct? 710 * Claim all interfaces on the device 711 */ 712 713 for (i = 0; i < uaa->nifaces; i++) 714 uaa->ifaces[i] = NULL; 715 716 USB_ATTACH_SUCCESS_RETURN; 717 bad: 718 ubt_detach(self); 719 720 USB_ATTACH_ERROR_RETURN; 721 } /* USB_ATTACH(ubt) */ 722 723 /* 724 * Detach the device 725 */ 726 727 USB_DETACH(ubt) 728 { 729 USB_DETACH_START(ubt, sc); 730 731 ng_ubt_reset(sc); 732 733 /* Destroy Netgraph node */ 734 if (sc->sc_node != NULL) { 735 NG_NODE_SET_PRIVATE(sc->sc_node, NULL); 736 ng_rmnode_self(sc->sc_node); 737 sc->sc_node = NULL; 738 } 739 740 /* Destroy USB transfer handles */ 741 if (sc->sc_ctrl_xfer != NULL) { 742 usbd_free_xfer(sc->sc_ctrl_xfer); 743 sc->sc_ctrl_xfer = NULL; 744 } 745 746 if (sc->sc_intr_xfer != NULL) { 747 usbd_free_xfer(sc->sc_intr_xfer); 748 sc->sc_intr_xfer = NULL; 749 } 750 751 if (sc->sc_bulk_in_xfer != NULL) { 752 usbd_free_xfer(sc->sc_bulk_in_xfer); 753 sc->sc_bulk_in_xfer = NULL; 754 } 755 if (sc->sc_bulk_out_xfer != NULL) { 756 usbd_free_xfer(sc->sc_bulk_out_xfer); 757 sc->sc_bulk_out_xfer = NULL; 758 } 759 760 if (sc->sc_isoc_in_xfer != NULL) { 761 usbd_free_xfer(sc->sc_isoc_in_xfer); 762 sc->sc_isoc_in_xfer = NULL; 763 } 764 if (sc->sc_isoc_out_xfer != NULL) { 765 usbd_free_xfer(sc->sc_isoc_out_xfer); 766 sc->sc_isoc_out_xfer = NULL; 767 } 768 769 /* Destroy isoc. frame size buffers */ 770 if (sc->sc_isoc_in_frlen != NULL) { 771 free(sc->sc_isoc_in_frlen, M_USBDEV); 772 sc->sc_isoc_in_frlen = NULL; 773 } 774 if (sc->sc_isoc_out_frlen != NULL) { 775 free(sc->sc_isoc_out_frlen, M_USBDEV); 776 sc->sc_isoc_out_frlen = NULL; 777 } 778 779 if (sc->sc_ith != NULL) { 780 ithread_remove_handler(sc->sc_ith); 781 sc->sc_ith = NULL; 782 } 783 784 /* Destroy queues */ 785 IF_DRAIN(&sc->sc_cmdq); 786 IF_DRAIN(&sc->sc_aclq); 787 IF_DRAIN(&sc->sc_scoq); 788 IF_DRAIN(&sc->sc_inq); 789 790 mtx_destroy(&sc->sc_cmdq.ifq_mtx); 791 mtx_destroy(&sc->sc_aclq.ifq_mtx); 792 mtx_destroy(&sc->sc_scoq.ifq_mtx); 793 mtx_destroy(&sc->sc_inq.ifq_mtx); 794 795 return (0); 796 } /* USB_DETACH(ubt) */ 797 798 /* 799 * Start USB control request (HCI command) 800 */ 801 802 Static usbd_status 803 ubt_request_start(ubt_softc_p sc, struct mbuf *m) 804 { 805 usb_device_request_t req; 806 usbd_status status = USBD_NORMAL_COMPLETION; 807 808 IF_LOCK(&sc->sc_cmdq); 809 810 if (m != NULL) { 811 if (_IF_QFULL(&sc->sc_cmdq)) { 812 NG_UBT_ERR( 813 "%s: %s - Dropping HCI command frame, len=%d. Queue full\n", 814 __func__, USBDEVNAME(sc->sc_dev), 815 m->m_pkthdr.len); 816 817 _IF_DROP(&sc->sc_cmdq); 818 NG_UBT_STAT_OERROR(sc->sc_stat); 819 820 NG_FREE_M(m); 821 } else 822 _IF_ENQUEUE(&sc->sc_cmdq, m); 823 } else 824 sc->sc_flags &= ~UBT_CMD_XMIT; 825 826 if (sc->sc_flags & UBT_CMD_XMIT) { 827 NG_UBT_INFO( 828 "%s: %s - Another control request is pending\n", 829 __func__, USBDEVNAME(sc->sc_dev)); 830 goto done; 831 } 832 833 _IF_DEQUEUE(&sc->sc_cmdq, m); 834 if (m == NULL) { 835 NG_UBT_INFO( 836 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev)); 837 goto done; 838 } 839 840 /* 841 * Check HCI command frame size and copy it back 842 * to linear USB transfer buffer. 843 */ 844 845 if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE) 846 panic( 847 "%s: %s - HCI command frame too big, size=%d, len=%d\n", 848 __func__, USBDEVNAME(sc->sc_dev), UBT_CTRL_BUFFER_SIZE, 849 m->m_pkthdr.len); 850 851 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer); 852 853 /* Initialize a USB control request and then schedule it */ 854 855 bzero(&req, sizeof(req)); 856 req.bmRequestType = UBT_HCI_REQUEST; 857 USETW(req.wLength, m->m_pkthdr.len); 858 859 NG_UBT_INFO( 860 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n", 861 __func__, USBDEVNAME(sc->sc_dev), req.bmRequestType, 862 UGETW(req.wLength)); 863 864 usbd_setup_default_xfer( 865 sc->sc_ctrl_xfer, 866 sc->sc_udev, 867 (usbd_private_handle) sc, 868 USBD_DEFAULT_TIMEOUT, /* XXX */ 869 &req, 870 sc->sc_ctrl_buffer, 871 m->m_pkthdr.len, 872 USBD_NO_COPY, 873 ubt_request_complete); 874 875 status = usbd_transfer(sc->sc_ctrl_xfer); 876 if (status && status != USBD_IN_PROGRESS) { 877 NG_UBT_ERR( 878 "%s: %s - Could not start control request. %s (%d)\n", 879 __func__, USBDEVNAME(sc->sc_dev), 880 usbd_errstr(status), status); 881 882 _IF_DROP(&sc->sc_cmdq); /* XXX */ 883 NG_UBT_STAT_OERROR(sc->sc_stat); 884 885 /* XXX FIXME: should we try to resubmit another request? */ 886 } else { 887 NG_UBT_INFO( 888 "%s: %s - Control request has been started\n", 889 __func__, USBDEVNAME(sc->sc_dev)); 890 891 sc->sc_flags |= UBT_CMD_XMIT; 892 893 status = USBD_NORMAL_COMPLETION; 894 } 895 896 NG_FREE_M(m); 897 done: 898 IF_UNLOCK(&sc->sc_cmdq); 899 900 return (status); 901 } /* ubt_request_start */ 902 903 /* 904 * USB control request callback 905 */ 906 907 Static void 908 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s) 909 { 910 ubt_softc_p sc = (ubt_softc_p) p; 911 912 if (s == USBD_CANCELLED) { 913 NG_UBT_INFO( 914 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev)); 915 916 return; 917 } 918 919 if (s != USBD_NORMAL_COMPLETION) { 920 NG_UBT_ERR( 921 "%s: %s - Control request failed. %s (%d)\n", 922 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s); 923 924 if (s == USBD_STALLED) 925 usbd_clear_endpoint_stall_async(h->pipe); 926 927 NG_UBT_STAT_OERROR(sc->sc_stat); 928 } else { 929 NG_UBT_INFO( 930 "%s: %s - Sent %d bytes to control pipe\n", 931 __func__, USBDEVNAME(sc->sc_dev), h->actlen); 932 933 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen); 934 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat); 935 } 936 937 ubt_request_start(sc, NULL /* completed request */); 938 } /* ubt_request_complete */ 939 940 /* 941 * Start interrupt transfer 942 */ 943 944 Static usbd_status 945 ubt_intr_start(ubt_softc_p sc) 946 { 947 usbd_status status; 948 949 /* Initialize a USB transfer and then schedule it */ 950 usbd_setup_xfer( 951 sc->sc_intr_xfer, 952 sc->sc_intr_pipe, 953 (usbd_private_handle) sc, 954 sc->sc_intr_buffer, 955 UBT_INTR_BUFFER_SIZE, 956 USBD_SHORT_XFER_OK | USBD_NO_COPY, 957 USBD_NO_TIMEOUT, 958 ubt_intr_complete); 959 960 status = usbd_transfer(sc->sc_intr_xfer); 961 if (status && status != USBD_IN_PROGRESS) { 962 NG_UBT_ERR( 963 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n", 964 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 965 status); 966 967 return (status); 968 } 969 970 return (USBD_NORMAL_COMPLETION); 971 } /* ubt_intr_start */ 972 973 /* 974 * Process interrupt from USB device (We got data from interrupt pipe) 975 */ 976 977 Static void 978 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s) 979 { 980 ubt_softc_p sc = (ubt_softc_p) p; 981 struct mbuf *m = NULL; 982 ng_hci_event_pkt_t *hdr = NULL; 983 int off; 984 985 if (s == USBD_CANCELLED) { 986 NG_UBT_INFO( 987 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev)); 988 989 return; 990 } 991 992 if (s != USBD_NORMAL_COMPLETION) { 993 NG_UBT_WARN( 994 "%s: %s - Interrupt xfer failed. %s (%d)\n", 995 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s); 996 997 if (s == USBD_STALLED) 998 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); 999 1000 NG_UBT_STAT_IERROR(sc->sc_stat); 1001 goto done; 1002 } 1003 1004 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen); 1005 1006 NG_UBT_INFO( 1007 "%s: %s - Got %d bytes from interrupt pipe\n", 1008 __func__, USBDEVNAME(sc->sc_dev), h->actlen); 1009 1010 if (h->actlen < sizeof(*hdr)) 1011 goto done; 1012 1013 /* Copy HCI event frame to mbuf */ 1014 1015 MGETHDR(m, M_DONTWAIT, MT_DATA); 1016 if (m == NULL) { 1017 NG_UBT_ALERT( 1018 "%s: %s - Could not allocate mbuf\n", __func__, USBDEVNAME(sc->sc_dev)); 1019 NG_UBT_STAT_IERROR(sc->sc_stat); 1020 goto done; 1021 } 1022 1023 /* 1024 * Copy data from USB buffer into mbuf and check if we got 1025 * full HCI event frame. Fix HCI event frame if required. 1026 */ 1027 1028 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) { 1029 off = 1; 1030 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT; 1031 } else 1032 off = 0; 1033 1034 m->m_pkthdr.len = 0; 1035 m->m_len = min(MHLEN, h->actlen + off); /* XXX m_copyback is stupid */ 1036 m_copyback(m, off, h->actlen, sc->sc_intr_buffer); 1037 1038 hdr = mtod(m, ng_hci_event_pkt_t *); 1039 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) { 1040 NG_UBT_INFO( 1041 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n", 1042 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, 1043 hdr->length); 1044 1045 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat); 1046 1047 IF_LOCK(&sc->sc_inq); 1048 if (_IF_QFULL(&sc->sc_inq)) { 1049 NG_UBT_ERR( 1050 "%s: %s -Incoming queue is full. Dropping mbuf, len=%d\n", 1051 __func__, USBDEVNAME(sc->sc_dev), 1052 m->m_pkthdr.len); 1053 1054 _IF_DROP(&sc->sc_inq); 1055 NG_UBT_STAT_IERROR(sc->sc_stat); 1056 1057 NG_FREE_M(m); 1058 } else 1059 _IF_ENQUEUE(&sc->sc_inq, m); 1060 IF_UNLOCK(&sc->sc_inq); 1061 1062 /* Schedule SWI */ 1063 swi_sched(sc->sc_ith, 0); 1064 } else { 1065 NG_UBT_ERR( 1066 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n", 1067 __func__, USBDEVNAME(sc->sc_dev), hdr->length, 1068 m->m_pkthdr.len); 1069 1070 NG_UBT_STAT_IERROR(sc->sc_stat); 1071 NG_FREE_M(m); 1072 } 1073 done: 1074 ubt_intr_start(sc); 1075 } /* ubt_intr_complete */ 1076 1077 /* 1078 * Start bulk-in USB transfer (ACL data) 1079 */ 1080 1081 Static usbd_status 1082 ubt_bulk_in_start(ubt_softc_p sc) 1083 { 1084 usbd_status status; 1085 1086 /* Initialize a bulk-in USB transfer and then schedule it */ 1087 usbd_setup_xfer( 1088 sc->sc_bulk_in_xfer, 1089 sc->sc_bulk_in_pipe, 1090 (usbd_private_handle) sc, 1091 sc->sc_bulk_in_buffer, 1092 UBT_BULK_BUFFER_SIZE, 1093 USBD_SHORT_XFER_OK | USBD_NO_COPY, 1094 USBD_NO_TIMEOUT, 1095 ubt_bulk_in_complete); 1096 1097 status = usbd_transfer(sc->sc_bulk_in_xfer); 1098 if (status && status != USBD_IN_PROGRESS) { 1099 NG_UBT_ERR( 1100 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n", 1101 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1102 status); 1103 1104 return (status); 1105 } 1106 1107 return (USBD_NORMAL_COMPLETION); 1108 } /* ubt_bulk_in_start */ 1109 1110 /* 1111 * USB bulk-in transfer callback 1112 */ 1113 1114 Static void 1115 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s) 1116 { 1117 ubt_softc_p sc = (ubt_softc_p) p; 1118 struct mbuf *m = NULL; 1119 ng_hci_acldata_pkt_t *hdr = NULL; 1120 int len; 1121 1122 if (s == USBD_CANCELLED) { 1123 NG_UBT_INFO( 1124 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n", 1125 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe); 1126 1127 return; 1128 } 1129 1130 if (s != USBD_NORMAL_COMPLETION) { 1131 NG_UBT_WARN( 1132 "%s: %s - Bulk-in xfer failed. %s (%d)\n", 1133 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s); 1134 1135 if (s == USBD_STALLED) 1136 usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe); 1137 1138 NG_UBT_STAT_IERROR(sc->sc_stat); 1139 goto done; 1140 } 1141 1142 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen); 1143 1144 NG_UBT_INFO( 1145 "%s: %s - Got %d bytes from bulk-in pipe\n", 1146 __func__, USBDEVNAME(sc->sc_dev), h->actlen); 1147 1148 if (h->actlen < sizeof(*hdr)) 1149 goto done; 1150 1151 MGETHDR(m, M_DONTWAIT, MT_DATA); 1152 if (m == NULL) { 1153 NG_UBT_ALERT( 1154 "%s: %s - Could not allocate mbuf\n", __func__, USBDEVNAME(sc->sc_dev)); 1155 1156 NG_UBT_STAT_IERROR(sc->sc_stat); 1157 goto done; 1158 } 1159 1160 /* 1161 * Copy data from linear USB buffer into mbuf and check if we got 1162 * full ACL data frame. Fix ACL data frame header if required. 1163 */ 1164 1165 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) { 1166 len = 1; 1167 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT; 1168 } else 1169 len = 0; 1170 1171 m->m_pkthdr.len = 0; 1172 m->m_len = min(MHLEN, h->actlen + len); /* XXX m_copyback is stupid */ 1173 m_copyback(m, len, h->actlen, sc->sc_bulk_in_buffer); 1174 1175 hdr = mtod(m, ng_hci_acldata_pkt_t *); 1176 len = le16toh(hdr->length); 1177 1178 if (len == m->m_pkthdr.len - sizeof(*hdr)) { 1179 NG_UBT_INFO( 1180 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n", 1181 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, 1182 len); 1183 1184 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat); 1185 1186 IF_LOCK(&sc->sc_inq); 1187 if (_IF_QFULL(&sc->sc_inq)) { 1188 NG_UBT_ERR( 1189 "%s: %s -Incoming queue is full. Dropping mbuf, len=%d\n", 1190 __func__, USBDEVNAME(sc->sc_dev), 1191 m->m_pkthdr.len); 1192 1193 _IF_DROP(&sc->sc_inq); 1194 NG_UBT_STAT_IERROR(sc->sc_stat); 1195 1196 NG_FREE_M(m); 1197 } else 1198 _IF_ENQUEUE(&sc->sc_inq, m); 1199 IF_UNLOCK(&sc->sc_inq); 1200 1201 /* Schedule SWI */ 1202 swi_sched(sc->sc_ith, 0); 1203 } else { 1204 NG_UBT_ERR( 1205 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n", 1206 __func__, USBDEVNAME(sc->sc_dev), len, 1207 m->m_pkthdr.len); 1208 1209 NG_UBT_STAT_IERROR(sc->sc_stat); 1210 NG_FREE_M(m); 1211 } 1212 done: 1213 ubt_bulk_in_start(sc); 1214 } /* ubt_bulk_in_complete */ 1215 1216 /* 1217 * Start bulk-out USB transfer 1218 */ 1219 1220 Static usbd_status 1221 ubt_bulk_out_start(ubt_softc_p sc, struct mbuf *m) 1222 { 1223 usbd_status status = USBD_NORMAL_COMPLETION; 1224 1225 IF_LOCK(&sc->sc_aclq); 1226 1227 if (m != NULL) { 1228 if (_IF_QFULL(&sc->sc_aclq)) { 1229 NG_UBT_ERR( 1230 "%s: %s - Dropping HCI ACL frame, len=%d. Queue full\n", 1231 __func__, USBDEVNAME(sc->sc_dev), 1232 m->m_pkthdr.len); 1233 1234 _IF_DROP(&sc->sc_aclq); 1235 NG_UBT_STAT_OERROR(sc->sc_stat); 1236 1237 NG_FREE_M(m); 1238 } else 1239 _IF_ENQUEUE(&sc->sc_aclq, m); 1240 } else 1241 sc->sc_flags &= ~UBT_ACL_XMIT; 1242 1243 if (sc->sc_flags & UBT_ACL_XMIT) { 1244 NG_UBT_INFO( 1245 "%s: %s - Another bulk-out transfer is pending\n", 1246 __func__, USBDEVNAME(sc->sc_dev)); 1247 goto done; 1248 } 1249 1250 _IF_DEQUEUE(&sc->sc_aclq, m); 1251 if (m == NULL) { 1252 NG_UBT_INFO( 1253 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev)); 1254 goto done; 1255 } 1256 1257 /* 1258 * Check ACL data frame size and copy it back to linear USB 1259 * transfer buffer. 1260 */ 1261 1262 if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE) 1263 panic( 1264 "%s: %s - ACL data frame too big, size=%d, len=%d\n", 1265 __func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE, 1266 m->m_pkthdr.len); 1267 1268 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer); 1269 1270 /* Initialize a bulk-out USB transfer and then schedule it */ 1271 usbd_setup_xfer( 1272 sc->sc_bulk_out_xfer, 1273 sc->sc_bulk_out_pipe, 1274 (usbd_private_handle) sc, 1275 sc->sc_bulk_out_buffer, 1276 m->m_pkthdr.len, 1277 USBD_NO_COPY, 1278 USBD_DEFAULT_TIMEOUT, /* XXX */ 1279 ubt_bulk_out_complete); 1280 1281 status = usbd_transfer(sc->sc_bulk_out_xfer); 1282 if (status && status != USBD_IN_PROGRESS) { 1283 NG_UBT_ERR( 1284 "%s: %s - Could not start bulk-out transfer. %s (%d)\n", 1285 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1286 status); 1287 1288 _IF_DROP(&sc->sc_aclq); /* XXX */ 1289 NG_UBT_STAT_OERROR(sc->sc_stat); 1290 1291 /* XXX FIXME: should we try to start another transfer? */ 1292 } else { 1293 NG_UBT_INFO( 1294 "%s: %s - Bulk-out transfer has been started, len=%d\n", 1295 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len); 1296 1297 sc->sc_flags |= UBT_ACL_XMIT; 1298 1299 status = USBD_NORMAL_COMPLETION; 1300 } 1301 1302 NG_FREE_M(m); 1303 done: 1304 IF_UNLOCK(&sc->sc_aclq); 1305 1306 return (status); 1307 } /* ubt_bulk_out_start */ 1308 1309 /* 1310 * USB bulk-out transfer callback 1311 */ 1312 1313 Static void 1314 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s) 1315 { 1316 ubt_softc_p sc = (ubt_softc_p) p; 1317 1318 if (s == USBD_CANCELLED) { 1319 NG_UBT_INFO( 1320 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n", 1321 __func__, USBDEVNAME(sc->sc_dev), 1322 sc->sc_bulk_out_pipe); 1323 1324 return; 1325 } 1326 1327 if (s != USBD_NORMAL_COMPLETION) { 1328 NG_UBT_WARN( 1329 "%s: %s - Bulk-out xfer failed. %s (%d)\n", 1330 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s); 1331 1332 if (s == USBD_STALLED) 1333 usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe); 1334 1335 NG_UBT_STAT_OERROR(sc->sc_stat); 1336 } else { 1337 NG_UBT_INFO( 1338 "%s: %s - Sent %d bytes to bulk-out pipe\n", 1339 __func__, USBDEVNAME(sc->sc_dev), h->actlen); 1340 1341 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen); 1342 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat); 1343 } 1344 1345 ubt_bulk_out_start(sc, NULL /* completed request */); 1346 } /* ubt_bulk_out_complete */ 1347 1348 /* 1349 * Start Isochronous-in USB transfer 1350 */ 1351 1352 Static usbd_status 1353 ubt_isoc_in_start(ubt_softc_p sc) 1354 { 1355 usbd_status status; 1356 int i; 1357 1358 /* Initialize an isoc-in USB transfer and then schedule it. */ 1359 1360 for (i = 0; i < sc->sc_isoc_nframes; i++) 1361 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size; 1362 1363 usbd_setup_isoc_xfer( 1364 sc->sc_isoc_in_xfer, 1365 sc->sc_isoc_in_pipe, 1366 (usbd_private_handle) sc, 1367 sc->sc_isoc_in_frlen, 1368 sc->sc_isoc_nframes, 1369 USBD_NO_COPY, /* XXX flags */ 1370 ubt_isoc_in_complete); 1371 1372 status = usbd_transfer(sc->sc_isoc_in_xfer); 1373 if (status && status != USBD_IN_PROGRESS) { 1374 NG_UBT_ERR( 1375 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n", 1376 __func__, USBDEVNAME(sc->sc_dev), 1377 usbd_errstr(status), status); 1378 1379 return (status); 1380 } 1381 1382 return (USBD_NORMAL_COMPLETION); 1383 } /* ubt_isoc_in_start */ 1384 1385 /* 1386 * USB isochronous transfer callback 1387 */ 1388 1389 Static void 1390 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s) 1391 { 1392 ubt_softc_p sc = (ubt_softc_p) p; 1393 struct mbuf *m = NULL; 1394 ng_hci_scodata_pkt_t *hdr = NULL; 1395 u_int8_t *b = NULL; 1396 int i; 1397 1398 if (s == USBD_CANCELLED) { 1399 NG_UBT_INFO( 1400 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n", 1401 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe); 1402 1403 return; 1404 } 1405 1406 if (s != USBD_NORMAL_COMPLETION) { 1407 NG_UBT_WARN( 1408 "%s: %s - Isoc-in xfer failed. %s (%d)\n", 1409 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s); 1410 1411 if (s == USBD_STALLED) 1412 usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe); 1413 1414 NG_UBT_STAT_IERROR(sc->sc_stat); 1415 goto done; 1416 } 1417 1418 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen); 1419 1420 NG_UBT_INFO( 1421 "%s: %s - Got %d bytes from isoc-in pipe\n", 1422 __func__, USBDEVNAME(sc->sc_dev), h->actlen); 1423 1424 if (h->actlen < sizeof(*hdr)) 1425 goto done; 1426 1427 /* Copy SCO data frame to mbuf */ 1428 1429 MGETHDR(m, M_DONTWAIT, MT_DATA); 1430 if (m == NULL) { 1431 NG_UBT_ALERT( 1432 "%s: %s - Could not allocate mbuf\n", 1433 __func__, USBDEVNAME(sc->sc_dev)); 1434 1435 NG_UBT_STAT_IERROR(sc->sc_stat); 1436 goto done; 1437 } 1438 1439 /* Fix SCO data frame header if required */ 1440 1441 if (sc->sc_flags & UBT_HAVE_FRAME_TYPE) { 1442 m->m_pkthdr.len = m->m_len = 0; 1443 } else { 1444 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT; 1445 m->m_pkthdr.len = m->m_len = 1; 1446 } 1447 1448 /* 1449 * XXX FIXME: how do we know how many frames we have received? 1450 * XXX use frlen for now. 1451 * XXX is that correct? 1452 */ 1453 1454 b = (u_int8_t *) sc->sc_isoc_in_buffer; 1455 1456 for (i = 0; i < sc->sc_isoc_nframes; i++) { 1457 b += (i * sc->sc_isoc_size); 1458 1459 if (sc->sc_isoc_in_frlen[i] > 0) 1460 m_copyback(m, m->m_pkthdr.len, 1461 sc->sc_isoc_in_frlen[i], b); 1462 } 1463 1464 NG_UBT_M_PULLUP(m, sizeof(*hdr)); 1465 if (m == NULL) { 1466 NG_UBT_STAT_IERROR(sc->sc_stat); 1467 goto done; 1468 } 1469 1470 hdr = mtod(m, ng_hci_scodata_pkt_t *); 1471 1472 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) { 1473 NG_UBT_INFO( 1474 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n", 1475 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, 1476 hdr->length); 1477 1478 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat); 1479 1480 IF_LOCK(&sc->sc_inq); 1481 if (_IF_QFULL(&sc->sc_inq)) { 1482 NG_UBT_ERR( 1483 "%s: %s -Incoming queue is full. Dropping mbuf, len=%d\n", 1484 __func__, USBDEVNAME(sc->sc_dev), 1485 m->m_pkthdr.len); 1486 1487 _IF_DROP(&sc->sc_inq); 1488 NG_UBT_STAT_IERROR(sc->sc_stat); 1489 1490 NG_FREE_M(m); 1491 } else 1492 _IF_ENQUEUE(&sc->sc_inq, m); 1493 IF_UNLOCK(&sc->sc_inq); 1494 1495 /* Schedule SWI */ 1496 swi_sched(sc->sc_ith, 0); 1497 } else { 1498 NG_UBT_ERR( 1499 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n", 1500 __func__, USBDEVNAME(sc->sc_dev), hdr->length, 1501 m->m_pkthdr.len); 1502 1503 NG_UBT_STAT_IERROR(sc->sc_stat); 1504 NG_FREE_M(m); 1505 } 1506 done: 1507 ubt_isoc_in_start(sc); 1508 } /* ubt_bulk_in_complete */ 1509 1510 /* 1511 * Start isochronous-out USB transfer 1512 */ 1513 1514 Static usbd_status 1515 ubt_isoc_out_start(ubt_softc_p sc, struct mbuf *m) 1516 { 1517 u_int8_t *b = NULL; 1518 int i, len, nframes; 1519 usbd_status status = USBD_NORMAL_COMPLETION; 1520 1521 IF_LOCK(&sc->sc_scoq); 1522 1523 if (m != NULL) { 1524 if (_IF_QFULL(&sc->sc_scoq)) { 1525 NG_UBT_ERR( 1526 "%s: %s - Dropping HCI SCO frame, len=%d. Queue full\n", 1527 __func__, USBDEVNAME(sc->sc_dev), 1528 m->m_pkthdr.len); 1529 1530 _IF_DROP(&sc->sc_scoq); 1531 NG_UBT_STAT_OERROR(sc->sc_stat); 1532 1533 NG_FREE_M(m); 1534 } else 1535 _IF_ENQUEUE(&sc->sc_scoq, m); 1536 } else 1537 sc->sc_flags &= ~UBT_SCO_XMIT; 1538 1539 if (sc->sc_flags & UBT_SCO_XMIT) { 1540 NG_UBT_INFO( 1541 "%s: %s - Another isoc-out transfer is pending\n", 1542 __func__, USBDEVNAME(sc->sc_dev)); 1543 goto done; 1544 } 1545 1546 _IF_DEQUEUE(&sc->sc_scoq, m); 1547 if (m == NULL) { 1548 NG_UBT_INFO( 1549 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev)); 1550 goto done; 1551 } 1552 1553 /* Copy entire SCO frame into USB transfer buffer and start transfer */ 1554 1555 b = (u_int8_t *) sc->sc_isoc_out_buffer; 1556 nframes = 0; 1557 1558 for (i = 0; i < sc->sc_isoc_nframes; i++) { 1559 b += (i * sc->sc_isoc_size); 1560 1561 len = min(m->m_pkthdr.len, sc->sc_isoc_size); 1562 if (len > 0) { 1563 m_copydata(m, 0, len, b); 1564 m_adj(m, len); 1565 nframes ++; 1566 } 1567 1568 sc->sc_isoc_out_frlen[i] = len; 1569 } 1570 1571 if (m->m_pkthdr.len > 0) 1572 panic( 1573 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n", 1574 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes, 1575 sc->sc_isoc_size, m->m_pkthdr.len); 1576 1577 NG_FREE_M(m); 1578 1579 /* Initialize an isoc-out USB transfer and then schedule it. */ 1580 1581 usbd_setup_isoc_xfer( 1582 sc->sc_isoc_out_xfer, 1583 sc->sc_isoc_out_pipe, 1584 (usbd_private_handle) sc, 1585 sc->sc_isoc_out_frlen, 1586 nframes, 1587 USBD_NO_COPY, 1588 ubt_isoc_out_complete); 1589 1590 status = usbd_transfer(sc->sc_isoc_out_xfer); 1591 if (status && status != USBD_IN_PROGRESS) { 1592 NG_UBT_ERR( 1593 "%s: %s - Could not start isoc-out transfer. %s (%d)\n", 1594 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1595 status); 1596 1597 _IF_DROP(&sc->sc_scoq); /* XXX */ 1598 NG_UBT_STAT_OERROR(sc->sc_stat); 1599 } else { 1600 NG_UBT_INFO( 1601 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n", 1602 __func__, USBDEVNAME(sc->sc_dev), nframes, 1603 sc->sc_isoc_size); 1604 1605 sc->sc_flags |= UBT_SCO_XMIT; 1606 1607 status = USBD_NORMAL_COMPLETION; 1608 } 1609 done: 1610 IF_UNLOCK(&sc->sc_scoq); 1611 1612 return (status); 1613 } /* ubt_isoc_out_start */ 1614 1615 /* 1616 * USB isoc-out. transfer callback 1617 */ 1618 1619 Static void 1620 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s) 1621 { 1622 ubt_softc_p sc = (ubt_softc_p) p; 1623 1624 if (s == USBD_CANCELLED) { 1625 NG_UBT_INFO( 1626 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n", 1627 __func__, USBDEVNAME(sc->sc_dev), 1628 sc->sc_isoc_out_pipe); 1629 1630 return; 1631 } 1632 1633 if (s != USBD_NORMAL_COMPLETION) { 1634 NG_UBT_WARN( 1635 "%s: %s - Isoc-out xfer failed. %s (%d)\n", 1636 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s); 1637 1638 if (s == USBD_STALLED) 1639 usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe); 1640 1641 NG_UBT_STAT_OERROR(sc->sc_stat); 1642 } else { 1643 NG_UBT_INFO( 1644 "%s: %s - Sent %d bytes to isoc-out pipe\n", 1645 __func__, USBDEVNAME(sc->sc_dev), h->actlen); 1646 1647 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen); 1648 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat); 1649 } 1650 1651 ubt_isoc_out_start(sc, NULL /* completed request */); 1652 } /* ubt_isoc_out_complete */ 1653 1654 /* 1655 * SWI interrupt handler 1656 */ 1657 1658 Static void 1659 ubt_swi_intr(void *context) 1660 { 1661 ubt_softc_p sc = (ubt_softc_p) context; 1662 struct mbuf *m = NULL; 1663 int error; 1664 1665 if (sc->sc_hook != NULL && NG_HOOK_IS_VALID(sc->sc_hook)) { 1666 for (;;) { 1667 IF_DEQUEUE(&sc->sc_inq, m); 1668 if (m == NULL) 1669 break; 1670 1671 NG_SEND_DATA_ONLY(error, sc->sc_hook, m); 1672 if (error != 0) 1673 NG_UBT_STAT_IERROR(sc->sc_stat); 1674 } 1675 } else { 1676 IF_LOCK(&sc->sc_inq); 1677 for (;;) { 1678 _IF_DEQUEUE(&sc->sc_inq, m); 1679 if (m == NULL) 1680 break; 1681 1682 NG_UBT_STAT_IERROR(sc->sc_stat); 1683 NG_FREE_M(m); 1684 } 1685 IF_UNLOCK(&sc->sc_inq); 1686 } 1687 } /* ubt_swi_intr */ 1688 1689 /**************************************************************************** 1690 **************************************************************************** 1691 ** Netgraph specific 1692 **************************************************************************** 1693 ****************************************************************************/ 1694 1695 /* 1696 * Netgraph node constructor. Do not allow to create node of this type. 1697 */ 1698 1699 Static int 1700 ng_ubt_constructor(node_p node) 1701 { 1702 return (EINVAL); 1703 } /* ng_ubt_constructor */ 1704 1705 /* 1706 * Netgraph node destructor. Destroy node only when device has been detached 1707 */ 1708 1709 Static int 1710 ng_ubt_shutdown(node_p node) 1711 { 1712 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node); 1713 1714 /* Let old node go */ 1715 NG_NODE_SET_PRIVATE(node, NULL); 1716 NG_NODE_UNREF(node); 1717 1718 if (sc == NULL) 1719 goto done; 1720 1721 /* Create Netgraph node */ 1722 if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) { 1723 printf("%s: Could not create Netgraph node\n", 1724 USBDEVNAME(sc->sc_dev)); 1725 sc->sc_node = NULL; 1726 goto done; 1727 } 1728 1729 /* Name node */ 1730 if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) { 1731 printf("%s: Could not name Netgraph node\n", 1732 USBDEVNAME(sc->sc_dev)); 1733 NG_NODE_UNREF(sc->sc_node); 1734 sc->sc_node = NULL; 1735 goto done; 1736 } 1737 1738 NG_NODE_SET_PRIVATE(sc->sc_node, sc); 1739 done: 1740 return (0); 1741 } /* ng_ubt_shutdown */ 1742 1743 /* 1744 * Create new hook. There can only be one. 1745 */ 1746 1747 Static int 1748 ng_ubt_newhook(node_p node, hook_p hook, char const *name) 1749 { 1750 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node); 1751 usbd_status status; 1752 1753 if (strcmp(name, NG_UBT_HOOK) != 0) 1754 return (EINVAL); 1755 1756 if (sc->sc_hook != NULL) 1757 return (EISCONN); 1758 1759 sc->sc_hook = hook; 1760 1761 /* Interrupt */ 1762 status = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep, 1763 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe); 1764 if (status) { 1765 NG_UBT_ALERT( 1766 "%s: %s - Could not open interrupt pipe. %s (%d)\n", 1767 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1768 status); 1769 goto fail; 1770 } 1771 1772 /* Bulk-in */ 1773 status = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep, 1774 USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe); 1775 if (status) { 1776 NG_UBT_ALERT( 1777 "%s: %s - Could not open bulk-in pipe. %s (%d)\n", 1778 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1779 status); 1780 goto fail; 1781 } 1782 1783 /* Bulk-out */ 1784 status = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep, 1785 USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe); 1786 if (status) { 1787 NG_UBT_ALERT( 1788 "%s: %s - Could not open bulk-out pipe. %s (%d)\n", 1789 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1790 status); 1791 goto fail; 1792 } 1793 1794 #if __broken__ /* XXX FIXME */ 1795 /* Isoc-in */ 1796 status = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep, 1797 USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe); 1798 if (status) { 1799 NG_UBT_ALERT( 1800 "%s: %s - Could not open isoc-in pipe. %s (%d)\n", 1801 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1802 status); 1803 goto fail; 1804 } 1805 1806 /* Isoc-out */ 1807 status = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep, 1808 USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe); 1809 if (status) { 1810 NG_UBT_ALERT( 1811 "%s: %s - Could not open isoc-out pipe. %s (%d)\n", 1812 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1813 status); 1814 goto fail; 1815 } 1816 #endif /* __broken__ */ 1817 1818 return (0); 1819 fail: 1820 ng_ubt_reset(sc); 1821 sc->sc_hook = NULL; 1822 1823 return (ENXIO); 1824 } /* ng_ubt_newhook */ 1825 1826 /* 1827 * Connect hook. Start incoming USB transfers 1828 */ 1829 1830 Static int 1831 ng_ubt_connect(hook_p hook) 1832 { 1833 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 1834 usbd_status status; 1835 1836 /* Start intr transfer */ 1837 status = ubt_intr_start(sc); 1838 if (status != USBD_NORMAL_COMPLETION) { 1839 NG_UBT_ALERT( 1840 "%s: %s - Could not start interrupt transfer. %s (%d)\n", 1841 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1842 status); 1843 goto fail; 1844 } 1845 1846 /* Start bulk-in transfer */ 1847 status = ubt_bulk_in_start(sc); 1848 if (status != USBD_NORMAL_COMPLETION) { 1849 NG_UBT_ALERT( 1850 "%s: %s - Could not start bulk-in transfer. %s (%d)\n", 1851 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1852 status); 1853 goto fail; 1854 } 1855 1856 #if __broken__ /* XXX FIXME */ 1857 /* Start isoc-in transfer */ 1858 status = ubt_isoc_in_start(sc); 1859 if (status != USBD_NORMAL_COMPLETION) { 1860 NG_UBT_ALERT( 1861 "%s: %s - Could not start isoc-in transfer. %s (%d)\n", 1862 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status), 1863 status); 1864 goto fail; 1865 } 1866 #endif /* __broken__ */ 1867 1868 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 1869 1870 return (0); 1871 fail: 1872 ng_ubt_reset(sc); 1873 sc->sc_hook = NULL; 1874 1875 return (ENXIO); 1876 } /* ng_ubt_connect */ 1877 1878 /* 1879 * Disconnect hook 1880 */ 1881 1882 Static int 1883 ng_ubt_disconnect(hook_p hook) 1884 { 1885 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 1886 1887 if (sc != NULL) { 1888 if (hook != sc->sc_hook) 1889 return (EINVAL); 1890 1891 ng_ubt_reset(sc); 1892 sc->sc_hook = NULL; 1893 } 1894 1895 return (0); 1896 } /* ng_ubt_disconnect */ 1897 1898 /* 1899 * Process control message 1900 */ 1901 1902 Static int 1903 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook) 1904 { 1905 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(node); 1906 struct ng_mesg *msg = NULL, *rsp = NULL; 1907 int error = 0, queue, qlen; 1908 struct ifqueue *q = NULL; 1909 1910 if (sc == NULL) { 1911 NG_FREE_ITEM(item); 1912 return (EHOSTDOWN); 1913 } 1914 1915 NGI_GET_MSG(item, msg); 1916 1917 switch (msg->header.typecookie) { 1918 case NGM_GENERIC_COOKIE: 1919 switch (msg->header.cmd) { 1920 case NGM_TEXT_STATUS: 1921 NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT); 1922 if (rsp == NULL) 1923 error = ENOMEM; 1924 else 1925 snprintf(rsp->data, NG_TEXTRESPONSE, 1926 "Hook: %s\n" \ 1927 "Flags: %#x\n" \ 1928 "Debug: %d\n" \ 1929 "CMD queue: [have:%d,max:%d]\n" \ 1930 "ACL queue: [have:%d,max:%d]\n" \ 1931 "SCO queue: [have:%d,max:%d]\n" \ 1932 "Inp queue: [have:%d,max:%d]", 1933 (sc->sc_hook != NULL)? NG_UBT_HOOK : "", 1934 sc->sc_flags, 1935 sc->sc_debug, 1936 _IF_QLEN(&sc->sc_cmdq), /* XXX */ 1937 sc->sc_cmdq.ifq_maxlen, /* XXX */ 1938 _IF_QLEN(&sc->sc_aclq), /* XXX */ 1939 sc->sc_aclq.ifq_maxlen, /* XXX */ 1940 _IF_QLEN(&sc->sc_scoq), /* XXX */ 1941 sc->sc_scoq.ifq_maxlen, /* XXX */ 1942 _IF_QLEN(&sc->sc_inq), /* XXX */ 1943 sc->sc_inq.ifq_maxlen /* XXX */ ); 1944 break; 1945 1946 default: 1947 error = EINVAL; 1948 break; 1949 } 1950 break; 1951 1952 case NGM_UBT_COOKIE: 1953 switch (msg->header.cmd) { 1954 case NGM_UBT_NODE_SET_DEBUG: 1955 if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep)) 1956 error = EMSGSIZE; 1957 else 1958 sc->sc_debug = 1959 *((ng_ubt_node_debug_ep *)(msg->data)); 1960 break; 1961 1962 case NGM_UBT_NODE_GET_DEBUG: 1963 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep), 1964 M_NOWAIT); 1965 if (rsp == NULL) 1966 error = ENOMEM; 1967 else 1968 *((ng_ubt_node_debug_ep *)(rsp->data)) = 1969 sc->sc_debug; 1970 break; 1971 1972 case NGM_UBT_NODE_SET_QLEN: 1973 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) 1974 error = EMSGSIZE; 1975 else { 1976 queue = ((ng_ubt_node_qlen_ep *) 1977 (msg->data))->queue; 1978 qlen = ((ng_ubt_node_qlen_ep *) 1979 (msg->data))->qlen; 1980 1981 if (qlen <= 0) { 1982 error = EINVAL; 1983 break; 1984 } 1985 1986 switch (queue) { 1987 case NGM_UBT_NODE_QUEUE_IN: 1988 q = &sc->sc_inq; 1989 break; 1990 1991 case NGM_UBT_NODE_QUEUE_CMD: 1992 q = &sc->sc_cmdq; 1993 break; 1994 1995 case NGM_UBT_NODE_QUEUE_ACL: 1996 q = &sc->sc_aclq; 1997 break; 1998 1999 case NGM_UBT_NODE_QUEUE_SCO: 2000 q = &sc->sc_scoq; 2001 break; 2002 2003 default: 2004 q = NULL; 2005 error = EINVAL; 2006 break; 2007 } 2008 2009 if (q != NULL) 2010 q->ifq_maxlen = qlen; /* XXX */ 2011 } 2012 break; 2013 2014 case NGM_UBT_NODE_GET_QLEN: 2015 if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) { 2016 error = EMSGSIZE; 2017 break; 2018 } 2019 2020 queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue; 2021 switch (queue) { 2022 case NGM_UBT_NODE_QUEUE_IN: 2023 q = &sc->sc_inq; 2024 break; 2025 2026 case NGM_UBT_NODE_QUEUE_CMD: 2027 q = &sc->sc_cmdq; 2028 break; 2029 2030 case NGM_UBT_NODE_QUEUE_ACL: 2031 q = &sc->sc_aclq; 2032 break; 2033 2034 case NGM_UBT_NODE_QUEUE_SCO: 2035 q = &sc->sc_scoq; 2036 break; 2037 2038 default: 2039 q = NULL; 2040 error = EINVAL; 2041 break; 2042 } 2043 2044 if (q != NULL) { 2045 NG_MKRESPONSE(rsp, msg, 2046 sizeof(ng_ubt_node_qlen_ep), M_NOWAIT); 2047 if (rsp == NULL) { 2048 error = ENOMEM; 2049 break; 2050 } 2051 2052 ((ng_ubt_node_qlen_ep *)(rsp->data))->queue = 2053 queue; 2054 ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen = 2055 q->ifq_maxlen; /* XXX */ 2056 } 2057 break; 2058 2059 case NGM_UBT_NODE_GET_STAT: 2060 NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep), 2061 M_NOWAIT); 2062 if (rsp == NULL) 2063 error = ENOMEM; 2064 else 2065 bcopy(&sc->sc_stat, rsp->data, 2066 sizeof(ng_ubt_node_stat_ep)); 2067 break; 2068 2069 case NGM_UBT_NODE_RESET_STAT: 2070 NG_UBT_STAT_RESET(sc->sc_stat); 2071 break; 2072 2073 default: 2074 error = EINVAL; 2075 break; 2076 } 2077 break; 2078 2079 default: 2080 error = EINVAL; 2081 break; 2082 } 2083 2084 NG_RESPOND_MSG(error, node, item, rsp); 2085 NG_FREE_MSG(msg); 2086 2087 return (error); 2088 } /* ng_ubt_rcvmsg */ 2089 2090 /* 2091 * Process data 2092 */ 2093 2094 Static int 2095 ng_ubt_rcvdata(hook_p hook, item_p item) 2096 { 2097 ubt_softc_p sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 2098 struct mbuf *m = NULL; 2099 usbd_status (*f)(ubt_softc_p, struct mbuf *) = NULL; 2100 int error = 0; 2101 2102 if (sc == NULL) { 2103 error = EHOSTDOWN; 2104 goto done; 2105 } 2106 2107 if (hook != sc->sc_hook) { 2108 error = EINVAL; 2109 goto done; 2110 } 2111 2112 /* Deatch mbuf and get HCI frame type */ 2113 NGI_GET_M(item, m); 2114 2115 /* Process HCI frame */ 2116 switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */ 2117 case NG_HCI_CMD_PKT: 2118 f = ubt_request_start; 2119 break; 2120 2121 case NG_HCI_ACL_DATA_PKT: 2122 f = ubt_bulk_out_start; 2123 break; 2124 2125 #if __broken__ /* XXX FIXME */ 2126 case NG_HCI_SCO_DATA_PKT: 2127 f = ubt_isoc_out_start; 2128 break; 2129 #endif /* __broken__ */ 2130 2131 default: 2132 NG_UBT_ERR( 2133 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n", 2134 __func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *), 2135 m->m_pkthdr.len); 2136 2137 NG_FREE_M(m); 2138 error = EINVAL; 2139 2140 goto done; 2141 /* NOT REACHED */ 2142 } 2143 2144 /* Loose frame type, if required */ 2145 if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE)) 2146 m_adj(m, sizeof(u_int8_t)); 2147 2148 if ((*f)(sc, m) != USBD_NORMAL_COMPLETION) 2149 error = EIO; 2150 done: 2151 NG_FREE_ITEM(item); 2152 2153 return (error); 2154 } /* ng_ubt_rcvdata */ 2155 2156 /* 2157 * Abort transfers and close all USB pipes. 2158 */ 2159 2160 Static void 2161 ng_ubt_reset(ubt_softc_p sc) 2162 { 2163 /* Abort transfers and close all USB pipes */ 2164 2165 /* Interrupt */ 2166 if (sc->sc_intr_pipe != NULL) { 2167 usbd_abort_pipe(sc->sc_intr_pipe); 2168 usbd_close_pipe(sc->sc_intr_pipe); 2169 sc->sc_intr_pipe = NULL; 2170 } 2171 2172 /* Bulk-in/out */ 2173 if (sc->sc_bulk_in_pipe != NULL) { 2174 usbd_abort_pipe(sc->sc_bulk_in_pipe); 2175 usbd_close_pipe(sc->sc_bulk_in_pipe); 2176 sc->sc_bulk_in_pipe = NULL; 2177 } 2178 if (sc->sc_bulk_out_pipe != NULL) { 2179 usbd_abort_pipe(sc->sc_bulk_out_pipe); 2180 usbd_close_pipe(sc->sc_bulk_out_pipe); 2181 sc->sc_bulk_out_pipe = NULL; 2182 } 2183 2184 /* Isoc-in/out */ 2185 if (sc->sc_isoc_in_pipe != NULL) { 2186 usbd_abort_pipe(sc->sc_isoc_in_pipe); 2187 usbd_close_pipe(sc->sc_isoc_in_pipe); 2188 sc->sc_isoc_in_pipe = NULL; 2189 } 2190 if (sc->sc_isoc_out_pipe != NULL) { 2191 usbd_abort_pipe(sc->sc_isoc_out_pipe); 2192 usbd_close_pipe(sc->sc_isoc_out_pipe); 2193 sc->sc_isoc_out_pipe = NULL; 2194 } 2195 2196 /* Cleanup queues */ 2197 IF_DRAIN(&sc->sc_cmdq); 2198 IF_DRAIN(&sc->sc_aclq); 2199 IF_DRAIN(&sc->sc_scoq); 2200 IF_DRAIN(&sc->sc_inq); 2201 } /* ng_ubt_reset */ 2202 2203