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