[BACK]Return to uhid.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/uhid.c, Revision 1.43

1.43    ! augustss    1: /*     $NetBSD: uhid.c,v 1.42 2000/12/29 01:47:49 augustss Exp $       */
1.28      augustss    2: /*     $FreeBSD: src/sys/dev/usb/uhid.c,v 1.22 1999/11/17 22:33:43 n_hibma Exp $       */
1.1       augustss    3:
                      4: /*
                      5:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
1.6       augustss    8:  * This code is derived from software contributed to The NetBSD Foundation
1.38      augustss    9:  * by Lennart Augustsson (lennart@augustsson.net) at
1.6       augustss   10:  * Carlstedt Research & Technology.
1.1       augustss   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:
1.15      augustss   41: /*
1.41      augustss   42:  * HID spec: http://www.usb.org/developers/data/devclass/hid1_1.pdf
1.15      augustss   43:  */
1.1       augustss   44:
                     45: #include <sys/param.h>
                     46: #include <sys/systm.h>
                     47: #include <sys/kernel.h>
                     48: #include <sys/malloc.h>
1.37      augustss   49: #include <sys/signalvar.h>
1.20      augustss   50: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.14      augustss   51: #include <sys/device.h>
1.12      augustss   52: #include <sys/ioctl.h>
                     53: #elif defined(__FreeBSD__)
                     54: #include <sys/ioccom.h>
                     55: #include <sys/filio.h>
                     56: #include <sys/module.h>
                     57: #include <sys/bus.h>
1.14      augustss   58: #include <sys/ioccom.h>
1.12      augustss   59: #endif
1.18      augustss   60: #include <sys/conf.h>
1.1       augustss   61: #include <sys/tty.h>
                     62: #include <sys/file.h>
                     63: #include <sys/select.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/vnode.h>
                     66: #include <sys/poll.h>
                     67:
                     68: #include <dev/usb/usb.h>
                     69: #include <dev/usb/usbhid.h>
                     70:
1.42      augustss   71: #include <dev/usb/usbdevs.h>
1.1       augustss   72: #include <dev/usb/usbdi.h>
                     73: #include <dev/usb/usbdi_util.h>
                     74: #include <dev/usb/hid.h>
                     75: #include <dev/usb/usb_quirks.h>
                     76:
1.42      augustss   77: /* Report descriptor for broken Wacom Graphire */
                     78: #include <dev/usb/ugraphire_rdesc.h>
                     79:
1.26      augustss   80: #ifdef UHID_DEBUG
1.19      augustss   81: #define DPRINTF(x)     if (uhiddebug) logprintf x
                     82: #define DPRINTFN(n,x)  if (uhiddebug>(n)) logprintf x
1.1       augustss   83: int    uhiddebug = 0;
                     84: #else
                     85: #define DPRINTF(x)
                     86: #define DPRINTFN(n,x)
                     87: #endif
                     88:
                     89: struct uhid_softc {
1.24      augustss   90:        USBBASEDEVICE sc_dev;                   /* base device */
1.32      augustss   91:        usbd_device_handle sc_udev;
1.1       augustss   92:        usbd_interface_handle sc_iface; /* interface */
                     93:        usbd_pipe_handle sc_intrpipe;   /* interrupt pipe */
                     94:        int sc_ep_addr;
                     95:
                     96:        int sc_isize;
                     97:        int sc_osize;
1.2       augustss   98:        int sc_fsize;
1.1       augustss   99:        u_int8_t sc_iid;
                    100:        u_int8_t sc_oid;
1.2       augustss  101:        u_int8_t sc_fid;
1.1       augustss  102:
1.33      augustss  103:        u_char *sc_ibuf;
                    104:        u_char *sc_obuf;
1.1       augustss  105:
                    106:        void *sc_repdesc;
                    107:        int sc_repdesc_size;
                    108:
                    109:        struct clist sc_q;
                    110:        struct selinfo sc_rsel;
1.37      augustss  111:        struct proc *sc_async;  /* process that wants SIGIO */
1.1       augustss  112:        u_char sc_state;        /* driver state */
                    113: #define        UHID_OPEN       0x01    /* device is open */
1.5       augustss  114: #define        UHID_ASLP       0x02    /* waiting for device data */
1.1       augustss  115: #define UHID_NEEDCLEAR 0x04    /* needs clearing endpoint stall */
1.2       augustss  116: #define UHID_IMMED     0x08    /* return read data immediately */
1.18      augustss  117:
                    118:        int sc_refcnt;
                    119:        u_char sc_dying;
1.1       augustss  120: };
                    121:
                    122: #define        UHIDUNIT(dev)   (minor(dev))
                    123: #define        UHID_CHUNK      128     /* chunk size for read */
                    124: #define        UHID_BSIZE      1020    /* buffer size */
                    125:
