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