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