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

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

1.1       nbrk        1: /*     $OpenBSD: urio.c,v 1.32 2007/06/14 10:11:16 mbalmer Exp $       */
                      2: /*     $NetBSD: urio.c,v 1.15 2002/10/23 09:14:02 jdolecek Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Lennart Augustsson (lennart@augustsson.net) at
                     10:  * Carlstedt Research & Technology.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *        This product includes software developed by the NetBSD
                     23:  *        Foundation, Inc. and its contributors.
                     24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     25:  *    contributors may be used to endorse or promote products derived
                     26:  *    from this software without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     38:  * POSSIBILITY OF SUCH DAMAGE.
                     39:  */
                     40:
                     41: /*
                     42:  * The inspiration and information for this driver comes from the
                     43:  * FreeBSD driver written by Iwasa Kazmi.
                     44:  */
                     45:
                     46: #include <sys/param.h>
                     47: #include <sys/systm.h>
                     48: #include <sys/kernel.h>
                     49: #include <sys/malloc.h>
                     50: #include <sys/device.h>
                     51: #include <sys/ioctl.h>
                     52: #include <sys/conf.h>
                     53: #include <sys/file.h>
                     54: #include <sys/selinfo.h>
                     55: #include <sys/proc.h>
                     56: #include <sys/vnode.h>
                     57: #include <sys/poll.h>
                     58:
                     59: #include <dev/usb/usb.h>
                     60: #include <dev/usb/usbdi.h>
                     61: #include <dev/usb/usbdi_util.h>
                     62:
                     63: #include <dev/usb/usbdevs.h>
                     64: #include <dev/usb/urio.h>
                     65:
                     66: #ifdef URIO_DEBUG
                     67: #define DPRINTF(x)     do { if (uriodebug) printf x; } while (0)
                     68: #define DPRINTFN(n,x)  do { if (uriodebug>(n)) printf x; } while (0)
                     69: int    uriodebug = 0;
                     70: #else
                     71: #define DPRINTF(x)
                     72: #define DPRINTFN(n,x)
                     73: #endif
                     74:
                     75: #define URIO_CONFIG_NO         1
                     76: #define URIO_IFACE_IDX         0
                     77:
                     78: #define        URIO_BSIZE      4096
                     79:
                     80: struct urio_softc {
                     81:        struct device           sc_dev;
                     82:        usbd_device_handle      sc_udev;
                     83:        usbd_interface_handle   sc_iface;
                     84:
                     85:        int                     sc_in_addr;
                     86:        usbd_pipe_handle        sc_in_pipe;
                     87:        int                     sc_out_addr;
                     88:        usbd_pipe_handle        sc_out_pipe;
                     89:
                     90:        int                     sc_refcnt;
                     91:        char                    sc_dying;
                     92: };
                     93:
                     94: #define URIOUNIT(n) (minor(n))
                     95:
                     96: #define URIO_RW_TIMEOUT 4000   /* ms */
                     97:
                     98: static const struct usb_devno urio_devs[] = {
                     99:        { USB_VENDOR_DIAMOND, USB_PRODUCT_DIAMOND_RIO500USB},
                    100:        { USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO600USB},
                    101:        { USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO800USB},
                    102:        { USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_PSAPLAY120},
                    103: };
                    104: #define urio_lookup(v, p) usb_lookup(urio_devs, v, p)
                    105:
                    106: int urio_match(struct device *, void *, void *);
                    107: void urio_attach(struct device *, struct device *, void *);
                    108: int urio_detach(struct device *, int);
                    109: int urio_activate(struct device *, enum devact);
                    110:
                    111: struct cfdriver urio_cd = {
                    112:        NULL, "urio", DV_DULL
                    113: };
                    114:
                    115: const struct cfattach urio_ca = {
                    116:        sizeof(struct urio_softc),
                    117:        urio_match,
                    118:        urio_attach,
                    119:        urio_detach,
                    120:        urio_activate,
                    121: };
                    122:
                    123: int
                    124: urio_match(struct device *parent, void *match, void *aux)
                    125: {
                    126:        struct usb_attach_arg   *uaa = aux;
                    127:
                    128:        DPRINTFN(50,("urio_match\n"));
                    129:
                    130:        if (uaa->iface != NULL)
                    131:                return (UMATCH_NONE);
                    132:
                    133:        return (urio_lookup(uaa->vendor, uaa->product) != NULL ?
                    134:                UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
                    135: }
                    136:
                    137: void
                    138: urio_attach(struct device *parent, struct device *self, void *aux)
                    139: {
                    140:        struct urio_softc       *sc = (struct urio_softc *)self;
                    141:        struct usb_attach_arg   *uaa = aux;
                    142:        usbd_device_handle      dev = uaa->device;
                    143:        usbd_interface_handle   iface;
                    144:        char                    *devinfop;
                    145:        usbd_status             err;
                    146:        usb_endpoint_descriptor_t *ed;
                    147:        u_int8_t                epcount;
                    148:        int                     i;
                    149:
                    150:        DPRINTFN(10,("urio_attach: sc=%p\n", sc));
                    151:
                    152:        devinfop = usbd_devinfo_alloc(dev, 0);
                    153:        printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
                    154:        usbd_devinfo_free(devinfop);
                    155:
                    156:        err = usbd_set_config_no(dev, URIO_CONFIG_NO, 1);
                    157:        if (err) {
                    158:                printf("%s: setting config no failed\n",
                    159:                    sc->sc_dev.dv_xname);
                    160:                return;
                    161:        }
                    162:
                    163:        err = usbd_device2interface_handle(dev, URIO_IFACE_IDX, &iface);
                    164:        if (err) {
                    165:                printf("%s: getting interface handle failed\n",
                    166:                    sc->sc_dev.dv_xname);
                    167:                return;
                    168:        }
                    169:
                    170:        sc->sc_udev = dev;
                    171:        sc->sc_iface = iface;
                    172:
                    173:        epcount = 0;
                    174:        (void)usbd_endpoint_count(iface, &epcount);
                    175:
                    176:        sc->sc_in_addr = -1;
                    177:        sc->sc_out_addr = -1;
                    178:        for (i = 0; i < epcount; i++) {
                    179:                ed = usbd_interface2endpoint_descriptor(iface, i);
                    180:                if (ed == NULL) {
                    181:                        printf("%s: couldn't get ep %d\n",
                    182:                            sc->sc_dev.dv_xname, i);
                    183:                        return;
                    184:                }
                    185:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                    186:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                    187:                        sc->sc_in_addr = ed->bEndpointAddress;
                    188:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
                    189:                           UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                    190:                        sc->sc_out_addr = ed->bEndpointAddress;
                    191:                }
                    192:        }
                    193:        if (sc->sc_in_addr == -1 || sc->sc_out_addr == -1) {
                    194:                printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
                    195:                return;
                    196:        }
                    197:
                    198:        DPRINTFN(10, ("urio_attach: %p\n", sc->sc_udev));
                    199:
                    200:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                    201:                           &sc->sc_dev);
                    202: }
                    203:
                    204: int
                    205: urio_detach(struct device *self, int flags)
                    206: {
                    207:        struct urio_softc *sc = (struct urio_softc *)self;
                    208:        int s;
                    209:        int maj, mn;
                    210:
                    211:        DPRINTF(("urio_detach: sc=%p flags=%d\n", sc, flags));
                    212:
                    213:        sc->sc_dying = 1;
                    214:        /* Abort all pipes.  Causes processes waiting for transfer to wake. */
                    215:        if (sc->sc_in_pipe != NULL) {
                    216:                usbd_abort_pipe(sc->sc_in_pipe);
                    217:                usbd_close_pipe(sc->sc_in_pipe);
                    218:                sc->sc_in_pipe = NULL;
                    219:        }
                    220:        if (sc->sc_out_pipe != NULL) {
                    221:                usbd_abort_pipe(sc->sc_out_pipe);
                    222:                usbd_close_pipe(sc->sc_out_pipe);
                    223:                sc->sc_out_pipe = NULL;
                    224:        }
                    225:
                    226:        s = splusb();
                    227:        if (--sc->sc_refcnt >= 0) {
                    228:                /* Wait for processes to go away. */
                    229:                usb_detach_wait(&sc->sc_dev);
                    230:        }
                    231:        splx(s);
                    232:
                    233:        /* locate the major number */
                    234:        for (maj = 0; maj < nchrdev; maj++)
                    235:                if (cdevsw[maj].d_open == urioopen)
                    236:                        break;
                    237:
                    238:        /* Nuke the vnodes for any open instances (calls close). */
                    239:        mn = self->dv_unit;
                    240:        vdevgone(maj, mn, mn, VCHR);
                    241:
                    242:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
                    243:                           &sc->sc_dev);
                    244:
                    245:        return (0);
                    246: }
                    247:
                    248: int
                    249: urio_activate(struct device *self, enum devact act)
                    250: {
                    251:        struct urio_softc *sc = (struct urio_softc *)self;
                    252:
                    253:        switch (act) {
                    254:        case DVACT_ACTIVATE:
                    255:                break;
                    256:
                    257:        case DVACT_DEACTIVATE:
                    258:                sc->sc_dying = 1;
                    259:                break;
                    260:        }
                    261:        return (0);
                    262: }
                    263:
                    264: int
                    265: urioopen(dev_t dev, int flag, int mode, struct proc *p)
                    266: {
                    267:        struct urio_softc *sc;
                    268:        usbd_status err;
                    269:
                    270:        if (URIOUNIT(dev) >= urio_cd.cd_ndevs)
                    271:                return (ENXIO);
                    272:        sc = urio_cd.cd_devs[URIOUNIT(dev)];
                    273:        if (sc == NULL)
                    274:                return (ENXIO);
                    275:
                    276:        DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n",
                    277:                     flag, mode, URIOUNIT(dev)));
                    278:
                    279:        if (sc->sc_dying)
                    280:                return (EIO);
                    281:
                    282:        if (sc->sc_in_pipe != NULL)
                    283:                return (EBUSY);
                    284:
                    285:        if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD))
                    286:                return (EACCES);
                    287:
                    288:        err = usbd_open_pipe(sc->sc_iface, sc->sc_in_addr, 0, &sc->sc_in_pipe);
                    289:        if (err)
                    290:                return (EIO);
                    291:        err = usbd_open_pipe(sc->sc_iface, sc->sc_out_addr,0,&sc->sc_out_pipe);
                    292:        if (err) {
                    293:                usbd_close_pipe(sc->sc_in_pipe);
                    294:                sc->sc_in_pipe = NULL;
                    295:                return (EIO);
                    296:        }
                    297:
                    298:        return (0);
                    299: }
                    300:
                    301: int
                    302: urioclose(dev_t dev, int flag, int mode, struct proc *p)
                    303: {
                    304:        struct urio_softc *sc;
                    305:        sc = urio_cd.cd_devs[URIOUNIT(dev)];
                    306:
                    307:        DPRINTFN(5, ("urioclose: flag=%d, mode=%d, unit=%d\n",
                    308:                     flag, mode, URIOUNIT(dev)));
                    309:
                    310:        if (sc->sc_in_pipe != NULL) {
                    311:                usbd_abort_pipe(sc->sc_in_pipe);
                    312:                usbd_close_pipe(sc->sc_in_pipe);
                    313:                sc->sc_in_pipe = NULL;
                    314:        }
                    315:        if (sc->sc_out_pipe != NULL) {
                    316:                usbd_abort_pipe(sc->sc_out_pipe);
                    317:                usbd_close_pipe(sc->sc_out_pipe);
                    318:                sc->sc_out_pipe = NULL;
                    319:        }
                    320:
                    321:        return (0);
                    322: }
                    323:
                    324: int
                    325: urioread(dev_t dev, struct uio *uio, int flag)
                    326: {
                    327:        struct urio_softc *sc;
                    328:        usbd_xfer_handle xfer;
                    329:        usbd_status err;
                    330:        void *bufp;
                    331:        u_int32_t n, tn;
                    332:        int error = 0;
                    333:
                    334:        sc = urio_cd.cd_devs[URIOUNIT(dev)];
                    335:
                    336:        DPRINTFN(5, ("urioread: %d\n", URIOUNIT(dev)));
                    337:
                    338:        if (sc->sc_dying)
                    339:                return (EIO);
                    340:
                    341:        xfer = usbd_alloc_xfer(sc->sc_udev);
                    342:        if (xfer == NULL)
                    343:                return (ENOMEM);
                    344:        bufp = usbd_alloc_buffer(xfer, URIO_BSIZE);
                    345:        if (bufp == NULL) {
                    346:                usbd_free_xfer(xfer);
                    347:                return (ENOMEM);
                    348:        }
                    349:
                    350:        sc->sc_refcnt++;
                    351:
                    352:        while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) {
                    353:                DPRINTFN(1, ("urioread: start transfer %d bytes\n", n));
                    354:                tn = n;
                    355:                err = usbd_bulk_transfer(xfer, sc->sc_in_pipe, USBD_NO_COPY,
                    356:                          URIO_RW_TIMEOUT, bufp, &tn, "uriors");
                    357:                if (err) {
                    358:                        if (err == USBD_INTERRUPTED)
                    359:                                error = EINTR;
                    360:                        else if (err == USBD_TIMEOUT)
                    361:                                error = ETIMEDOUT;
                    362:                        else
                    363:                                error = EIO;
                    364:                        break;
                    365:                }
                    366:
                    367:                DPRINTFN(1, ("urioread: got %d bytes\n", tn));
                    368:
                    369:                error = uiomove(bufp, tn, uio);
                    370:                if (error || tn < n)
                    371:                        break;
                    372:        }
                    373:        usbd_free_xfer(xfer);
                    374:
                    375:        if (--sc->sc_refcnt < 0)
                    376:                usb_detach_wakeup(&sc->sc_dev);
                    377:
                    378:        return (error);
                    379: }
                    380:
                    381: int
                    382: uriowrite(dev_t dev, struct uio *uio, int flag)
                    383: {
                    384:        struct urio_softc *sc;
                    385:        usbd_xfer_handle xfer;
                    386:        usbd_status err;
                    387:        void *bufp;
                    388:        u_int32_t n;
                    389:        int error = 0;
                    390:
                    391:        sc = urio_cd.cd_devs[URIOUNIT(dev)];
                    392:
                    393:        DPRINTFN(5, ("uriowrite: unit=%d, len=%ld\n", URIOUNIT(dev),
                    394:                     (long)uio->uio_resid));
                    395:
                    396:        if (sc->sc_dying)
                    397:                return (EIO);
                    398:
                    399:        xfer = usbd_alloc_xfer(sc->sc_udev);
                    400:        if (xfer == NULL)
                    401:                return (ENOMEM);
                    402:        bufp = usbd_alloc_buffer(xfer, URIO_BSIZE);
                    403:        if (bufp == NULL) {
                    404:                usbd_free_xfer(xfer);
                    405:                return (ENOMEM);
                    406:        }
                    407:
                    408:        sc->sc_refcnt++;
                    409:
                    410:        while ((n = min(URIO_BSIZE, uio->uio_resid)) != 0) {
                    411:                error = uiomove(bufp, n, uio);
                    412:                if (error)
                    413:                        break;
                    414:
                    415:                DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n));
                    416:
                    417:                err = usbd_bulk_transfer(xfer, sc->sc_out_pipe, USBD_NO_COPY,
                    418:                          URIO_RW_TIMEOUT, bufp, &n, "uriowr");
                    419:                DPRINTFN(2, ("uriowrite: err=%d\n", err));
                    420:                if (err) {
                    421:                        if (err == USBD_INTERRUPTED)
                    422:                                error = EINTR;
                    423:                        else if (err == USBD_TIMEOUT)
                    424:                                error = ETIMEDOUT;
                    425:                        else
                    426:                                error = EIO;
                    427:                        break;
                    428:                }
                    429:        }
                    430:
                    431:        usbd_free_xfer(xfer);
                    432:
                    433:        if (--sc->sc_refcnt < 0)
                    434:                usb_detach_wakeup(&sc->sc_dev);
                    435:
                    436:        DPRINTFN(5, ("uriowrite: done unit=%d, error=%d\n", URIOUNIT(dev),
                    437:                     error));
                    438:
                    439:        return (error);
                    440: }
                    441:
                    442:
                    443: int
                    444: urioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
                    445: {
                    446:        struct urio_softc * sc;
                    447:        int unit = URIOUNIT(dev);
                    448:        struct urio_command *rcmd;
                    449:        int requesttype, len;
                    450:        struct iovec iov;
                    451:        struct uio uio;
                    452:        usb_device_request_t req;
                    453:        usbd_status err;
                    454:        int req_flags = 0;
                    455:        u_int32_t req_actlen = 0;
                    456:        void *ptr = NULL;
                    457:        int error = 0;
                    458:
                    459:        sc = urio_cd.cd_devs[unit];
                    460:
                    461:        if (sc->sc_dying)
                    462:                return (EIO);
                    463:
                    464:        rcmd = (struct urio_command *)addr;
                    465:
                    466:        switch (cmd) {
                    467:        case URIO_RECV_COMMAND:
                    468:                requesttype = rcmd->requesttype | UT_READ_VENDOR_DEVICE;
                    469:                break;
                    470:
                    471:        case URIO_SEND_COMMAND:
                    472:                requesttype = rcmd->requesttype | UT_WRITE_VENDOR_DEVICE;
                    473:                break;
                    474:
                    475:        default:
                    476:                return (EINVAL);
                    477:                break;
                    478:        }
                    479:
                    480:        if (!(flag & FWRITE))
                    481:                return (EPERM);
                    482:        len = rcmd->length;
                    483:
                    484:        DPRINTFN(1,("urio_ioctl: cmd=0x%08lx reqtype=0x%0x req=0x%0x "
                    485:                    "value=0x%0x index=0x%0x len=0x%0x\n",
                    486:                    cmd, requesttype, rcmd->request, rcmd->value,
                    487:                    rcmd->index, len));
                    488:
                    489:        /* Send rio control message */
                    490:        req.bmRequestType = requesttype;
                    491:        req.bRequest = rcmd->request;
                    492:        USETW(req.wValue, rcmd->value);
                    493:        USETW(req.wIndex, rcmd->index);
                    494:        USETW(req.wLength, len);
                    495:
                    496:        if (len < 0 || len > 32767)
                    497:                return (EINVAL);
                    498:        if (len != 0) {
                    499:                iov.iov_base = (caddr_t)rcmd->buffer;
                    500:                iov.iov_len = len;
                    501:                uio.uio_iov = &iov;
                    502:                uio.uio_iovcnt = 1;
                    503:                uio.uio_resid = len;
                    504:                uio.uio_offset = 0;
                    505:                uio.uio_segflg = UIO_USERSPACE;
                    506:                uio.uio_rw = req.bmRequestType & UT_READ ?
                    507:                             UIO_READ : UIO_WRITE;
                    508:                uio.uio_procp = p;
                    509:                ptr = malloc(len, M_TEMP, M_WAITOK);
                    510:                if (uio.uio_rw == UIO_WRITE) {
                    511:                        error = uiomove(ptr, len, &uio);
                    512:                        if (error)
                    513:                                goto ret;
                    514:                }
                    515:        }
                    516:
                    517:        sc->sc_refcnt++;
                    518:
                    519:        err = usbd_do_request_flags(sc->sc_udev, &req, ptr, req_flags,
                    520:                  &req_actlen, USBD_DEFAULT_TIMEOUT);
                    521:
                    522:        if (--sc->sc_refcnt < 0)
                    523:                usb_detach_wakeup(&sc->sc_dev);
                    524:
                    525:        if (err) {
                    526:                error = EIO;
                    527:        } else {
                    528:                if (len != 0 && uio.uio_rw == UIO_READ)
                    529:                        error = uiomove(ptr, len, &uio);
                    530:        }
                    531:
                    532: ret:
                    533:        if (ptr != NULL)
                    534:                free(ptr, M_TEMP);
                    535:        return (error);
                    536: }
                    537:
                    538: int
                    539: uriopoll(dev_t dev, int events, struct proc *p)
                    540: {
                    541:        return (0);
                    542: }

CVSweb