1.20      augustss  126: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.19      augustss  127: cdev_decl(uhid);
                    128: #elif defined(__FreeBSD__)
                    129: d_open_t       uhidopen;
                    130: d_close_t      uhidclose;
                    131: d_read_t       uhidread;
                    132: d_write_t      uhidwrite;
                    133: d_ioctl_t      uhidioctl;
                    134: d_poll_t       uhidpoll;
                    135:
                    136: #define                UHID_CDEV_MAJOR 122
                    137:
1.36      augustss  138: Static struct cdevsw uhid_cdevsw = {
1.19      augustss  139:        /* open */      uhidopen,
                    140:        /* close */     uhidclose,
                    141:        /* read */      uhidread,
                    142:        /* write */     uhidwrite,
                    143:        /* ioctl */     uhidioctl,
                    144:        /* poll */      uhidpoll,
                    145:        /* mmap */      nommap,
                    146:        /* strategy */  nostrategy,
                    147:        /* name */      "uhid",
                    148:        /* maj */       UHID_CDEV_MAJOR,
                    149:        /* dump */      nodump,
                    150:        /* psize */     nopsize,
                    151:        /* flags */     0,
                    152:        /* bmaj */      -1
                    153: };
                    154: #endif
                    155:
1.39      augustss  156: Static void uhid_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
1.18      augustss  157:
1.39      augustss  158: Static int uhid_do_read(struct uhid_softc *, struct uio *uio, int);
                    159: Static int uhid_do_write(struct uhid_softc *, struct uio *uio, int);
                    160: Static int uhid_do_ioctl(struct uhid_softc*, u_long, caddr_t, int,struct proc*);
1.1       augustss  161:
1.12      augustss  162: USB_DECLARE_DRIVER(uhid);
1.1       augustss  163:
1.12      augustss  164: USB_MATCH(uhid)
1.1       augustss  165: {
1.12      augustss  166:        USB_MATCH_START(uhid, uaa);
1.1       augustss  167:        usb_interface_descriptor_t *id;
                    168:
1.28      augustss  169:        if (uaa->iface == NULL)
1.1       augustss  170:                return (UMATCH_NONE);
                    171:        id = usbd_get_interface_descriptor(uaa->iface);
1.34      augustss  172:        if (id == NULL || id->bInterfaceClass != UICLASS_HID)
1.1       augustss  173:                return (UMATCH_NONE);
1.43    ! augustss  174:        if (uaa->matchlvl)
        !           175:                return (uaa->matchlvl);
1.1       augustss  176:        return (UMATCH_IFACECLASS_GENERIC);
                    177: }
                    178:
