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