1 /* $NetBSD: ugenhc.c,v 1.8 2010/02/23 14:05:04 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2009, 2010 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 /* 29 * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. 30 * All rights reserved. 31 * 32 * This code is derived from software contributed to The NetBSD Foundation 33 * by Lennart Augustsson (lennart@augustsson.net) at 34 * Carlstedt Research & Technology. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 46 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 47 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 49 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 51 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 52 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 53 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 55 * POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58 /* 59 * This rump driver attaches ugen as a kernel usb host controller. 60 * It's still somewhat under the hammer .... 61 */ 62 63 #include <sys/cdefs.h> 64 __KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.8 2010/02/23 14:05:04 pooka Exp $"); 65 66 #include <sys/param.h> 67 #include <sys/bus.h> 68 #include <sys/conf.h> 69 #include <sys/device.h> 70 #include <sys/fcntl.h> 71 #include <sys/kmem.h> 72 #include <sys/kernel.h> 73 #include <sys/kthread.h> 74 75 #include <dev/usb/usb.h> 76 #include <dev/usb/usbdi.h> 77 #include <dev/usb/usbhid.h> 78 #include <dev/usb/usbdivar.h> 79 #include <dev/usb/usb_mem.h> 80 #include <dev/usb/usbroothub_subr.h> 81 82 #include <rump/rumpuser.h> 83 84 #include "rump_private.h" 85 #include "rump_dev_private.h" 86 87 #define UGEN_NEPTS 16 88 #define UGEN_EPT_CTRL 0 /* ugenx.00 is the control endpoint */ 89 90 struct ugenhc_softc { 91 struct usbd_bus sc_bus; 92 int sc_devnum; 93 94 int sc_ugenfd[UGEN_NEPTS]; 95 int sc_fdmodes[UGEN_NEPTS]; 96 97 int sc_port_status; 98 int sc_port_change; 99 int sc_addr; 100 int sc_conf; 101 102 struct lwp *sc_rhintr; 103 usbd_xfer_handle sc_intrxfer; 104 }; 105 106 static int ugenhc_probe(struct device *, struct cfdata *, void *); 107 static void ugenhc_attach(struct device *, struct device *, void *); 108 109 CFATTACH_DECL_NEW(ugenhc, sizeof(struct ugenhc_softc), 110 ugenhc_probe, ugenhc_attach, NULL, NULL); 111 112 struct rusb_xfer { 113 struct usbd_xfer rusb_xfer; 114 int rusb_status; /* now this is a cheap trick */ 115 }; 116 #define RUSB(x) ((struct rusb_xfer *)x) 117 118 #define UGENDEV_BASESTR "/dev/ugen" 119 #define UGENDEV_BUFSIZE 32 120 static void 121 makeugendevstr(int devnum, int endpoint, char *buf) 122 { 123 124 CTASSERT(UGENDEV_BUFSIZE > sizeof(UGENDEV_BASESTR)+sizeof("0.00")+1); 125 sprintf(buf, "%s%d.%02d", UGENDEV_BASESTR, devnum, endpoint); 126 } 127 128 /* 129 * Our fictional hubbie. 130 */ 131 132 static const usb_device_descriptor_t rumphub_udd = { 133 .bLength = USB_DEVICE_DESCRIPTOR_SIZE, 134 .bDescriptorType = UDESC_DEVICE, 135 .bDeviceClass = UDCLASS_HUB, 136 .bDeviceSubClass = UDSUBCLASS_HUB, 137 .bDeviceProtocol = UDPROTO_FSHUB, 138 .bMaxPacketSize = 64, 139 .idVendor = { 0x75, 0x72 }, 140 .idProduct = { 0x70, 0x6d }, 141 .bNumConfigurations = 1, 142 }; 143 144 static const usb_config_descriptor_t rumphub_ucd = { 145 .bLength = USB_CONFIG_DESCRIPTOR_SIZE, 146 .bDescriptorType = UDESC_CONFIG, 147 .wTotalLength = { USB_CONFIG_DESCRIPTOR_SIZE 148 + USB_INTERFACE_DESCRIPTOR_SIZE 149 + USB_ENDPOINT_DESCRIPTOR_SIZE }, 150 .bNumInterface = 1, 151 .bmAttributes = UC_SELF_POWERED | UC_ATTR_MBO, 152 }; 153 /* XXX: spec says UC_ATTR_MBO is reserved and set to one. required? */ 154 155 static const usb_interface_descriptor_t rumphub_uid = { 156 .bLength = USB_INTERFACE_DESCRIPTOR_SIZE, 157 .bDescriptorType = UDESC_INTERFACE, 158 .bInterfaceNumber = 0, 159 .bNumEndpoints = 1, 160 .bInterfaceClass = UICLASS_HUB, 161 .bInterfaceSubClass = UISUBCLASS_HUB, 162 .bInterfaceProtocol = UIPROTO_FSHUB, 163 }; 164 165 static const usb_endpoint_descriptor_t rumphub_epd = { 166 .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE, 167 .bDescriptorType = UDESC_ENDPOINT, 168 .bmAttributes = UE_INTERRUPT, 169 .wMaxPacketSize = {64, 0}, 170 }; 171 172 static const usb_hub_descriptor_t rumphub_hdd = { 173 .bDescLength = USB_HUB_DESCRIPTOR_SIZE, 174 .bDescriptorType = UDESC_HUB, 175 .bNbrPorts = 1, 176 }; 177 178 static usbd_status 179 rumpusb_root_ctrl_start(usbd_xfer_handle xfer) 180 { 181 usb_device_request_t *req = &xfer->request; 182 struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private; 183 int len, totlen, value, curlen, err; 184 uint8_t *buf = NULL; 185 186 len = totlen = UGETW(req->wLength); 187 if (len) 188 buf = KERNADDR(&xfer->dmabuf, 0); 189 value = UGETW(req->wValue); 190 191 #define C(x,y) ((x) | ((y) << 8)) 192 switch(C(req->bRequest, req->bmRequestType)) { 193 194 case C(UR_GET_CONFIG, UT_READ_DEVICE): 195 if (len > 0) { 196 *buf = sc->sc_conf; 197 totlen = 1; 198 } 199 break; 200 201 case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): 202 switch (value >> 8) { 203 case UDESC_DEVICE: 204 totlen = min(len, USB_DEVICE_DESCRIPTOR_SIZE); 205 memcpy(buf, &rumphub_udd, totlen); 206 break; 207 208 case UDESC_CONFIG: 209 totlen = 0; 210 curlen = min(len, USB_CONFIG_DESCRIPTOR_SIZE); 211 memcpy(buf, &rumphub_ucd, curlen); 212 len -= curlen; 213 buf += curlen; 214 totlen += curlen; 215 216 curlen = min(len, USB_INTERFACE_DESCRIPTOR_SIZE); 217 memcpy(buf, &rumphub_uid, curlen); 218 len -= curlen; 219 buf += curlen; 220 totlen += curlen; 221 222 curlen = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE); 223 memcpy(buf, &rumphub_epd, curlen); 224 len -= curlen; 225 buf += curlen; 226 totlen += curlen; 227 break; 228 229 case UDESC_STRING: 230 #define sd ((usb_string_descriptor_t *)buf) 231 switch (value & 0xff) { 232 case 0: /* Language table */ 233 totlen = usb_makelangtbl(sd, len); 234 break; 235 case 1: /* Vendor */ 236 totlen = usb_makestrdesc(sd, len, "rod nevada"); 237 break; 238 case 2: /* Product */ 239 totlen = usb_makestrdesc(sd, len, 240 "RUMPUSBHC root hub"); 241 break; 242 } 243 #undef sd 244 break; 245 246 default: 247 panic("unhandled read device request"); 248 break; 249 } 250 break; 251 252 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): 253 if (value >= USB_MAX_DEVICES) { 254 err = USBD_IOERROR; 255 goto ret; 256 } 257 sc->sc_addr = value; 258 break; 259 260 case C(UR_SET_CONFIG, UT_WRITE_DEVICE): 261 if (value != 0 && value != 1) { 262 err = USBD_IOERROR; 263 goto ret; 264 } 265 sc->sc_conf = value; 266 break; 267 268 case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): 269 switch (value) { 270 case UHF_PORT_RESET: 271 sc->sc_port_change |= UPS_C_PORT_RESET; 272 break; 273 case UHF_PORT_POWER: 274 break; 275 default: 276 panic("unhandled"); 277 } 278 break; 279 280 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): 281 sc->sc_port_change &= ~value; 282 break; 283 284 case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): 285 totlen = min(len, USB_HUB_DESCRIPTOR_SIZE); 286 memcpy(buf, &rumphub_hdd, totlen); 287 break; 288 289 case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): 290 /* huh? other hc's do this */ 291 memset(buf, 0, len); 292 totlen = len; 293 break; 294 295 case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): 296 { 297 usb_port_status_t ps; 298 299 USETW(ps.wPortStatus, sc->sc_port_status); 300 USETW(ps.wPortChange, sc->sc_port_change); 301 totlen = min(len, sizeof(ps)); 302 memcpy(buf, &ps, totlen); 303 break; 304 } 305 306 default: 307 panic("unhandled request"); 308 break; 309 } 310 err = USBD_NORMAL_COMPLETION; 311 xfer->actlen = totlen; 312 313 ret: 314 xfer->status = err; 315 usb_transfer_complete(xfer); 316 return (USBD_IN_PROGRESS); 317 } 318 319 static usbd_status 320 rumpusb_root_ctrl_transfer(usbd_xfer_handle xfer) 321 { 322 usbd_status err; 323 324 err = usb_insert_transfer(xfer); 325 if (err) 326 return (err); 327 328 return (rumpusb_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); 329 } 330 331 static void 332 rumpusb_root_ctrl_abort(usbd_xfer_handle xfer) 333 { 334 335 } 336 337 static void 338 rumpusb_root_ctrl_close(usbd_pipe_handle pipe) 339 { 340 341 } 342 343 static void 344 rumpusb_root_ctrl_cleartoggle(usbd_pipe_handle pipe) 345 { 346 347 } 348 349 static void 350 rumpusb_root_ctrl_done(usbd_xfer_handle xfer) 351 { 352 353 } 354 355 static const struct usbd_pipe_methods rumpusb_root_ctrl_methods = { 356 .transfer = rumpusb_root_ctrl_transfer, 357 .start = rumpusb_root_ctrl_start, 358 .abort = rumpusb_root_ctrl_abort, 359 .close = rumpusb_root_ctrl_close, 360 .cleartoggle = rumpusb_root_ctrl_cleartoggle, 361 .done = rumpusb_root_ctrl_done, 362 }; 363 364 static usbd_status 365 rumpusb_device_ctrl_start(usbd_xfer_handle xfer) 366 { 367 usb_device_request_t *req = &xfer->request; 368 struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private; 369 uint8_t *buf = NULL; 370 int len, totlen; 371 int value; 372 int err = 0; 373 int ru_error, mightfail = 0; 374 375 len = totlen = UGETW(req->wLength); 376 if (len) 377 buf = KERNADDR(&xfer->dmabuf, 0); 378 value = UGETW(req->wValue); 379 380 #define C(x,y) ((x) | ((y) << 8)) 381 switch(C(req->bRequest, req->bmRequestType)) { 382 case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): 383 switch (value>>8) { 384 case UDESC_DEVICE: 385 { 386 usb_device_descriptor_t uddesc; 387 totlen = min(len, USB_DEVICE_DESCRIPTOR_SIZE); 388 memset(buf, 0, totlen); 389 if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL], 390 USB_GET_DEVICE_DESC, &uddesc, &ru_error) == -1) { 391 err = EIO; 392 goto ret; 393 } 394 memcpy(buf, &uddesc, totlen); 395 } 396 397 break; 398 case UDESC_CONFIG: 399 { 400 struct usb_full_desc ufdesc; 401 ufdesc.ufd_config_index = value & 0xff; 402 ufdesc.ufd_size = len; 403 ufdesc.ufd_data = buf; 404 memset(buf, 0, len); 405 if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL], 406 USB_GET_FULL_DESC, &ufdesc, &ru_error) == -1) { 407 err = USBD_IOERROR; 408 goto ret; 409 } 410 totlen = ufdesc.ufd_size; 411 } 412 break; 413 414 case UDESC_STRING: 415 { 416 struct usb_device_info udi; 417 418 if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL], 419 USB_GET_DEVICEINFO, &udi, &ru_error) == -1) { 420 printf("ugenhc: get dev info failed: %d\n", 421 ru_error); 422 err = USBD_IOERROR; 423 goto ret; 424 } 425 426 switch (value & 0xff) { 427 #define sd ((usb_string_descriptor_t *)buf) 428 case 0: /* language table */ 429 break; 430 case 1: /* vendor */ 431 totlen = usb_makestrdesc(sd, len, 432 udi.udi_vendor); 433 break; 434 case 2: /* product */ 435 totlen = usb_makestrdesc(sd, len, 436 udi.udi_product); 437 break; 438 } 439 #undef sd 440 } 441 break; 442 443 default: 444 panic("not handled"); 445 } 446 break; 447 448 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): 449 /* ignored, ugen won't let us */ 450 break; 451 452 case C(UR_SET_CONFIG, UT_WRITE_DEVICE): 453 if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL], 454 USB_SET_CONFIG, &value, &ru_error) == -1) { 455 printf("ugenhc: set config failed: %d\n", 456 ru_error); 457 err = USBD_IOERROR; 458 goto ret; 459 } 460 break; 461 462 case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): 463 { 464 struct usb_alt_interface uai; 465 466 totlen = 0; 467 uai.uai_interface_index = UGETW(req->wIndex); 468 uai.uai_alt_no = value; 469 if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL], 470 USB_SET_ALTINTERFACE, &uai, &ru_error) == -1) { 471 printf("ugenhc: set alt interface failed: %d\n", 472 ru_error); 473 err = USBD_IOERROR; 474 goto ret; 475 } 476 break; 477 } 478 479 /* 480 * This request might fail unknown reasons. "EIO" doesn't 481 * give much help, and debugging the host ugen would be 482 * necessary. However, since it doesn't seem to really 483 * affect anything, just let it fail for now. 484 */ 485 case C(0x00, UT_WRITE_CLASS_INTERFACE): 486 mightfail = 1; 487 /*FALLTHROUGH*/ 488 489 /* 490 * XXX: don't wildcard these yet. I want to better figure 491 * out what to trap here. This is kinda silly, though ... 492 */ 493 494 case C(0x01, UT_WRITE_VENDOR_DEVICE): 495 case C(0x06, UT_WRITE_VENDOR_DEVICE): 496 case C(0x07, UT_READ_VENDOR_DEVICE): 497 case C(0x09, UT_READ_VENDOR_DEVICE): 498 case C(0xfe, UT_READ_CLASS_INTERFACE): 499 case C(0x01, UT_READ_CLASS_INTERFACE): 500 case C(UR_GET_STATUS, UT_READ_CLASS_OTHER): 501 case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): 502 case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): 503 case C(UR_GET_DESCRIPTOR, UT_READ_INTERFACE): 504 case C(0xff, UT_WRITE_CLASS_INTERFACE): 505 case C(0x20, UT_WRITE_CLASS_INTERFACE): 506 case C(0x22, UT_WRITE_CLASS_INTERFACE): 507 case C(0x0a, UT_WRITE_CLASS_INTERFACE): 508 case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): 509 case C(UR_SET_FEATURE, UT_WRITE_DEVICE): 510 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): 511 case C(UR_SET_REPORT, UT_WRITE_CLASS_INTERFACE): 512 case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): 513 { 514 struct usb_ctl_request ucr; 515 516 memcpy(&ucr.ucr_request, req, sizeof(ucr.ucr_request)); 517 ucr.ucr_data = buf; 518 if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL], 519 USB_DO_REQUEST, &ucr, &ru_error) == -1) { 520 if (!mightfail) { 521 panic("request failed: %d", ru_error); 522 } else { 523 err = ru_error; 524 } 525 } 526 } 527 break; 528 529 default: 530 panic("unhandled request"); 531 break; 532 } 533 xfer->actlen = totlen; 534 err = USBD_NORMAL_COMPLETION; 535 536 ret: 537 xfer->status = err; 538 usb_transfer_complete(xfer); 539 return (USBD_IN_PROGRESS); 540 } 541 542 static usbd_status 543 rumpusb_device_ctrl_transfer(usbd_xfer_handle xfer) 544 { 545 usbd_status err; 546 547 err = usb_insert_transfer(xfer); 548 if (err) 549 return (err); 550 551 return (rumpusb_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); 552 } 553 554 static void 555 rumpusb_device_ctrl_abort(usbd_xfer_handle xfer) 556 { 557 558 } 559 560 static void 561 rumpusb_device_ctrl_close(usbd_pipe_handle pipe) 562 { 563 564 } 565 566 static void 567 rumpusb_device_ctrl_cleartoggle(usbd_pipe_handle pipe) 568 { 569 570 } 571 572 static void 573 rumpusb_device_ctrl_done(usbd_xfer_handle xfer) 574 { 575 576 } 577 578 static const struct usbd_pipe_methods rumpusb_device_ctrl_methods = { 579 .transfer = rumpusb_device_ctrl_transfer, 580 .start = rumpusb_device_ctrl_start, 581 .abort = rumpusb_device_ctrl_abort, 582 .close = rumpusb_device_ctrl_close, 583 .cleartoggle = rumpusb_device_ctrl_cleartoggle, 584 .done = rumpusb_device_ctrl_done, 585 }; 586 587 static void 588 rhscintr(void *arg) 589 { 590 char buf[UGENDEV_BUFSIZE]; 591 struct ugenhc_softc *sc = arg; 592 usbd_xfer_handle xfer; 593 int fd, error; 594 595 makeugendevstr(sc->sc_devnum, 0, buf); 596 597 for (;;) { 598 /* 599 * Detect device attach. 600 */ 601 602 for (;;) { 603 fd = rumpuser_open(buf, O_RDWR, &error); 604 if (fd != -1) 605 break; 606 kpause("ugwait", false, hz/4, NULL); 607 } 608 609 sc->sc_ugenfd[UGEN_EPT_CTRL] = fd; 610 sc->sc_port_status = UPS_CURRENT_CONNECT_STATUS 611 | UPS_PORT_ENABLED | UPS_PORT_POWER; 612 sc->sc_port_change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET; 613 614 xfer = sc->sc_intrxfer; 615 memset(xfer->buffer, 0xff, xfer->length); 616 xfer->actlen = xfer->length; 617 xfer->status = USBD_NORMAL_COMPLETION; 618 619 usb_transfer_complete(xfer); 620 621 kpause("ugwait2", false, hz, NULL); 622 623 /* 624 * Detect device detach. 625 */ 626 627 for (;;) { 628 fd = rumpuser_open(buf, O_RDWR, &error); 629 if (fd == -1) 630 break; 631 632 rumpuser_close(fd, &error); 633 kpause("ugwait2", false, hz/4, NULL); 634 } 635 636 sc->sc_port_status = ~(UPS_CURRENT_CONNECT_STATUS 637 | UPS_PORT_ENABLED | UPS_PORT_POWER); 638 sc->sc_port_change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET; 639 640 rumpuser_close(sc->sc_ugenfd[UGEN_EPT_CTRL], &error); 641 sc->sc_ugenfd[UGEN_EPT_CTRL] = -1; 642 643 xfer = sc->sc_intrxfer; 644 memset(xfer->buffer, 0xff, xfer->length); 645 xfer->actlen = xfer->length; 646 xfer->status = USBD_NORMAL_COMPLETION; 647 usb_transfer_complete(xfer); 648 649 kpause("ugwait3", false, hz, NULL); 650 } 651 652 kthread_exit(0); 653 } 654 655 static usbd_status 656 rumpusb_root_intr_start(usbd_xfer_handle xfer) 657 { 658 struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private; 659 int error; 660 661 sc->sc_intrxfer = xfer; 662 if (!sc->sc_rhintr) { 663 error = kthread_create(PRI_NONE, 0, NULL, 664 rhscintr, sc, &sc->sc_rhintr, "ugenrhi"); 665 if (error) 666 xfer->status = error; 667 } 668 669 return (USBD_IN_PROGRESS); 670 } 671 672 static usbd_status 673 rumpusb_root_intr_transfer(usbd_xfer_handle xfer) 674 { 675 usbd_status err; 676 677 err = usb_insert_transfer(xfer); 678 if (err) 679 return (err); 680 681 return (rumpusb_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); 682 } 683 684 static void 685 rumpusb_root_intr_abort(usbd_xfer_handle xfer) 686 { 687 688 } 689 690 static void 691 rumpusb_root_intr_close(usbd_pipe_handle pipe) 692 { 693 694 } 695 696 static void 697 rumpusb_root_intr_cleartoggle(usbd_pipe_handle pipe) 698 { 699 700 } 701 702 static void 703 rumpusb_root_intr_done(usbd_xfer_handle xfer) 704 { 705 706 } 707 708 static const struct usbd_pipe_methods rumpusb_root_intr_methods = { 709 .transfer = rumpusb_root_intr_transfer, 710 .start = rumpusb_root_intr_start, 711 .abort = rumpusb_root_intr_abort, 712 .close = rumpusb_root_intr_close, 713 .cleartoggle = rumpusb_root_intr_cleartoggle, 714 .done = rumpusb_root_intr_done, 715 }; 716 717 static usbd_status 718 rumpusb_device_bulk_start(usbd_xfer_handle xfer) 719 { 720 struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private; 721 ssize_t n; 722 ssize_t done; 723 bool isread; 724 int len, error, endpt; 725 uint8_t *buf; 726 int xfererr = USBD_NORMAL_COMPLETION; 727 int val; 728 729 endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; 730 isread = UE_GET_DIR(endpt) == UE_DIR_IN; 731 endpt = UE_GET_ADDR(endpt); 732 KASSERT(endpt < UGEN_NEPTS); 733 734 KASSERT(xfer->length); 735 len = xfer->length; 736 buf = KERNADDR(&xfer->dmabuf, 0); 737 done = 0; 738 739 while (RUSB(xfer)->rusb_status == 0) { 740 if (isread) { 741 if (xfer->flags & USBD_SHORT_XFER_OK) 742 val = 1; 743 else 744 val = 0; 745 rumpuser_ioctl(sc->sc_ugenfd[endpt], 746 USB_SET_SHORT_XFER, &val, &error); 747 n = rumpuser_read(sc->sc_ugenfd[endpt], 748 buf+done, len-done, &error); 749 if (n == -1) { 750 if (error == ETIMEDOUT) 751 continue; 752 n = 0; 753 xfererr = USBD_IOERROR; 754 goto out; 755 } 756 done += n; 757 if (done == len) 758 break; 759 } else { 760 n = rumpuser_write(sc->sc_ugenfd[endpt], 761 buf, len, &error); 762 done = n; 763 if (done == len) 764 break; 765 else if (n != -1) 766 panic("short write"); 767 768 xfererr = USBD_IOERROR; 769 goto out; 770 } 771 772 if (xfer->flags & USBD_SHORT_XFER_OK) 773 break; 774 } 775 776 if (RUSB(xfer)->rusb_status == 0) { 777 xfer->actlen = done; 778 } else { 779 xfererr = USBD_CANCELLED; 780 RUSB(xfer)->rusb_status = 2; 781 } 782 out: 783 xfer->status = xfererr; 784 usb_transfer_complete(xfer); 785 return (USBD_IN_PROGRESS); 786 } 787 788 static void 789 doxfer_kth(void *arg) 790 { 791 usbd_xfer_handle xfer = arg; 792 793 do { 794 rumpusb_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); 795 } while (!SIMPLEQ_EMPTY(&xfer->pipe->queue)); 796 kthread_exit(0); 797 } 798 799 static usbd_status 800 rumpusb_device_bulk_transfer(usbd_xfer_handle xfer) 801 { 802 usbd_status err; 803 804 if (!rump_threads) { 805 /* XXX: lie about supporting async transfers */ 806 if ((xfer->flags & USBD_SYNCHRONOUS) == 0) { 807 printf("non-threaded rump does not support " 808 "async transfers.\n"); 809 return USBD_IN_PROGRESS; 810 } 811 812 err = usb_insert_transfer(xfer); 813 if (err) 814 return err; 815 816 return rumpusb_device_bulk_start( 817 SIMPLEQ_FIRST(&xfer->pipe->queue)); 818 } else { 819 /* biglocked */ 820 err = usb_insert_transfer(xfer); 821 if (err) 822 return err; 823 kthread_create(PRI_NONE, 0, NULL, doxfer_kth, xfer, NULL, 824 "rusbhcxf"); 825 826 return USBD_IN_PROGRESS; 827 } 828 } 829 830 /* wait for transfer to abort. yea, this is cheesy (from a spray can) */ 831 static void 832 rumpusb_device_bulk_abort(usbd_xfer_handle xfer) 833 { 834 struct rusb_xfer *rx = RUSB(xfer); 835 836 rx->rusb_status = 1; 837 while (rx->rusb_status < 2) { 838 kpause("jopo", false, hz/10, NULL); 839 } 840 } 841 842 static void 843 rumpusb_device_bulk_close(usbd_pipe_handle pipe) 844 { 845 struct ugenhc_softc *sc = pipe->device->bus->hci_private; 846 int endpt = pipe->endpoint->edesc->bEndpointAddress; 847 usbd_xfer_handle xfer; 848 int error; 849 850 endpt = UE_GET_ADDR(endpt); 851 852 while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) 853 rumpusb_device_bulk_abort(xfer); 854 855 rumpuser_close(sc->sc_ugenfd[endpt], &error); 856 sc->sc_ugenfd[endpt] = -1; 857 sc->sc_fdmodes[endpt] = -1; 858 } 859 860 static void 861 rumpusb_device_bulk_cleartoggle(usbd_pipe_handle pipe) 862 { 863 864 } 865 866 static void 867 rumpusb_device_bulk_done(usbd_xfer_handle xfer) 868 { 869 870 } 871 872 static const struct usbd_pipe_methods rumpusb_device_bulk_methods = { 873 .transfer = rumpusb_device_bulk_transfer, 874 .start = rumpusb_device_bulk_start, 875 .abort = rumpusb_device_bulk_abort, 876 .close = rumpusb_device_bulk_close, 877 .cleartoggle = rumpusb_device_bulk_cleartoggle, 878 .done = rumpusb_device_bulk_done, 879 }; 880 881 static const struct usbd_pipe_methods rumpusb_device_intr_methods = { 882 .transfer = rumpusb_root_intr_transfer, 883 .start = rumpusb_root_intr_start, 884 .abort = rumpusb_root_intr_abort, 885 .close = rumpusb_root_intr_close, 886 .cleartoggle = rumpusb_root_intr_cleartoggle, 887 .done = rumpusb_root_intr_done, 888 }; 889 890 static usbd_status 891 ugenhc_open(struct usbd_pipe *pipe) 892 { 893 usbd_device_handle dev = pipe->device; 894 struct ugenhc_softc *sc = dev->bus->hci_private; 895 usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; 896 u_int8_t addr = dev->address; 897 u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; 898 char buf[UGENDEV_BUFSIZE]; 899 int endpt, oflags, error; 900 int fd, val; 901 902 if (addr == sc->sc_addr) { 903 switch (xfertype) { 904 case UE_CONTROL: 905 pipe->methods = &rumpusb_root_ctrl_methods; 906 break; 907 case UE_INTERRUPT: 908 pipe->methods = &rumpusb_root_intr_methods; 909 break; 910 default: 911 panic("%d not supported", xfertype); 912 break; 913 } 914 } else { 915 switch (xfertype) { 916 case UE_CONTROL: 917 pipe->methods = &rumpusb_device_ctrl_methods; 918 break; 919 case UE_INTERRUPT: 920 case UE_BULK: 921 pipe->methods = &rumpusb_device_bulk_methods; 922 endpt = pipe->endpoint->edesc->bEndpointAddress; 923 if (UE_GET_DIR(endpt) == UE_DIR_IN) { 924 oflags = O_RDONLY; 925 } else { 926 oflags = O_WRONLY; 927 } 928 endpt = UE_GET_ADDR(endpt); 929 930 if (sc->sc_fdmodes[endpt] == oflags 931 || sc->sc_fdmodes[endpt] == O_RDWR) 932 break; 933 934 if (sc->sc_fdmodes[endpt] != -1) { 935 /* XXX: closing from under someone? */ 936 rumpuser_close(sc->sc_ugenfd[endpt], &error); 937 oflags = O_RDWR; 938 } 939 940 makeugendevstr(sc->sc_devnum, endpt, buf); 941 fd = rumpuser_open(buf, oflags, &error); 942 if (fd == -1) 943 return USBD_INVAL; /* XXX: no mapping */ 944 val = 100; 945 if (rumpuser_ioctl(fd, USB_SET_TIMEOUT, &val, 946 &error) == -1) 947 panic("timeout set failed"); 948 sc->sc_ugenfd[endpt] = fd; 949 sc->sc_fdmodes[endpt] = oflags; 950 break; 951 default: 952 panic("%d not supported", xfertype); 953 break; 954 955 } 956 } 957 return 0; 958 } 959 960 static void 961 ugenhc_softint(void *arg) 962 { 963 964 } 965 966 static void 967 ugenhc_poll(struct usbd_bus *ubus) 968 { 969 970 } 971 972 static usbd_status 973 ugenhc_allocm(struct usbd_bus *bus, usb_dma_t *dma, uint32_t size) 974 { 975 struct ugenhc_softc *sc = bus->hci_private; 976 977 return usb_allocmem(&sc->sc_bus, size, 0, dma); 978 } 979 980 static void 981 ugenhc_freem(struct usbd_bus *bus, usb_dma_t *dma) 982 { 983 struct ugenhc_softc *sc = bus->hci_private; 984 985 usb_freemem(&sc->sc_bus, dma); 986 } 987 988 static struct usbd_xfer * 989 ugenhc_allocx(struct usbd_bus *bus) 990 { 991 usbd_xfer_handle xfer; 992 993 xfer = kmem_zalloc(sizeof(struct usbd_xfer), KM_SLEEP); 994 xfer->busy_free = XFER_BUSY; 995 996 return xfer; 997 } 998 999 static void 1000 ugenhc_freex(struct usbd_bus *bus, struct usbd_xfer *xfer) 1001 { 1002 1003 kmem_free(xfer, sizeof(struct usbd_xfer)); 1004 } 1005 1006 struct ugenhc_pipe { 1007 struct usbd_pipe pipe; 1008 }; 1009 1010 static const struct usbd_bus_methods ugenhc_bus_methods = { 1011 .open_pipe = ugenhc_open, 1012 .soft_intr = ugenhc_softint, 1013 .do_poll = ugenhc_poll, 1014 .allocm = ugenhc_allocm, 1015 .freem = ugenhc_freem, 1016 .allocx = ugenhc_allocx, 1017 .freex = ugenhc_freex, 1018 }; 1019 1020 static int 1021 ugenhc_probe(struct device *parent, struct cfdata *match, void *aux) 1022 { 1023 char buf[UGENDEV_BUFSIZE]; 1024 int error; 1025 1026 makeugendevstr(match->cf_unit, 0, buf); 1027 if (rumpuser_getfileinfo(buf, NULL, NULL, &error) == -1) 1028 return 0; 1029 1030 return 1; 1031 } 1032 1033 static void 1034 ugenhc_attach(struct device *parent, struct device *self, void *aux) 1035 { 1036 struct mainbus_attach_args *maa = aux; 1037 struct ugenhc_softc *sc = device_private(self); 1038 1039 aprint_normal("\n"); 1040 1041 memset(sc, 0, sizeof(*sc)); 1042 memset(&sc->sc_ugenfd, -1, sizeof(sc->sc_ugenfd)); 1043 memset(&sc->sc_fdmodes, -1, sizeof(sc->sc_fdmodes)); 1044 1045 sc->sc_bus.usbrev = USBREV_2_0; 1046 sc->sc_bus.methods = &ugenhc_bus_methods; 1047 sc->sc_bus.hci_private = sc; 1048 sc->sc_bus.pipe_size = sizeof(struct ugenhc_pipe); 1049 sc->sc_devnum = maa->maa_unit; 1050 1051 config_found(self, &sc->sc_bus, usbctlprint); 1052 } 1053