1.12      augustss  179: USB_ATTACH(uhid)
1.1       augustss  180: {
1.12      augustss  181:        USB_ATTACH_START(uhid, sc, uaa);
1.1       augustss  182:        usbd_interface_handle iface = uaa->iface;
                    183:        usb_interface_descriptor_t *id;
                    184:        usb_endpoint_descriptor_t *ed;
                    185:        int size;
                    186:        void *desc;
1.27      augustss  187:        usbd_status err;
1.1       augustss  188:        char devinfo[1024];
                    189:
1.32      augustss  190:        sc->sc_udev = uaa->device;
1.1       augustss  191:        sc->sc_iface = iface;
                    192:        id = usbd_get_interface_descriptor(iface);
                    193:        usbd_devinfo(uaa->device, 0, devinfo);
1.12      augustss  194:        USB_ATTACH_SETUP;
                    195:        printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
1.7       augustss  196:               devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
1.12      augustss  197:
1.1       augustss  198:        ed = usbd_interface2endpoint_descriptor(iface, 0);
1.27      augustss  199:        if (ed == NULL) {
1.1       augustss  200:                printf("%s: could not read endpoint descriptor\n",
1.12      augustss  201:                       USBDEVNAME(sc->sc_dev));
1.18      augustss  202:                sc->sc_dying = 1;
1.12      augustss  203:                USB_ATTACH_ERROR_RETURN;
1.1       augustss  204:        }
                    205:
1.11      augustss  206:        DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d "
                    207:                     "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
                    208:                     " bInterval=%d\n",
                    209:                     ed->bLength, ed->bDescriptorType,
                    210:                     ed->bEndpointAddress & UE_ADDR,
1.23      augustss  211:                     UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
1.11      augustss  212:                     ed->bmAttributes & UE_XFERTYPE,
                    213:                     UGETW(ed->wMaxPacketSize), ed->bInterval));
1.1       augustss  214:
1.23      augustss  215:        if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
1.1       augustss  216:            (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
1.12      augustss  217:                printf("%s: unexpected endpoint\n", USBDEVNAME(sc->sc_dev));
1.18      augustss  218:                sc->sc_dying = 1;
1.12      augustss  219:                USB_ATTACH_ERROR_RETURN;
1.1       augustss  220:        }
                    221:
                    222:        sc->sc_ep_addr = ed->bEndpointAddress;
                    223:
1.42      augustss  224:        if (uaa->vendor == USB_VENDOR_WACOM &&
                    225:            uaa->product == USB_PRODUCT_WACOM_GRAPHIRE /* &&
                    226:            uaa->revision == 0x???? */) { /* XXX should use revision */
                    227:                /* The report descriptor for the Wacom Graphire is broken. */
                    228:                size = sizeof uhid_graphire_report_descr;
                    229:                desc = malloc(size, M_USBDEV, M_NOWAIT);
                    230:                if (desc == NULL)
                    231:                        err = USBD_NOMEM;
                    232:                else {
                    233:                        err = USBD_NORMAL_COMPLETION;
                    234:                        memcpy(desc, uhid_graphire_report_descr, size);
                    235:                }
                    236:        } else {
                    237:                desc = NULL;
                    238:                err = usbd_alloc_report_desc(uaa->iface, &desc, &size,M_USBDEV);
                    239:        }
1.27      augustss  240:        if (err) {
1.12      augustss  241:                printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));
1.18      augustss  242:                sc->sc_dying = 1;
1.12      augustss  243:                USB_ATTACH_ERROR_RETURN;
1.1       augustss  244:        }
                    245:
                    246:        (void)usbd_set_idle(iface, 0, 0);
                    247:
1.2       augustss  248:        sc->sc_isize = hid_report_size(desc, size, hid_input,   &sc->sc_iid);
                    249:        sc->sc_osize = hid_report_size(desc, size, hid_output,  &sc->sc_oid);
                    250:        sc->sc_fsize = hid_report_size(desc, size, hid_feature, &sc->sc_fid);
1.1       augustss  251:
                    252:        sc->sc_repdesc = desc;
                    253:        sc->sc_repdesc_size = size;
1.12      augustss  254:
1.28      augustss  255: #ifdef __FreeBSD__
                    256:        {
                    257:                static int global_init_done = 0;
                    258:
                    259:                if (!global_init_done) {
                    260:                        cdevsw_add(&uhid_cdevsw);
                    261:                        global_init_done = 1;
                    262:                }
                    263:        }
                    264: #endif
                    265:
