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