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