1.32      augustss  266:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                    267:                           USBDEV(sc->sc_dev));
                    268:
1.12      augustss  269:        USB_ATTACH_SUCCESS_RETURN;
1.1       augustss  270: }
                    271:
1.26      augustss  272: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.18      augustss  273: int
1.39      augustss  274: uhid_activate(device_ptr_t self, enum devact act)
1.18      augustss  275: {
1.21      augustss  276:        struct uhid_softc *sc = (struct uhid_softc *)self;
                    277:
                    278:        switch (act) {
                    279:        case DVACT_ACTIVATE:
                    280:                return (EOPNOTSUPP);
                    281:                break;
                    282:
                    283:        case DVACT_DEACTIVATE:
                    284:                sc->sc_dying = 1;
                    285:                break;
                    286:        }
1.18      augustss  287:        return (0);
1.12      augustss  288: }
1.26      augustss  289: #endif
1.12      augustss  290:
1.26      augustss  291: USB_DETACH(uhid)
1.1       augustss  292: {
1.26      augustss  293:        USB_DETACH_START(uhid, sc);
                    294:        int s;
                    295: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.18      augustss  296:        int maj, mn;
                    297:
                    298:        DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags));
1.26      augustss  299: #else
                    300:        DPRINTF(("uhid_detach: sc=%p\n", sc));
                    301: #endif
1.3       augustss  302:
1.18      augustss  303:        sc->sc_dying = 1;
1.27      augustss  304:        if (sc->sc_intrpipe != NULL)
1.18      augustss  305:                usbd_abort_pipe(sc->sc_intrpipe);
                    306:
                    307:        if (sc->sc_state & UHID_OPEN) {
                    308:                s = splusb();
                    309:                if (--sc->sc_refcnt >= 0) {
                    310:                        /* Wake everyone */
                    311:                        wakeup(&sc->sc_q);
                    312:                        /* Wait for processes to go away. */
1.24      augustss  313:                        usb_detach_wait(USBDEV(sc->sc_dev));
1.18      augustss  314:                }
                    315:                splx(s);
                    316:        }
                    317:
1.26      augustss  318: #if defined(__NetBSD__) || defined(__OpenBSD__)
1.18      augustss  319:        /* locate the major number */
                    320:        for (maj = 0; maj < nchrdev; maj++)
                    321:                if (cdevsw[maj].d_open == uhidopen)
                    322:                        break;
                    323:
                    324:        /* Nuke the vnodes for any open instances (calls close). */
                    325:        mn = self->dv_unit;
                    326:        vdevgone(maj, mn, mn, VCHR);
1.26      augustss  327: #elif defined(__FreeBSD__)
                    328:        /* XXX not implemented yet */
                    329: #endif
1.18      augustss  330:
1.40      augustss  331:        if (sc->sc_repdesc)
                    332:                free(sc->sc_repdesc, M_USBDEV);
1.32      augustss  333:
                    334:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
                    335:                           USBDEV(sc->sc_dev));
1.18      augustss  336:
                    337:        return (0);
1.1       augustss  338: }
                    339:
                    340: void
1.39      augustss  341: uhid_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
1.1       augustss  342: {
                    343:        struct uhid_softc *sc = addr;
                    344:
1.33      augustss  345: #ifdef UHID_DEBUG
                    346:        if (uhiddebug > 5) {
                    347:                u_int32_t cc, i;
                    348:
                    349:                usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
                    350:                DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc));
                    351:                DPRINTF(("uhid_intr: data ="));
                    352:                for (i = 0; i < cc; i++)
                    353:                        DPRINTF((" %02x", sc->sc_ibuf[i]));
                    354:                DPRINTF(("\n"));
                    355:        }
                    356: #endif
