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

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

1.1       nbrk        1: /*     $OpenBSD: uhid.c,v 1.41 2007/06/14 10:11:15 mbalmer Exp $ */
                      2: /*     $NetBSD: uhid.c,v 1.57 2003/03/11 16:44:00 augustss Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 1998 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:  * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
                     43:  */
                     44:
                     45: #include <sys/param.h>
                     46: #include <sys/systm.h>
                     47: #include <sys/kernel.h>
                     48: #include <sys/malloc.h>
                     49: #include <sys/signalvar.h>
                     50: #include <sys/device.h>
                     51: #include <sys/ioctl.h>
                     52: #include <sys/conf.h>
                     53: #include <sys/tty.h>
                     54: #include <sys/file.h>
                     55: #include <sys/selinfo.h>
                     56: #include <sys/proc.h>
                     57: #include <sys/vnode.h>
                     58: #include <sys/poll.h>
                     59:
                     60: #include <dev/usb/usb.h>
                     61: #include <dev/usb/usbhid.h>
                     62:
                     63: #include <dev/usb/usbdevs.h>
                     64: #include <dev/usb/usbdi.h>
                     65: #include <dev/usb/usbdi_util.h>
                     66: #include <dev/usb/hid.h>
                     67: #include <dev/usb/usb_quirks.h>
                     68:
                     69: #include <dev/usb/uhidev.h>
                     70:
                     71: #ifdef UHID_DEBUG
                     72: #define DPRINTF(x)     do { if (uhiddebug) printf x; } while (0)
                     73: #define DPRINTFN(n,x)  do { if (uhiddebug>(n)) printf x; } while (0)
                     74: int    uhiddebug = 0;
                     75: #else
                     76: #define DPRINTF(x)
                     77: #define DPRINTFN(n,x)
                     78: #endif
                     79:
                     80: struct uhid_softc {
                     81:        struct uhidev sc_hdev;
                     82:
                     83:        int sc_isize;
                     84:        int sc_osize;
                     85:        int sc_fsize;
                     86:
                     87:        u_char *sc_obuf;
                     88:
                     89:        struct clist sc_q;
                     90:        struct selinfo sc_rsel;
                     91:        struct proc *sc_async;  /* process that wants SIGIO */
                     92:        u_char sc_state;        /* driver state */
                     93: #define        UHID_ASLP       0x01    /* waiting for device data */
                     94: #define UHID_IMMED     0x02    /* return read data immediately */
                     95:
                     96:        int sc_refcnt;
                     97:        u_char sc_dying;
                     98: };
                     99:
                    100: #define        UHIDUNIT(dev)   (minor(dev))
                    101: #define        UHID_CHUNK      128     /* chunk size for read */
                    102: #define        UHID_BSIZE      1020    /* buffer size */
                    103:
                    104: void uhid_intr(struct uhidev *, void *, u_int len);
                    105:
                    106: int uhid_do_read(struct uhid_softc *, struct uio *uio, int);
                    107: int uhid_do_write(struct uhid_softc *, struct uio *uio, int);
                    108: int uhid_do_ioctl(struct uhid_softc*, u_long, caddr_t, int,
                    109:                         struct proc *);
                    110:
                    111: int uhid_match(struct device *, void *, void *);
                    112: void uhid_attach(struct device *, struct device *, void *);
                    113: int uhid_detach(struct device *, int);
                    114: int uhid_activate(struct device *, enum devact);
                    115:
                    116: struct cfdriver uhid_cd = {
                    117:        NULL, "uhid", DV_DULL
                    118: };
                    119:
                    120: const struct cfattach uhid_ca = {
                    121:        sizeof(struct uhid_softc),
                    122:        uhid_match,
                    123:        uhid_attach,
                    124:        uhid_detach,
                    125:        uhid_activate,
                    126: };
                    127:
                    128: int
                    129: uhid_match(struct device *parent, void *match, void *aux)
                    130: {
                    131:        struct usb_attach_arg *uaa = aux;
                    132:        struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
                    133:
                    134:        DPRINTF(("uhid_match: report=%d\n", uha->reportid));
                    135:
                    136:        if (uha->matchlvl)
                    137:                return (uha->matchlvl);
                    138:        return (UMATCH_IFACECLASS_GENERIC);
                    139: }
                    140:
                    141: void
                    142: uhid_attach(struct device *parent, struct device *self, void *aux)
                    143: {
                    144:        struct uhid_softc *sc = (struct uhid_softc *)self;
                    145:        struct usb_attach_arg *uaa = aux;
                    146:        struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
                    147:        int size, repid;
                    148:        void *desc;
                    149:
                    150:        sc->sc_hdev.sc_intr = uhid_intr;
                    151:        sc->sc_hdev.sc_parent = uha->parent;
                    152:        sc->sc_hdev.sc_report_id = uha->reportid;
                    153:
                    154:        uhidev_get_report_desc(uha->parent, &desc, &size);
                    155:        repid = uha->reportid;
                    156:        sc->sc_isize = hid_report_size(desc, size, hid_input,   repid);
                    157:        sc->sc_osize = hid_report_size(desc, size, hid_output,  repid);
                    158:        sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid);
                    159:
                    160:        printf(": input=%d, output=%d, feature=%d\n",
                    161:               sc->sc_isize, sc->sc_osize, sc->sc_fsize);
                    162: }
                    163:
                    164: int
                    165: uhid_activate(struct device *self, enum devact act)
                    166: {
                    167:        struct uhid_softc *sc = (struct uhid_softc *)self;
                    168:
                    169:        switch (act) {
                    170:        case DVACT_ACTIVATE:
                    171:                break;
                    172:
                    173:        case DVACT_DEACTIVATE:
                    174:                sc->sc_dying = 1;
                    175:                break;
                    176:        }
                    177:        return (0);
                    178: }
                    179:
                    180: int
                    181: uhid_detach(struct device *self, int flags)
                    182: {
                    183:        struct uhid_softc *sc = (struct uhid_softc *)self;
                    184:        int s;
                    185:        int maj, mn;
                    186:
                    187:        DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags));
                    188:
                    189:        sc->sc_dying = 1;
                    190:
                    191:        if (sc->sc_hdev.sc_state & UHIDEV_OPEN) {
                    192:                s = splusb();
                    193:                if (--sc->sc_refcnt >= 0) {
                    194:                        /* Wake everyone */
                    195:                        wakeup(&sc->sc_q);
                    196:                        /* Wait for processes to go away. */
                    197:                        usb_detach_wait(&sc->sc_hdev.sc_dev);
                    198:                }
                    199:                splx(s);
                    200:        }
                    201:
                    202:        /* locate the major number */
                    203:        for (maj = 0; maj < nchrdev; maj++)
                    204:                if (cdevsw[maj].d_open == uhidopen)
                    205:                        break;
                    206:
                    207:        /* Nuke the vnodes for any open instances (calls close). */
                    208:        mn = self->dv_unit;
                    209:        vdevgone(maj, mn, mn, VCHR);
                    210:
                    211: #if 0
                    212:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH,
                    213:                           sc->sc_hdev.sc_parent->sc_udev,
                    214:                           &sc->sc_hdev.sc_dev);
                    215: #endif
                    216:
                    217:        return (0);
                    218: }
                    219:
                    220: void
                    221: uhid_intr(struct uhidev *addr, void *data, u_int len)
                    222: {
                    223:        struct uhid_softc *sc = (struct uhid_softc *)addr;
                    224:
                    225: #ifdef UHID_DEBUG
                    226:        if (uhiddebug > 5) {
                    227:                u_int32_t i;
                    228:
                    229:                DPRINTF(("uhid_intr: data ="));
                    230:                for (i = 0; i < len; i++)
                    231:                        DPRINTF((" %02x", ((u_char *)data)[i]));
                    232:                DPRINTF(("\n"));
                    233:        }
                    234: #endif
                    235:
                    236:        (void)b_to_q(data, len, &sc->sc_q);
                    237:
                    238:        if (sc->sc_state & UHID_ASLP) {
                    239:                sc->sc_state &= ~UHID_ASLP;
                    240:                DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q));
                    241:                wakeup(&sc->sc_q);
                    242:        }
                    243:        selwakeup(&sc->sc_rsel);
                    244:        if (sc->sc_async != NULL) {
                    245:                DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async));
                    246:                psignal(sc->sc_async, SIGIO);
                    247:        }
                    248: }
                    249:
                    250: int
                    251: uhidopen(dev_t dev, int flag, int mode, struct proc *p)
                    252: {
                    253:        struct uhid_softc *sc;
                    254:        int error;
                    255:
                    256:        if (UHIDUNIT(dev) >= uhid_cd.cd_ndevs)
                    257:                return (ENXIO);
                    258:        sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
                    259:        if (sc == NULL)
                    260:                return (ENXIO);
                    261:
                    262:        DPRINTF(("uhidopen: sc=%p\n", sc));
                    263:
                    264:        if (sc->sc_dying)
                    265:                return (ENXIO);
                    266:
                    267:        error = uhidev_open(&sc->sc_hdev);
                    268:        if (error)
                    269:                return (error);
                    270:
                    271:        if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) {
                    272:                uhidev_close(&sc->sc_hdev);
                    273:                return (ENOMEM);
                    274:        }
                    275:        sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
                    276:        sc->sc_state &= ~UHID_IMMED;
                    277:        sc->sc_async = NULL;
                    278:
                    279:        return (0);
                    280: }
                    281:
                    282: int
                    283: uhidclose(dev_t dev, int flag, int mode, struct proc *p)
                    284: {
                    285:        struct uhid_softc *sc;
                    286:
                    287:        sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
                    288:
                    289:        DPRINTF(("uhidclose: sc=%p\n", sc));
                    290:
                    291:        clfree(&sc->sc_q);
                    292:        free(sc->sc_obuf, M_USBDEV);
                    293:        sc->sc_async = NULL;
                    294:        uhidev_close(&sc->sc_hdev);
                    295:
                    296:        return (0);
                    297: }
                    298:
                    299: int
                    300: uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag)
                    301: {
                    302:        int s;
                    303:        int error = 0;
                    304:        int extra;
                    305:        size_t length;
                    306:        u_char buffer[UHID_CHUNK];
                    307:        usbd_status err;
                    308:
                    309:        DPRINTFN(1, ("uhidread\n"));
                    310:        if (sc->sc_state & UHID_IMMED) {
                    311:                DPRINTFN(1, ("uhidread immed\n"));
                    312:                extra = sc->sc_hdev.sc_report_id != 0;
                    313:                err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
                    314:                                        buffer, sc->sc_isize + extra);
                    315:                if (err)
                    316:                        return (EIO);
                    317:                return (uiomove(buffer+extra, sc->sc_isize, uio));
                    318:        }
                    319:
                    320:        s = splusb();
                    321:        while (sc->sc_q.c_cc == 0) {
                    322:                if (flag & IO_NDELAY) {
                    323:                        splx(s);
                    324:                        return (EWOULDBLOCK);
                    325:                }
                    326:                sc->sc_state |= UHID_ASLP;
                    327:                DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q));
                    328:                error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0);
                    329:                DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
                    330:                if (sc->sc_dying)
                    331:                        error = EIO;
                    332:                if (error) {
                    333:                        sc->sc_state &= ~UHID_ASLP;
                    334:                        break;
                    335:                }
                    336:        }
                    337:        splx(s);
                    338:
                    339:        /* Transfer as many chunks as possible. */
                    340:        while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) {
                    341:                length = min(sc->sc_q.c_cc, uio->uio_resid);
                    342:                if (length > sizeof(buffer))
                    343:                        length = sizeof(buffer);
                    344:
                    345:                /* Remove a small chunk from the input queue. */
                    346:                (void) q_to_b(&sc->sc_q, buffer, length);
                    347:                DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length));
                    348:
                    349:                /* Copy the data to the user process. */
                    350:                if ((error = uiomove(buffer, length, uio)) != 0)
                    351:                        break;
                    352:        }
                    353:
                    354:        return (error);
                    355: }
                    356:
                    357: int
                    358: uhidread(dev_t dev, struct uio *uio, int flag)
                    359: {
                    360:        struct uhid_softc *sc;
                    361:        int error;
                    362:
                    363:        sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
                    364:
                    365:        sc->sc_refcnt++;
                    366:        error = uhid_do_read(sc, uio, flag);
                    367:        if (--sc->sc_refcnt < 0)
                    368:                usb_detach_wakeup(&sc->sc_hdev.sc_dev);
                    369:        return (error);
                    370: }
                    371:
                    372: int
                    373: uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag)
                    374: {
                    375:        int error;
                    376:        int size;
                    377:        usbd_status err;
                    378:
                    379:        DPRINTFN(1, ("uhidwrite\n"));
                    380:
                    381:        if (sc->sc_dying)
                    382:                return (EIO);
                    383:
                    384:        size = sc->sc_osize;
                    385:        error = 0;
                    386:        if (uio->uio_resid != size)
                    387:                return (EINVAL);
                    388:        error = uiomove(sc->sc_obuf, size, uio);
                    389:        if (!error) {
                    390:                err = uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT,
                    391:                                        sc->sc_obuf, size);
                    392:                if (err)
                    393:                        error = EIO;
                    394:        }
                    395:
                    396:        return (error);
                    397: }
                    398:
                    399: int
                    400: uhidwrite(dev_t dev, struct uio *uio, int flag)
                    401: {
                    402:        struct uhid_softc *sc;
                    403:        int error;
                    404:
                    405:        sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
                    406:
                    407:        sc->sc_refcnt++;
                    408:        error = uhid_do_write(sc, uio, flag);
                    409:        if (--sc->sc_refcnt < 0)
                    410:                usb_detach_wakeup(&sc->sc_hdev.sc_dev);
                    411:        return (error);
                    412: }
                    413:
                    414: int
                    415: uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr,
                    416:              int flag, struct proc *p)
                    417: {
                    418:        struct usb_ctl_report_desc *rd;
                    419:        struct usb_ctl_report *re;
                    420:        u_char buffer[UHID_CHUNK];
                    421:        int size, extra;
                    422:        usbd_status err;
                    423:        void *desc;
                    424:
                    425:        DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
                    426:
                    427:        if (sc->sc_dying)
                    428:                return (EIO);
                    429:
                    430:        switch (cmd) {
                    431:        case FIONBIO:
                    432:                /* All handled in the upper FS layer. */
                    433:                break;
                    434:
                    435:        case FIOASYNC:
                    436:                if (*(int *)addr) {
                    437:                        if (sc->sc_async != NULL)
                    438:                                return (EBUSY);
                    439:                        sc->sc_async = p;
                    440:                        DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", p));
                    441:                } else
                    442:                        sc->sc_async = NULL;
                    443:                break;
                    444:
                    445:        /* XXX this is not the most general solution. */
                    446:        case TIOCSPGRP:
                    447:                if (sc->sc_async == NULL)
                    448:                        return (EINVAL);
                    449:                if (*(int *)addr != sc->sc_async->p_pgid)
                    450:                        return (EPERM);
                    451:                break;
                    452:
                    453:        case USB_GET_REPORT_DESC:
                    454:                uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
                    455:                rd = (struct usb_ctl_report_desc *)addr;
                    456:                size = min(size, sizeof rd->ucrd_data);
                    457:                rd->ucrd_size = size;
                    458:                memcpy(rd->ucrd_data, desc, size);
                    459:                break;
                    460:
                    461:        case USB_SET_IMMED:
                    462:                if (*(int *)addr) {
                    463:                        extra = sc->sc_hdev.sc_report_id != 0;
                    464:                        err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
                    465:                                                buffer, sc->sc_isize + extra);
                    466:                        if (err)
                    467:                                return (EOPNOTSUPP);
                    468:
                    469:                        sc->sc_state |=  UHID_IMMED;
                    470:                } else
                    471:                        sc->sc_state &= ~UHID_IMMED;
                    472:                break;
                    473:
                    474:        case USB_GET_REPORT:
                    475:                re = (struct usb_ctl_report *)addr;
                    476:                switch (re->ucr_report) {
                    477:                case UHID_INPUT_REPORT:
                    478:                        size = sc->sc_isize;
                    479:                        break;
                    480:                case UHID_OUTPUT_REPORT:
                    481:                        size = sc->sc_osize;
                    482:                        break;
                    483:                case UHID_FEATURE_REPORT:
                    484:                        size = sc->sc_fsize;
                    485:                        break;
                    486:                default:
                    487:                        return (EINVAL);
                    488:                }
                    489:                extra = sc->sc_hdev.sc_report_id != 0;
                    490:                err = uhidev_get_report(&sc->sc_hdev, re->ucr_report,
                    491:                    re->ucr_data, size + extra);
                    492:                if (extra)
                    493:                        memcpy(re->ucr_data, re->ucr_data+1, size);
                    494:                if (err)
                    495:                        return (EIO);
                    496:                break;
                    497:
                    498:        case USB_SET_REPORT:
                    499:                re = (struct usb_ctl_report *)addr;
                    500:                switch (re->ucr_report) {
                    501:                case UHID_INPUT_REPORT:
                    502:                        size = sc->sc_isize;
                    503:                        break;
                    504:                case UHID_OUTPUT_REPORT:
                    505:                        size = sc->sc_osize;
                    506:                        break;
                    507:                case UHID_FEATURE_REPORT:
                    508:                        size = sc->sc_fsize;
                    509:                        break;
                    510:                default:
                    511:                        return (EINVAL);
                    512:                }
                    513:                err = uhidev_set_report(&sc->sc_hdev, re->ucr_report,
                    514:                    re->ucr_data, size);
                    515:                if (err)
                    516:                        return (EIO);
                    517:                break;
                    518:
                    519:        case USB_GET_REPORT_ID:
                    520:                *(int *)addr = sc->sc_hdev.sc_report_id;
                    521:                break;
                    522:
                    523:        default:
                    524:                return (EINVAL);
                    525:        }
                    526:        return (0);
                    527: }
                    528:
                    529: int
                    530: uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
                    531: {
                    532:        struct uhid_softc *sc;
                    533:        int error;
                    534:
                    535:        sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
                    536:
                    537:        sc->sc_refcnt++;
                    538:        error = uhid_do_ioctl(sc, cmd, addr, flag, p);
                    539:        if (--sc->sc_refcnt < 0)
                    540:                usb_detach_wakeup(&sc->sc_hdev.sc_dev);
                    541:        return (error);
                    542: }
                    543:
                    544: int
                    545: uhidpoll(dev_t dev, int events, struct proc *p)
                    546: {
                    547:        struct uhid_softc *sc;
                    548:        int revents = 0;
                    549:        int s;
                    550:
                    551:        sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
                    552:
                    553:        if (sc->sc_dying)
                    554:                return (POLLERR);
                    555:
                    556:        s = splusb();
                    557:        if (events & (POLLOUT | POLLWRNORM))
                    558:                revents |= events & (POLLOUT | POLLWRNORM);
                    559:        if (events & (POLLIN | POLLRDNORM)) {
                    560:                if (sc->sc_q.c_cc > 0)
                    561:                        revents |= events & (POLLIN | POLLRDNORM);
                    562:                else
                    563:                        selrecord(p, &sc->sc_rsel);
                    564:        }
                    565:
                    566:        splx(s);
                    567:        return (revents);
                    568: }
                    569:
                    570: void filt_uhidrdetach(struct knote *);
                    571: int filt_uhidread(struct knote *, long);
                    572: int uhidkqfilter(dev_t, struct knote *);
                    573:
                    574: void
                    575: filt_uhidrdetach(struct knote *kn)
                    576: {
                    577:        struct uhid_softc *sc = (void *)kn->kn_hook;
                    578:        int s;
                    579:
                    580:        s = splusb();
                    581:        SLIST_REMOVE(&sc->sc_rsel.si_note, kn, knote, kn_selnext);
                    582:        splx(s);
                    583: }
                    584:
                    585: int
                    586: filt_uhidread(struct knote *kn, long hint)
                    587: {
                    588:        struct uhid_softc *sc = (void *)kn->kn_hook;
                    589:
                    590:        kn->kn_data = sc->sc_q.c_cc;
                    591:        return (kn->kn_data > 0);
                    592: }
                    593:
                    594: struct filterops uhidread_filtops =
                    595:        { 1, NULL, filt_uhidrdetach, filt_uhidread };
                    596:
                    597: struct filterops uhid_seltrue_filtops =
                    598:        { 1, NULL, filt_uhidrdetach, filt_seltrue };
                    599:
                    600: int
                    601: uhidkqfilter(dev_t dev, struct knote *kn)
                    602: {
                    603:        struct uhid_softc *sc;
                    604:        struct klist *klist;
                    605:        int s;
                    606:
                    607:        sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
                    608:
                    609:        if (sc->sc_dying)
                    610:                return (EIO);
                    611:
                    612:        switch (kn->kn_filter) {
                    613:        case EVFILT_READ:
                    614:                klist = &sc->sc_rsel.si_note;
                    615:                kn->kn_fop = &uhidread_filtops;
                    616:                break;
                    617:
                    618:        case EVFILT_WRITE:
                    619:                klist = &sc->sc_rsel.si_note;
                    620:                kn->kn_fop = &uhid_seltrue_filtops;
                    621:                break;
                    622:
                    623:        default:
                    624:                return (1);
                    625:        }
                    626:
                    627:        kn->kn_hook = (void *)sc;
                    628:
                    629:        s = splusb();
                    630:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
                    631:        splx(s);
                    632:
                    633:        return (0);
                    634: }

CVSweb