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