1.1       augustss  357:
                    358:        if (status == USBD_CANCELLED)
                    359:                return;
                    360:
                    361:        if (status != USBD_NORMAL_COMPLETION) {
                    362:                DPRINTF(("uhid_intr: status=%d\n", status));
                    363:                sc->sc_state |= UHID_NEEDCLEAR;
                    364:                return;
                    365:        }
                    366:
                    367:        (void) b_to_q(sc->sc_ibuf, sc->sc_isize, &sc->sc_q);
                    368:
                    369:        if (sc->sc_state & UHID_ASLP) {
                    370:                sc->sc_state &= ~UHID_ASLP;
                    371:                DPRINTFN(5, ("uhid_intr: waking %p\n", sc));
1.18      augustss  372:                wakeup(&sc->sc_q);
1.1       augustss  373:        }
                    374:        selwakeup(&sc->sc_rsel);
1.37      augustss  375:        if (sc->sc_async != NULL) {
                    376:                DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async));
                    377:                psignal(sc->sc_async, SIGIO);
                    378:        }
1.1       augustss  379: }
                    380:
                    381: int
1.39      augustss  382: uhidopen(dev_t dev, int flag, int mode, struct proc *p)
1.1       augustss  383: {
1.25      augustss  384:        struct uhid_softc *sc;
1.27      augustss  385:        usbd_status err;
1.25      augustss  386:
1.12      augustss  387:        USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);
1.1       augustss  388:
1.18      augustss  389:        DPRINTF(("uhidopen: sc=%p\n", sc));
1.1       augustss  390:
1.18      augustss  391:        if (sc->sc_dying)
                    392:                return (ENXIO);
1.1       augustss  393:
                    394:        if (sc->sc_state & UHID_OPEN)
1.12      augustss  395:                return (EBUSY);
1.17      augustss  396:        sc->sc_state |= UHID_OPEN;
1.1       augustss  397:
1.17      augustss  398:        if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) {
                    399:                sc->sc_state &= ~UHID_OPEN;
1.12      augustss  400:                return (ENOMEM);
1.17      augustss  401:        }
1.1       augustss  402:
1.18      augustss  403:        sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
                    404:        sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
1.1       augustss  405:
                    406:        /* Set up interrupt pipe. */
1.27      augustss  407:        err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
                    408:                  USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,
1.31      augustss  409:                  sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL);
1.27      augustss  410:        if (err) {
1.11      augustss  411:                DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
1.27      augustss  412:                         "error=%d\n",err));
1.18      augustss  413:                free(sc->sc_ibuf, M_USBDEV);
                    414:                free(sc->sc_obuf, M_USBDEV);
1.1       augustss  415:                sc->sc_state &= ~UHID_OPEN;
                    416:                return (EIO);
                    417:        }
1.17      augustss  418:
                    419:        sc->sc_state &= ~UHID_IMMED;
                    420:
1.37      augustss  421:        sc->sc_async = 0;
                    422:
1.12      augustss  423:        return (0);
1.1       augustss  424: }
                    425:
                    426: int
1.39      augustss  427: uhidclose(dev_t dev, int flag, int mode, struct proc *p)
1.1       augustss  428: {
1.25      augustss  429:        struct uhid_softc *sc;
                    430:
1.12      augustss  431:        USB_GET_SC(uhid, UHIDUNIT(dev), sc);
1.1       augustss  432:
                    433:        DPRINTF(("uhidclose: sc=%p\n", sc));
                    434:
                    435:        /* Disable interrupts. */
                    436:        usbd_abort_pipe(sc->sc_intrpipe);
                    437:        usbd_close_pipe(sc->sc_intrpipe);
1.18      augustss  438:        sc->sc_intrpipe = 0;
1.1       augustss  439:
                    440:        clfree(&sc->sc_q);
                    441:
1.18      augustss  442:        free(sc->sc_ibuf, M_USBDEV);
                    443:        free(sc->sc_obuf, M_USBDEV);
1.17      augustss  444:
                    445:        sc->sc_state &= ~UHID_OPEN;
1.1       augustss  446:
1.37      augustss  447:        sc->sc_async = 0;
                    448:
1.12      augustss  449:        return (0);
1.1       augustss  450: }
                    451:
                    452: int
