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