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