1.39      augustss  453: uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag)
1.1       augustss  454: {
                    455:        int s;
                    456:        int error = 0;
                    457:        size_t length;
                    458:        u_char buffer[UHID_CHUNK];
1.27      augustss  459:        usbd_status err;
1.1       augustss  460:
                    461:        DPRINTFN(1, ("uhidread\n"));
1.2       augustss  462:        if (sc->sc_state & UHID_IMMED) {
                    463:                DPRINTFN(1, ("uhidread immed\n"));
                    464:
1.27      augustss  465:                err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
1.16      augustss  466:                                    sc->sc_iid, buffer, sc->sc_isize);
1.27      augustss  467:                if (err)
1.2       augustss  468:                        return (EIO);
                    469:                return (uiomove(buffer, sc->sc_isize, uio));
                    470:        }
                    471:
1.10      augustss  472:        s = splusb();
1.1       augustss  473:        while (sc->sc_q.c_cc == 0) {
                    474:                if (flag & IO_NDELAY) {
                    475:                        splx(s);
1.18      augustss  476:                        return (EWOULDBLOCK);
1.1       augustss  477:                }
                    478:                sc->sc_state |= UHID_ASLP;
                    479:                DPRINTFN(5, ("uhidread: sleep on %p\n", sc));
1.18      augustss  480:                error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0);
1.1       augustss  481:                DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
1.18      augustss  482:                if (sc->sc_dying)
                    483:                        error = EIO;
1.1       augustss  484:                if (error) {
                    485:                        sc->sc_state &= ~UHID_ASLP;
1.18      augustss  486:                        break;
1.1       augustss  487:                }
                    488:                if (sc->sc_state & UHID_NEEDCLEAR) {
                    489:                        DPRINTFN(-1,("uhidread: clearing stall\n"));
                    490:                        sc->sc_state &= ~UHID_NEEDCLEAR;
                    491:                        usbd_clear_endpoint_stall(sc->sc_intrpipe);
                    492:                }
                    493:        }
                    494:        splx(s);
                    495:
                    496:        /* Transfer as many chunks as possible. */
1.18      augustss  497:        while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) {
1.1       augustss  498:                length = min(sc->sc_q.c_cc, uio->uio_resid);
                    499:                if (length > sizeof(buffer))
                    500:                        length = sizeof(buffer);
                    501:
                    502:                /* Remove a small chunk from the input queue. */
                    503:                (void) q_to_b(&sc->sc_q, buffer, length);
1.29      augustss  504:                DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length));
1.1       augustss  505:
                    506:                /* Copy the data to the user process. */
                    507:                if ((error = uiomove(buffer, length, uio)) != 0)
                    508:                        break;
                    509:        }
                    510:
                    511:        return (error);
                    512: }
                    513:
                    514: int
1.39      augustss  515: uhidread(dev_t dev, struct uio *uio, int flag)
1.1       augustss  516: {
1.25      augustss  517:        struct uhid_softc *sc;
                    518:        int error;
                    519:
1.18      augustss  520:        USB_GET_SC(uhid, UHIDUNIT(dev), sc);
                    521:
                    522:        sc->sc_refcnt++;
                    523:        error = uhid_do_read(sc, uio, flag);
                    524:        if (--sc->sc_refcnt < 0)
1.24      augustss  525:                usb_detach_wakeup(USBDEV(sc->sc_dev));
1.18      augustss  526:        return (error);
                    527: }
                    528:
                    529: int
