[BACK]Return to ugen.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/ugen.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb