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