1.39      augustss  530: uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag)
1.18      augustss  531: {
1.1       augustss  532:        int error;
                    533:        int size;
1.27      augustss  534:        usbd_status err;
1.1       augustss  535:
1.18      augustss  536:        DPRINTFN(1, ("uhidwrite\n"));
                    537:
                    538:        if (sc->sc_dying)
1.1       augustss  539:                return (EIO);
                    540:
                    541:        size = sc->sc_osize;
                    542:        error = 0;
1.18      augustss  543:        if (uio->uio_resid != size)
                    544:                return (EINVAL);
                    545:        error = uiomove(sc->sc_obuf, size, uio);
                    546:        if (!error) {
1.1       augustss  547:                if (sc->sc_oid)
1.27      augustss  548:                        err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
                    549:                                  sc->sc_obuf[0], sc->sc_obuf+1, size-1);
1.1       augustss  550:                else
1.27      augustss  551:                        err = usbd_set_report(sc->sc_iface, UHID_OUTPUT_REPORT,
                    552:                                  0, sc->sc_obuf, size);
                    553:                if (err)
1.1       augustss  554:                        error = EIO;
                    555:        }
1.18      augustss  556:
1.1       augustss  557:        return (error);
                    558: }
                    559:
                    560: int
1.39      augustss  561: uhidwrite(dev_t dev, struct uio *uio, int flag)
1.18      augustss  562: {
1.25      augustss  563:        struct uhid_softc *sc;
                    564:        int error;
                    565:
1.18      augustss  566:        USB_GET_SC(uhid, UHIDUNIT(dev), sc);
                    567:
                    568:        sc->sc_refcnt++;
                    569:        error = uhid_do_write(sc, uio, flag);
                    570:        if (--sc->sc_refcnt < 0)
1.24      augustss  571:                usb_detach_wakeup(USBDEV(sc->sc_dev));
1.18      augustss  572:        return (error);
                    573: }
                    574:
                    575: int
1.39      augustss  576: uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr,
                    577:              int flag, struct proc *p)
1.1       augustss  578: {
                    579:        struct usb_ctl_report_desc *rd;
1.2       augustss  580:        struct usb_ctl_report *re;
                    581:        int size, id;
1.27      augustss  582:        usbd_status err;
1.1       augustss  583:
1.18      augustss  584:        DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
                    585:
                    586:        if (sc->sc_dying)
1.1       augustss  587:                return (EIO);
                    588:
                    589:        switch (cmd) {
1.2       augustss  590:        case FIONBIO:
                    591:                /* All handled in the upper FS layer. */
1.37      augustss  592:                break;
                    593:
                    594:        case FIOASYNC:
                    595:                if (*(int *)addr) {
                    596:                        if (sc->sc_async != NULL)
                    597:                                return (EBUSY);
                    598:                        sc->sc_async = p;
                    599:                        DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", p));
                    600:                } else
                    601:                        sc->sc_async = NULL;
                    602:                break;
                    603:
                    604:        /* XXX this is not the most general solution. */
                    605:        case TIOCSPGRP:
                    606:                if (sc->sc_async == NULL)
                    607:                        return (EINVAL);
                    608:                if (*(int *)addr != sc->sc_async->p_pgid)
                    609:                        return (EPERM);
1.2       augustss  610:                break;
                    611:
1.1       augustss  612:        case USB_GET_REPORT_DESC:
                    613:                rd = (struct usb_ctl_report_desc *)addr;
                    614:                size = min(sc->sc_repdesc_size, sizeof rd->data);
                    615:                rd->size = size;
                    616:                memcpy(rd->data, sc->sc_repdesc, size);
                    617:                break;
1.2       augustss  618:
                    619:        case USB_SET_IMMED:
1.9       augustss  620:                if (*(int *)addr) {
1.27      augustss  621:                        /* XXX should read into ibuf, but does it matter? */
                    622:                        err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
                    623:                                  sc->sc_iid, sc->sc_ibuf, sc->sc_isize);
                    624:                        if (err)
1.9       augustss  625:                                return (EOPNOTSUPP);
1.12      augustss  626:
1.2       augustss  627:                        sc->sc_state |=  UHID_IMMED;
1.9       augustss  628:                } else
1.2       augustss  629:                        sc->sc_state &= ~UHID_IMMED;
                    630:                break;
                    631:
                    632:        case USB_GET_REPORT:
                    633:                re = (struct usb_ctl_report *)addr;
                    634:                switch (re->report) {
                    635:                case UHID_INPUT_REPORT:
                    636:                        size = sc->sc_isize;
                    637:                        id = sc->sc_iid;
                    638:                        break;
                    639:                case UHID_OUTPUT_REPORT:
                    640:                        size = sc->sc_osize;
                    641:                        id = sc->sc_oid;
                    642:                        break;
                    643:                case UHID_FEATURE_REPORT:
                    644:                        size = sc->sc_fsize;
                    645:                        id = sc->sc_fid;
                    646:                        break;
                    647:                default:
                    648:                        return (EINVAL);
                    649:                }
1.27      augustss  650:                err = usbd_get_report(sc->sc_iface, re->report, id, re->data,
1.35      augustss  651:                          size);
                    652:                if (err)
                    653:                        return (EIO);
                    654:                break;
                    655:
                    656:        case USB_SET_REPORT:
                    657:                re = (struct usb_ctl_report *)addr;
                    658:                switch (re->report) {
                    659:                case UHID_INPUT_REPORT:
                    660:                        size = sc->sc_isize;
                    661:                        id = sc->sc_iid;
                    662:                        break;
                    663:                case UHID_OUTPUT_REPORT:
                    664:                        size = sc->sc_osize;
                    665:                        id = sc->sc_oid;
                    666:                        break;
                    667:                case UHID_FEATURE_REPORT:
                    668:                        size = sc->sc_fsize;
                    669:                        id = sc->sc_fid;
                    670:                        break;
                    671:                default:
                    672:                        return (EINVAL);
                    673:                }
                    674:                err = usbd_set_report(sc->sc_iface, re->report, id, re->data,
1.27      augustss  675:                          size);
                    676:                if (err)
1.2       augustss  677:                        return (EIO);
                    678:                break;
                    679:
1.1       augustss  680:        default:
                    681:                return (EINVAL);
                    682:        }
                    683:        return (0);
                    684: }
                    685:
                    686: int
