1 /* $NetBSD: ugen.c,v 1.36 2000/03/06 20:59:17 augustss Exp $ */ 2 /* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */ 3 4 /* 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Lennart Augustsson (augustss@carlstedt.se) at 10 * Carlstedt Research & Technology. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/malloc.h> 46 #if defined(__NetBSD__) || defined(__OpenBSD__) 47 #include <sys/device.h> 48 #include <sys/ioctl.h> 49 #elif defined(__FreeBSD__) 50 #include <sys/module.h> 51 #include <sys/bus.h> 52 #include <sys/ioccom.h> 53 #include <sys/conf.h> 54 #include <sys/fcntl.h> 55 #include <sys/filio.h> 56 #endif 57 #include <sys/conf.h> 58 #include <sys/tty.h> 59 #include <sys/file.h> 60 #include <sys/select.h> 61 #include <sys/proc.h> 62 #include <sys/vnode.h> 63 #include <sys/poll.h> 64 65 #include <dev/usb/usb.h> 66 #include <dev/usb/usbdi.h> 67 #include <dev/usb/usbdi_util.h> 68 69 #ifdef UGEN_DEBUG 70 #define DPRINTF(x) if (ugendebug) logprintf x 71 #define DPRINTFN(n,x) if (ugendebug>(n)) logprintf x 72 int ugendebug = 0; 73 #else 74 #define DPRINTF(x) 75 #define DPRINTFN(n,x) 76 #endif 77 78 struct ugen_endpoint { 79 struct ugen_softc *sc; 80 usb_endpoint_descriptor_t *edesc; 81 usbd_interface_handle iface; 82 int state; 83 #define UGEN_ASLP 0x02 /* waiting for data */ 84 #define UGEN_SHORT_OK 0x04 /* short xfers are OK */ 85 usbd_pipe_handle pipeh; 86 struct clist q; 87 struct selinfo rsel; 88 void *ibuf; 89 u_int32_t timeout; 90 }; 91 92 #define UGEN_CHUNK 128 /* chunk size for read */ 93 #define UGEN_IBSIZE 1020 /* buffer size */ 94 #define UGEN_BBSIZE 1024 95 96 struct ugen_softc { 97 USBBASEDEVICE sc_dev; /* base device */ 98 usbd_device_handle sc_udev; 99 100 char sc_is_open[USB_MAX_ENDPOINTS]; 101 struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2]; 102 #define OUT 0 103 #define IN 1 104 105 int sc_refcnt; 106 u_char sc_dying; 107 }; 108 109 #if defined(__NetBSD__) || defined(__OpenBSD__) 110 cdev_decl(ugen); 111 #elif defined(__FreeBSD__) 112 d_open_t ugenopen; 113 d_close_t ugenclose; 114 d_read_t ugenread; 115 d_write_t ugenwrite; 116 d_ioctl_t ugenioctl; 117 d_poll_t ugenpoll; 118 119 #define UGEN_CDEV_MAJOR 114 120 121 static struct cdevsw ugen_cdevsw = { 122 /* open */ ugenopen, 123 /* close */ ugenclose, 124 /* read */ ugenread, 125 /* write */ ugenwrite, 126 /* ioctl */ ugenioctl, 127 /* poll */ ugenpoll, 128 /* mmap */ nommap, 129 /* strategy */ nostrategy, 130 /* name */ "ugen", 131 /* maj */ UGEN_CDEV_MAJOR, 132 /* dump */ nodump, 133 /* psize */ nopsize, 134 /* flags */ 0, 135 /* bmaj */ -1 136 }; 137 #endif 138 139 static void ugenintr __P((usbd_xfer_handle xfer, usbd_private_handle addr, 140 usbd_status status)); 141 142 static int ugen_do_read __P((struct ugen_softc *, int, struct uio *, int)); 143 static int ugen_do_write __P((struct ugen_softc *, int, struct uio *, int)); 144 static int ugen_do_ioctl __P((struct ugen_softc *, int, u_long, 145 caddr_t, int, struct proc *)); 146 static int ugen_set_config __P((struct ugen_softc *sc, int configno)); 147 static usb_config_descriptor_t *ugen_get_cdesc __P((struct ugen_softc *sc, 148 int index, int *lenp)); 149 static usbd_status ugen_set_interface __P((struct ugen_softc *, int, int)); 150 static int ugen_get_alt_index __P((struct ugen_softc *sc, int ifaceidx)); 151 152 #define UGENUNIT(n) ((minor(n) >> 4) & 0xf) 153 #define UGENENDPOINT(n) (minor(n) & 0xf) 154 #define UGENDEV(u, e) (makedev(0, ((u) << 4) | (e))) 155 156 USB_DECLARE_DRIVER(ugen); 157 158 USB_MATCH(ugen) 159 { 160 USB_MATCH_START(ugen, uaa); 161 162 if (uaa->usegeneric) 163 return (UMATCH_GENERIC); 164 else 165 return (UMATCH_NONE); 166 } 167 168 USB_ATTACH(ugen) 169 { 170 USB_ATTACH_START(ugen, sc, uaa); 171 usbd_device_handle udev; 172 char devinfo[1024]; 173 usbd_status err; 174 int conf; 175 176 usbd_devinfo(uaa->device, 0, devinfo); 177 USB_ATTACH_SETUP; 178 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo); 179 180 sc->sc_udev = udev = uaa->device; 181 182 /* First set configuration index 0, the default one for ugen. */ 183 err = usbd_set_config_index(udev, 0, 0); 184 if (err) { 185 printf("%s: setting configuration index 0 failed\n", 186 USBDEVNAME(sc->sc_dev)); 187 sc->sc_dying = 1; 188 USB_ATTACH_ERROR_RETURN; 189 } 190 conf = usbd_get_config_descriptor(udev)->bConfigurationValue; 191 192 /* Set up all the local state for this configuration. */ 193 err = ugen_set_config(sc, conf); 194 if (err) { 195 printf("%s: setting configuration %d failed\n", 196 USBDEVNAME(sc->sc_dev), conf); 197 sc->sc_dying = 1; 198 USB_ATTACH_ERROR_RETURN; 199 } 200 201 #ifdef __FreeBSD__ 202 { 203 static int global_init_done = 0; 204 if (!global_init_done) { 205 cdevsw_add(&ugen_cdevsw); 206 global_init_done = 1; 207 } 208 } 209 #endif 210 211 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 212 USBDEV(sc->sc_dev)); 213 214 USB_ATTACH_SUCCESS_RETURN; 215 } 216 217 static int 218 ugen_set_config(sc, configno) 219 struct ugen_softc *sc; 220 int configno; 221 { 222 usbd_device_handle dev = sc->sc_udev; 223 usbd_interface_handle iface; 224 usb_endpoint_descriptor_t *ed; 225 struct ugen_endpoint *sce; 226 u_int8_t niface, nendpt; 227 int ifaceno, endptno, endpt; 228 usbd_status err; 229 int dir; 230 231 DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n", 232 USBDEVNAME(sc->sc_dev), configno, sc)); 233 /* Avoid setting the current value. */ 234 if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) { 235 err = usbd_set_config_no(dev, configno, 0); 236 if (err) 237 return (err); 238 } 239 240 err = usbd_interface_count(dev, &niface); 241 if (err) 242 return (err); 243 memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints); 244 for (ifaceno = 0; ifaceno < niface; ifaceno++) { 245 DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno)); 246 err = usbd_device2interface_handle(dev, ifaceno, &iface); 247 if (err) 248 return (err); 249 err = usbd_endpoint_count(iface, &nendpt); 250 if (err) 251 return (err); 252 for (endptno = 0; endptno < nendpt; endptno++) { 253 ed = usbd_interface2endpoint_descriptor(iface,endptno); 254 endpt = ed->bEndpointAddress; 255 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; 256 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; 257 DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x" 258 "(%d,%d), sce=%p\n", 259 endptno, endpt, UE_GET_ADDR(endpt), 260 UE_GET_DIR(endpt), sce)); 261 sce->sc = sc; 262 sce->edesc = ed; 263 sce->iface = iface; 264 } 265 } 266 return (USBD_NORMAL_COMPLETION); 267 } 268 269 int 270 ugenopen(dev, flag, mode, p) 271 dev_t dev; 272 int flag; 273 int mode; 274 struct proc *p; 275 { 276 struct ugen_softc *sc; 277 int unit = UGENUNIT(dev); 278 int endpt = UGENENDPOINT(dev); 279 usb_endpoint_descriptor_t *edesc; 280 struct ugen_endpoint *sce; 281 int dir, isize; 282 usbd_status err; 283 284 USB_GET_SC_OPEN(ugen, unit, sc); 285 286 DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n", 287 flag, mode, unit, endpt)); 288 289 if (sc == NULL || sc->sc_dying) 290 return (ENXIO); 291 292 if (sc->sc_is_open[endpt]) 293 return (EBUSY); 294 295 if (endpt == USB_CONTROL_ENDPOINT) { 296 sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1; 297 return (0); 298 } 299 300 /* Make sure there are pipes for all directions. */ 301 for (dir = OUT; dir <= IN; dir++) { 302 if (flag & (dir == OUT ? FWRITE : FREAD)) { 303 sce = &sc->sc_endpoints[endpt][dir]; 304 if (sce == 0 || sce->edesc == 0) 305 return (ENXIO); 306 } 307 } 308 309 /* Actually open the pipes. */ 310 /* XXX Should back out properly if it fails. */ 311 for (dir = OUT; dir <= IN; dir++) { 312 if (!(flag & (dir == OUT ? FWRITE : FREAD))) 313 continue; 314 sce = &sc->sc_endpoints[endpt][dir]; 315 sce->state = 0; 316 sce->timeout = USBD_NO_TIMEOUT; 317 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n", 318 sc, endpt, dir, sce)); 319 edesc = sce->edesc; 320 switch (edesc->bmAttributes & UE_XFERTYPE) { 321 case UE_INTERRUPT: 322 isize = UGETW(edesc->wMaxPacketSize); 323 if (isize == 0) /* shouldn't happen */ 324 return (EINVAL); 325 sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK); 326 DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n", 327 endpt, isize)); 328 if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1) 329 return (ENOMEM); 330 err = usbd_open_pipe_intr(sce->iface, 331 edesc->bEndpointAddress, 332 USBD_SHORT_XFER_OK, &sce->pipeh, sce, 333 sce->ibuf, isize, ugenintr, 334 USBD_DEFAULT_INTERVAL); 335 if (err) { 336 free(sce->ibuf, M_USBDEV); 337 clfree(&sce->q); 338 return (EIO); 339 } 340 DPRINTFN(5, ("ugenopen: interrupt open done\n")); 341 break; 342 case UE_BULK: 343 err = usbd_open_pipe(sce->iface, 344 edesc->bEndpointAddress, 0, &sce->pipeh); 345 if (err) 346 return (EIO); 347 break; 348 case UE_CONTROL: 349 case UE_ISOCHRONOUS: 350 return (EINVAL); 351 } 352 } 353 sc->sc_is_open[endpt] = 1; 354 return (0); 355 } 356 357 int 358 ugenclose(dev, flag, mode, p) 359 dev_t dev; 360 int flag; 361 int mode; 362 struct proc *p; 363 { 364 int endpt = UGENENDPOINT(dev); 365 struct ugen_softc *sc; 366 struct ugen_endpoint *sce; 367 int dir; 368 369 USB_GET_SC(ugen, UGENUNIT(dev), sc); 370 371 DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n", 372 flag, mode, UGENUNIT(dev), endpt)); 373 374 #ifdef DIAGNOSTIC 375 if (!sc->sc_is_open[endpt]) { 376 printf("ugenclose: not open\n"); 377 return (EINVAL); 378 } 379 #endif 380 381 if (endpt == USB_CONTROL_ENDPOINT) { 382 DPRINTFN(5, ("ugenclose: close control\n")); 383 sc->sc_is_open[endpt] = 0; 384 return (0); 385 } 386 387 for (dir = OUT; dir <= IN; dir++) { 388 if (!(flag & (dir == OUT ? FWRITE : FREAD))) 389 continue; 390 sce = &sc->sc_endpoints[endpt][dir]; 391 if (sce == NULL || sce->pipeh == NULL) 392 continue; 393 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n", 394 endpt, dir, sce)); 395 396 usbd_abort_pipe(sce->pipeh); 397 usbd_close_pipe(sce->pipeh); 398 sce->pipeh = NULL; 399 400 if (sce->ibuf != NULL) { 401 free(sce->ibuf, M_USBDEV); 402 sce->ibuf = NULL; 403 clfree(&sce->q); 404 405 } 406 } 407 sc->sc_is_open[endpt] = 0; 408 409 return (0); 410 } 411 412 static int 413 ugen_do_read(sc, endpt, uio, flag) 414 struct ugen_softc *sc; 415 int endpt; 416 struct uio *uio; 417 int flag; 418 { 419 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN]; 420 u_int32_t n, tn; 421 char buf[UGEN_BBSIZE]; 422 usbd_xfer_handle xfer; 423 usbd_status err; 424 int s; 425 int error = 0; 426 u_char buffer[UGEN_CHUNK]; 427 428 #ifdef __NetBSD__ 429 DPRINTFN(5, ("ugenread: %d:%d\n", sc->sc_dev.dv_unit, endpt)); 430 #endif 431 432 if (sc->sc_dying) 433 return (EIO); 434 435 if (endpt == USB_CONTROL_ENDPOINT) 436 return (ENODEV); 437 438 #ifdef DIAGNOSTIC 439 if (sce->edesc == NULL) { 440 printf("ugenread: no edesc\n"); 441 return (EIO); 442 } 443 if (sce->pipeh == NULL) { 444 printf("ugenread: no pipe\n"); 445 return (EIO); 446 } 447 #endif 448 449 switch (sce->edesc->bmAttributes & UE_XFERTYPE) { 450 case UE_INTERRUPT: 451 /* Block until activity occured. */ 452 s = splusb(); 453 while (sce->q.c_cc == 0) { 454 if (flag & IO_NDELAY) { 455 splx(s); 456 return (EWOULDBLOCK); 457 } 458 sce->state |= UGEN_ASLP; 459 DPRINTFN(5, ("ugenread: sleep on %p\n", sc)); 460 error = tsleep(sce, PZERO | PCATCH, "ugenri", 0); 461 DPRINTFN(5, ("ugenread: woke, error=%d\n", error)); 462 if (sc->sc_dying) 463 error = EIO; 464 if (error) { 465 sce->state &= ~UGEN_ASLP; 466 break; 467 } 468 } 469 splx(s); 470 471 /* Transfer as many chunks as possible. */ 472 while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) { 473 n = min(sce->q.c_cc, uio->uio_resid); 474 if (n > sizeof(buffer)) 475 n = sizeof(buffer); 476 477 /* Remove a small chunk from the input queue. */ 478 q_to_b(&sce->q, buffer, n); 479 DPRINTFN(5, ("ugenread: got %d chars\n", n)); 480 481 /* Copy the data to the user process. */ 482 error = uiomove(buffer, n, uio); 483 if (error) 484 break; 485 } 486 break; 487 case UE_BULK: 488 xfer = usbd_alloc_xfer(sc->sc_udev); 489 if (xfer == 0) 490 return (ENOMEM); 491 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { 492 DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n)); 493 tn = n; 494 err = usbd_bulk_transfer( 495 xfer, sce->pipeh, 496 sce->state & UGEN_SHORT_OK ? 497 USBD_SHORT_XFER_OK : 0, 498 sce->timeout, buf, &tn, "ugenrb"); 499 if (err) { 500 if (err == USBD_INTERRUPTED) 501 error = EINTR; 502 else if (err == USBD_TIMEOUT) 503 error = ETIMEDOUT; 504 else 505 error = EIO; 506 break; 507 } 508 DPRINTFN(1, ("ugenread: got %d bytes\n", tn)); 509 error = uiomove(buf, tn, uio); 510 if (error || tn < n) 511 break; 512 } 513 usbd_free_xfer(xfer); 514 break; 515 default: 516 return (ENXIO); 517 } 518 return (error); 519 } 520 521 int 522 ugenread(dev, uio, flag) 523 dev_t dev; 524 struct uio *uio; 525 int flag; 526 { 527 int endpt = UGENENDPOINT(dev); 528 struct ugen_softc *sc; 529 int error; 530 531 USB_GET_SC(ugen, UGENUNIT(dev), sc); 532 533 sc->sc_refcnt++; 534 error = ugen_do_read(sc, endpt, uio, flag); 535 if (--sc->sc_refcnt < 0) 536 usb_detach_wakeup(USBDEV(sc->sc_dev)); 537 return (error); 538 } 539 540 static int 541 ugen_do_write(sc, endpt, uio, flag) 542 struct ugen_softc *sc; 543 int endpt; 544 struct uio *uio; 545 int flag; 546 { 547 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT]; 548 u_int32_t n; 549 int error = 0; 550 char buf[UGEN_BBSIZE]; 551 usbd_xfer_handle xfer; 552 usbd_status err; 553 554 DPRINTFN(5, ("%s: ugenwrite: %d\n", USBDEVNAME(sc->sc_dev), endpt)); 555 556 if (sc->sc_dying) 557 return (EIO); 558 559 if (endpt == USB_CONTROL_ENDPOINT) 560 return (ENODEV); 561 562 #ifdef DIAGNOSTIC 563 if (sce->edesc == NULL) { 564 printf("ugenwrite: no edesc\n"); 565 return (EIO); 566 } 567 if (sce->pipeh == NULL) { 568 printf("ugenwrite: no pipe\n"); 569 return (EIO); 570 } 571 #endif 572 573 switch (sce->edesc->bmAttributes & UE_XFERTYPE) { 574 case UE_BULK: 575 xfer = usbd_alloc_xfer(sc->sc_udev); 576 if (xfer == 0) 577 return (EIO); 578 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) { 579 error = uiomove(buf, n, uio); 580 if (error) 581 break; 582 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n)); 583 err = usbd_bulk_transfer(xfer, sce->pipeh, 0, 584 sce->timeout, buf, &n,"ugenwb"); 585 if (err) { 586 if (err == USBD_INTERRUPTED) 587 error = EINTR; 588 else if (err == USBD_TIMEOUT) 589 error = ETIMEDOUT; 590 else 591 error = EIO; 592 break; 593 } 594 } 595 usbd_free_xfer(xfer); 596 break; 597 default: 598 return (ENXIO); 599 } 600 return (error); 601 } 602 603 int 604 ugenwrite(dev, uio, flag) 605 dev_t dev; 606 struct uio *uio; 607 int flag; 608 { 609 int endpt = UGENENDPOINT(dev); 610 struct ugen_softc *sc; 611 int error; 612 613 USB_GET_SC(ugen, UGENUNIT(dev), sc); 614 615 sc->sc_refcnt++; 616 error = ugen_do_write(sc, endpt, uio, flag); 617 if (--sc->sc_refcnt < 0) 618 usb_detach_wakeup(USBDEV(sc->sc_dev)); 619 return (error); 620 } 621 622 #if defined(__NetBSD__) || defined(__OpenBSD__) 623 int 624 ugen_activate(self, act) 625 device_ptr_t self; 626 enum devact act; 627 { 628 struct ugen_softc *sc = (struct ugen_softc *)self; 629 630 switch (act) { 631 case DVACT_ACTIVATE: 632 return (EOPNOTSUPP); 633 break; 634 635 case DVACT_DEACTIVATE: 636 sc->sc_dying = 1; 637 break; 638 } 639 return (0); 640 } 641 #endif 642 643 USB_DETACH(ugen) 644 { 645 USB_DETACH_START(ugen, sc); 646 struct ugen_endpoint *sce; 647 int i, dir; 648 int s; 649 #if defined(__NetBSD__) || defined(__OpenBSD__) 650 int maj, mn; 651 652 DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags)); 653 #elif defined(__FreeBSD__) 654 DPRINTF(("ugen_detach: sc=%p\n", sc)); 655 #endif 656 657 sc->sc_dying = 1; 658 /* Abort all pipes. Causes processes waiting for transfer to wake. */ 659 for (i = 0; i < USB_MAX_ENDPOINTS; i++) { 660 for (dir = OUT; dir <= IN; dir++) { 661 sce = &sc->sc_endpoints[i][dir]; 662 if (sce && sce->pipeh) 663 usbd_abort_pipe(sce->pipeh); 664 } 665 } 666 667 s = splusb(); 668 if (--sc->sc_refcnt >= 0) { 669 /* Wake everyone */ 670 for (i = 0; i < USB_MAX_ENDPOINTS; i++) 671 wakeup(&sc->sc_endpoints[i][IN]); 672 /* Wait for processes to go away. */ 673 usb_detach_wait(USBDEV(sc->sc_dev)); 674 } 675 splx(s); 676 677 #if defined(__NetBSD__) || defined(__OpenBSD__) 678 /* locate the major number */ 679 for (maj = 0; maj < nchrdev; maj++) 680 if (cdevsw[maj].d_open == ugenopen) 681 break; 682 683 /* Nuke the vnodes for any open instances (calls close). */ 684 mn = self->dv_unit * USB_MAX_ENDPOINTS; 685 vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR); 686 #elif defined(__FreeBSD__) 687 /* XXX not implemented yet */ 688 #endif 689 690 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 691 USBDEV(sc->sc_dev)); 692 693 return (0); 694 } 695 696 static void 697 ugenintr(xfer, addr, status) 698 usbd_xfer_handle xfer; 699 usbd_private_handle addr; 700 usbd_status status; 701 { 702 struct ugen_endpoint *sce = addr; 703 /*struct ugen_softc *sc = sce->sc;*/ 704 u_int32_t count; 705 u_char *ibuf; 706 707 if (status == USBD_CANCELLED) 708 return; 709 710 if (status != USBD_NORMAL_COMPLETION) { 711 DPRINTF(("ugenintr: status=%d\n", status)); 712 usbd_clear_endpoint_stall_async(sce->pipeh); 713 return; 714 } 715 716 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 717 ibuf = sce->ibuf; 718 719 DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n", 720 xfer, status, count)); 721 DPRINTFN(5, (" data = %02x %02x %02x\n", 722 ibuf[0], ibuf[1], ibuf[2])); 723 724 (void)b_to_q(ibuf, count, &sce->q); 725 726 if (sce->state & UGEN_ASLP) { 727 sce->state &= ~UGEN_ASLP; 728 DPRINTFN(5, ("ugen_intr: waking %p\n", sce)); 729 wakeup(sce); 730 } 731 selwakeup(&sce->rsel); 732 } 733 734 static usbd_status 735 ugen_set_interface(sc, ifaceidx, altno) 736 struct ugen_softc *sc; 737 int ifaceidx, altno; 738 { 739 usbd_interface_handle iface; 740 usb_endpoint_descriptor_t *ed; 741 usbd_status err; 742 struct ugen_endpoint *sce; 743 u_int8_t niface, nendpt, endptno, endpt; 744 int dir; 745 746 DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno)); 747 748 err = usbd_interface_count(sc->sc_udev, &niface); 749 if (err) 750 return (err); 751 if (ifaceidx < 0 || ifaceidx >= niface) 752 return (USBD_INVAL); 753 754 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); 755 if (err) 756 return (err); 757 err = usbd_endpoint_count(iface, &nendpt); 758 if (err) 759 return (err); 760 for (endptno = 0; endptno < nendpt; endptno++) { 761 ed = usbd_interface2endpoint_descriptor(iface,endptno); 762 endpt = ed->bEndpointAddress; 763 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; 764 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; 765 sce->sc = 0; 766 sce->edesc = 0; 767 sce->iface = 0; 768 } 769 770 /* change setting */ 771 err = usbd_set_interface(iface, altno); 772 if (err) 773 return (err); 774 775 err = usbd_endpoint_count(iface, &nendpt); 776 if (err) 777 return (err); 778 for (endptno = 0; endptno < nendpt; endptno++) { 779 ed = usbd_interface2endpoint_descriptor(iface,endptno); 780 endpt = ed->bEndpointAddress; 781 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT; 782 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir]; 783 sce->sc = sc; 784 sce->edesc = ed; 785 sce->iface = iface; 786 } 787 return (0); 788 } 789 790 /* Retrieve a complete descriptor for a certain device and index. */ 791 static usb_config_descriptor_t * 792 ugen_get_cdesc(sc, index, lenp) 793 struct ugen_softc *sc; 794 int index; 795 int *lenp; 796 { 797 usb_config_descriptor_t *cdesc, *tdesc, cdescr; 798 int len; 799 usbd_status err; 800 801 if (index == USB_CURRENT_CONFIG_INDEX) { 802 tdesc = usbd_get_config_descriptor(sc->sc_udev); 803 len = UGETW(tdesc->wTotalLength); 804 if (lenp) 805 *lenp = len; 806 cdesc = malloc(len, M_TEMP, M_WAITOK); 807 memcpy(cdesc, tdesc, len); 808 DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len)); 809 } else { 810 err = usbd_get_config_desc(sc->sc_udev, index, &cdescr); 811 if (err) 812 return (0); 813 len = UGETW(cdescr.wTotalLength); 814 DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len)); 815 if (lenp) 816 *lenp = len; 817 cdesc = malloc(len, M_TEMP, M_WAITOK); 818 err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc,len); 819 if (err) { 820 free(cdesc, M_TEMP); 821 return (0); 822 } 823 } 824 return (cdesc); 825 } 826 827 static int 828 ugen_get_alt_index(sc, ifaceidx) 829 struct ugen_softc *sc; 830 int ifaceidx; 831 { 832 usbd_interface_handle iface; 833 usbd_status err; 834 835 err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface); 836 if (err) 837 return (-1); 838 return (usbd_get_interface_altindex(iface)); 839 } 840 841 static int 842 ugen_do_ioctl(sc, endpt, cmd, addr, flag, p) 843 struct ugen_softc *sc; 844 int endpt; 845 u_long cmd; 846 caddr_t addr; 847 int flag; 848 struct proc *p; 849 { 850 struct ugen_endpoint *sce; 851 usbd_status err; 852 usbd_interface_handle iface; 853 struct usb_config_desc *cd; 854 usb_config_descriptor_t *cdesc; 855 struct usb_interface_desc *id; 856 usb_interface_descriptor_t *idesc; 857 struct usb_endpoint_desc *ed; 858 usb_endpoint_descriptor_t *edesc; 859 struct usb_alt_interface *ai; 860 struct usb_string_desc *si; 861 u_int8_t conf, alt; 862 863 DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd)); 864 if (sc->sc_dying) 865 return (EIO); 866 867 switch (cmd) { 868 case FIONBIO: 869 /* All handled in the upper FS layer. */ 870 return (0); 871 case USB_SET_SHORT_XFER: 872 /* This flag only affects read */ 873 if (endpt == USB_CONTROL_ENDPOINT) 874 return (EINVAL); 875 sce = &sc->sc_endpoints[endpt][IN]; 876 if (sce == NULL) 877 return (EINVAL); 878 #ifdef DIAGNOSTIC 879 if (sce->pipeh == NULL) { 880 printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n"); 881 return (EIO); 882 } 883 #endif 884 if (*(int *)addr) 885 sce->state |= UGEN_SHORT_OK; 886 else 887 sce->state &= ~UGEN_SHORT_OK; 888 return (0); 889 case USB_SET_TIMEOUT: 890 sce = &sc->sc_endpoints[endpt][IN]; 891 if (sce == NULL) 892 return (EINVAL); 893 #ifdef DIAGNOSTIC 894 if (sce->pipeh == NULL) { 895 printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n"); 896 return (EIO); 897 } 898 #endif 899 sce->timeout = *(int *)addr; 900 return (0); 901 default: 902 break; 903 } 904 905 if (endpt != USB_CONTROL_ENDPOINT) 906 return (EINVAL); 907 908 switch (cmd) { 909 #ifdef UGEN_DEBUG 910 case USB_SETDEBUG: 911 ugendebug = *(int *)addr; 912 break; 913 #endif 914 case USB_GET_CONFIG: 915 err = usbd_get_config(sc->sc_udev, &conf); 916 if (err) 917 return (EIO); 918 *(int *)addr = conf; 919 break; 920 case USB_SET_CONFIG: 921 if (!(flag & FWRITE)) 922 return (EPERM); 923 err = ugen_set_config(sc, *(int *)addr); 924 if (err) 925 return (EIO); 926 break; 927 case USB_GET_ALTINTERFACE: 928 ai = (struct usb_alt_interface *)addr; 929 err = usbd_device2interface_handle(sc->sc_udev, 930 ai->interface_index, &iface); 931 if (err) 932 return (EINVAL); 933 idesc = usbd_get_interface_descriptor(iface); 934 if (idesc == NULL) 935 return (EIO); 936 ai->alt_no = idesc->bAlternateSetting; 937 break; 938 case USB_SET_ALTINTERFACE: 939 if (!(flag & FWRITE)) 940 return (EPERM); 941 ai = (struct usb_alt_interface *)addr; 942 err = usbd_device2interface_handle(sc->sc_udev, 943 ai->interface_index, &iface); 944 if (err) 945 return (EINVAL); 946 err = ugen_set_interface(sc, ai->interface_index, ai->alt_no); 947 if (err) 948 return (EINVAL); 949 break; 950 case USB_GET_NO_ALT: 951 ai = (struct usb_alt_interface *)addr; 952 cdesc = ugen_get_cdesc(sc, ai->config_index, 0); 953 if (cdesc == NULL) 954 return (EINVAL); 955 idesc = usbd_find_idesc(cdesc, ai->interface_index, 0); 956 if (idesc == NULL) { 957 free(cdesc, M_TEMP); 958 return (EINVAL); 959 } 960 ai->alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber); 961 free(cdesc, M_TEMP); 962 break; 963 case USB_GET_DEVICE_DESC: 964 *(usb_device_descriptor_t *)addr = 965 *usbd_get_device_descriptor(sc->sc_udev); 966 break; 967 case USB_GET_CONFIG_DESC: 968 cd = (struct usb_config_desc *)addr; 969 cdesc = ugen_get_cdesc(sc, cd->config_index, 0); 970 if (cdesc == NULL) 971 return (EINVAL); 972 cd->desc = *cdesc; 973 free(cdesc, M_TEMP); 974 break; 975 case USB_GET_INTERFACE_DESC: 976 id = (struct usb_interface_desc *)addr; 977 cdesc = ugen_get_cdesc(sc, id->config_index, 0); 978 if (cdesc == NULL) 979 return (EINVAL); 980 if (id->config_index == USB_CURRENT_CONFIG_INDEX && 981 id->alt_index == USB_CURRENT_ALT_INDEX) 982 alt = ugen_get_alt_index(sc, id->interface_index); 983 else 984 alt = id->alt_index; 985 idesc = usbd_find_idesc(cdesc, id->interface_index, alt); 986 if (idesc == NULL) { 987 free(cdesc, M_TEMP); 988 return (EINVAL); 989 } 990 id->desc = *idesc; 991 free(cdesc, M_TEMP); 992 break; 993 case USB_GET_ENDPOINT_DESC: 994 ed = (struct usb_endpoint_desc *)addr; 995 cdesc = ugen_get_cdesc(sc, ed->config_index, 0); 996 if (cdesc == NULL) 997 return (EINVAL); 998 if (ed->config_index == USB_CURRENT_CONFIG_INDEX && 999 ed->alt_index == USB_CURRENT_ALT_INDEX) 1000 alt = ugen_get_alt_index(sc, ed->interface_index); 1001 else 1002 alt = ed->alt_index; 1003 edesc = usbd_find_edesc(cdesc, ed->interface_index, 1004 alt, ed->endpoint_index); 1005 if (edesc == NULL) { 1006 free(cdesc, M_TEMP); 1007 return (EINVAL); 1008 } 1009 ed->desc = *edesc; 1010 free(cdesc, M_TEMP); 1011 break; 1012 case USB_GET_FULL_DESC: 1013 { 1014 int len; 1015 struct iovec iov; 1016 struct uio uio; 1017 struct usb_full_desc *fd = (struct usb_full_desc *)addr; 1018 int error; 1019 1020 cdesc = ugen_get_cdesc(sc, fd->config_index, &len); 1021 if (len > fd->size) 1022 len = fd->size; 1023 iov.iov_base = (caddr_t)fd->data; 1024 iov.iov_len = len; 1025 uio.uio_iov = &iov; 1026 uio.uio_iovcnt = 1; 1027 uio.uio_resid = len; 1028 uio.uio_offset = 0; 1029 uio.uio_segflg = UIO_USERSPACE; 1030 uio.uio_rw = UIO_READ; 1031 uio.uio_procp = p; 1032 error = uiomove((void *)cdesc, len, &uio); 1033 free(cdesc, M_TEMP); 1034 return (error); 1035 } 1036 case USB_GET_STRING_DESC: 1037 si = (struct usb_string_desc *)addr; 1038 err = usbd_get_string_desc(sc->sc_udev, si->string_index, 1039 si->language_id, &si->desc); 1040 if (err) 1041 return (EINVAL); 1042 break; 1043 case USB_DO_REQUEST: 1044 { 1045 struct usb_ctl_request *ur = (void *)addr; 1046 int len = UGETW(ur->request.wLength); 1047 struct iovec iov; 1048 struct uio uio; 1049 void *ptr = 0; 1050 usbd_status err; 1051 int error = 0; 1052 1053 if (!(flag & FWRITE)) 1054 return (EPERM); 1055 /* Avoid requests that would damage the bus integrity. */ 1056 if ((ur->request.bmRequestType == UT_WRITE_DEVICE && 1057 ur->request.bRequest == UR_SET_ADDRESS) || 1058 (ur->request.bmRequestType == UT_WRITE_DEVICE && 1059 ur->request.bRequest == UR_SET_CONFIG) || 1060 (ur->request.bmRequestType == UT_WRITE_INTERFACE && 1061 ur->request.bRequest == UR_SET_INTERFACE)) 1062 return (EINVAL); 1063 1064 if (len < 0 || len > 32767) 1065 return (EINVAL); 1066 if (len != 0) { 1067 iov.iov_base = (caddr_t)ur->data; 1068 iov.iov_len = len; 1069 uio.uio_iov = &iov; 1070 uio.uio_iovcnt = 1; 1071 uio.uio_resid = len; 1072 uio.uio_offset = 0; 1073 uio.uio_segflg = UIO_USERSPACE; 1074 uio.uio_rw = 1075 ur->request.bmRequestType & UT_READ ? 1076 UIO_READ : UIO_WRITE; 1077 uio.uio_procp = p; 1078 ptr = malloc(len, M_TEMP, M_WAITOK); 1079 if (uio.uio_rw == UIO_WRITE) { 1080 error = uiomove(ptr, len, &uio); 1081 if (error) 1082 goto ret; 1083 } 1084 } 1085 err = usbd_do_request_flags(sc->sc_udev, &ur->request, 1086 ptr, ur->flags, &ur->actlen); 1087 if (err) { 1088 error = EIO; 1089 goto ret; 1090 } 1091 if (len != 0) { 1092 if (uio.uio_rw == UIO_READ) { 1093 error = uiomove(ptr, len, &uio); 1094 if (error) 1095 goto ret; 1096 } 1097 } 1098 ret: 1099 if (ptr) 1100 free(ptr, M_TEMP); 1101 return (error); 1102 } 1103 case USB_GET_DEVICEINFO: 1104 usbd_fill_deviceinfo(sc->sc_udev, 1105 (struct usb_device_info *)addr); 1106 break; 1107 default: 1108 return (EINVAL); 1109 } 1110 return (0); 1111 } 1112 1113 int 1114 ugenioctl(dev, cmd, addr, flag, p) 1115 dev_t dev; 1116 u_long cmd; 1117 caddr_t addr; 1118 int flag; 1119 struct proc *p; 1120 { 1121 int endpt = UGENENDPOINT(dev); 1122 struct ugen_softc *sc; 1123 int error; 1124 1125 USB_GET_SC(ugen, UGENUNIT(dev), sc); 1126 1127 sc->sc_refcnt++; 1128 error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p); 1129 if (--sc->sc_refcnt < 0) 1130 usb_detach_wakeup(USBDEV(sc->sc_dev)); 1131 return (error); 1132 } 1133 1134 int 1135 ugenpoll(dev, events, p) 1136 dev_t dev; 1137 int events; 1138 struct proc *p; 1139 { 1140 struct ugen_softc *sc; 1141 struct ugen_endpoint *sce; 1142 int revents = 0; 1143 int s; 1144 1145 USB_GET_SC(ugen, UGENUNIT(dev), sc); 1146 1147 if (sc->sc_dying) 1148 return (EIO); 1149 1150 /* XXX always IN */ 1151 sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; 1152 if (sce == NULL) 1153 return (EINVAL); 1154 #ifdef DIAGNOSTIC 1155 if (!sce->edesc) { 1156 printf("ugenpoll: no edesc\n"); 1157 return (EIO); 1158 } 1159 if (!sce->pipeh) { 1160 printf("ugenpoll: no pipe\n"); 1161 return (EIO); 1162 } 1163 #endif 1164 s = splusb(); 1165 switch (sce->edesc->bmAttributes & UE_XFERTYPE) { 1166 case UE_INTERRUPT: 1167 if (events & (POLLIN | POLLRDNORM)) { 1168 if (sce->q.c_cc > 0) 1169 revents |= events & (POLLIN | POLLRDNORM); 1170 else 1171 selrecord(p, &sce->rsel); 1172 } 1173 break; 1174 case UE_BULK: 1175 /* 1176 * We have no easy way of determining if a read will 1177 * yield any data or a write will happen. 1178 * Pretend they will. 1179 */ 1180 revents |= events & 1181 (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM); 1182 break; 1183 default: 1184 break; 1185 } 1186 splx(s); 1187 return (revents); 1188 } 1189 1190 #if defined(__FreeBSD__) 1191 DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0); 1192 #endif 1193