root/dev/usb/ugen.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ugen_match
  2. ugen_attach
  3. ugen_set_config
  4. ugenopen
  5. ugenclose
  6. ugen_do_read
  7. ugenread
  8. ugen_do_write
  9. ugenwrite
  10. ugen_activate
  11. ugen_detach
  12. ugenintr
  13. ugen_isoc_rintr
  14. ugen_set_interface
  15. ugen_get_cdesc
  16. ugen_get_alt_index
  17. ugen_do_ioctl
  18. ugenioctl
  19. ugenpoll
  20. filt_ugenrdetach
  21. filt_ugenread_intr
  22. filt_ugenread_isoc
  23. ugenkqfilter

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

/* [<][>][^][v][top][bottom][index][help] */