1.39      augustss  687: uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1.18      augustss  688: {
1.25      augustss  689:        struct uhid_softc *sc;
                    690:        int error;
                    691:
1.18      augustss  692:        USB_GET_SC(uhid, UHIDUNIT(dev), sc);
                    693:
                    694:        sc->sc_refcnt++;
                    695:        error = uhid_do_ioctl(sc, cmd, addr, flag, p);
                    696:        if (--sc->sc_refcnt < 0)
1.24      augustss  697:                usb_detach_wakeup(USBDEV(sc->sc_dev));
1.18      augustss  698:        return (error);
                    699: }
                    700:
                    701: int
1.39      augustss  702: uhidpoll(dev_t dev, int events, struct proc *p)
1.1       augustss  703: {
1.25      augustss  704:        struct uhid_softc *sc;
1.1       augustss  705:        int revents = 0;
                    706:        int s;
1.25      augustss  707:
1.12      augustss  708:        USB_GET_SC(uhid, UHIDUNIT(dev), sc);
1.1       augustss  709:
1.18      augustss  710:        if (sc->sc_dying)
1.1       augustss  711:                return (EIO);
                    712:
1.10      augustss  713:        s = splusb();
1.1       augustss  714:        if (events & (POLLOUT | POLLWRNORM))
                    715:                revents |= events & (POLLOUT | POLLWRNORM);
1.4       veego     716:        if (events & (POLLIN | POLLRDNORM)) {
1.1       augustss  717:                if (sc->sc_q.c_cc > 0)
                    718:                        revents |= events & (POLLIN | POLLRDNORM);
                    719:                else
                    720:                        selrecord(p, &sc->sc_rsel);
1.4       veego     721:        }
1.1       augustss  722:
                    723:        splx(s);
                    724:        return (revents);
                    725: }
1.12      augustss  726:
                    727: #if defined(__FreeBSD__)
1.28      augustss  728: DRIVER_MODULE(uhid, uhub, uhid_driver, uhid_devclass, usbd_driver_load, 0);
1.12      augustss  729: #endif

CVSweb <webmaster@jp.NetBSD.org>