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

Annotation of src/sys/dev/wscons/wsevent.c, Revision 1.17.2.1

1.17.2.1! yamt        1: /* $NetBSD: wsevent.c,v 1.17 2005/12/11 12:24:12 christos Exp $ */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 2006 The NetBSD Foundation, Inc.
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * This code is derived from software contributed to The NetBSD Foundation
        !             8:  * by Julio M. Merino Vidal.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by the NetBSD
        !            21:  *     Foundation, Inc. and its contributors.
        !            22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            23:  *    contributors may be used to endorse or promote products derived
        !            24:  *    from this software without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            36:  * POSSIBILITY OF SUCH DAMAGE.
        !            37:  */
1.1       drochner   38:
                     39: /*
                     40:  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
                     41:  *
                     42:  * Redistribution and use in source and binary forms, with or without
                     43:  * modification, are permitted provided that the following conditions
                     44:  * are met:
                     45:  * 1. Redistributions of source code must retain the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer.
                     47:  * 2. Redistributions in binary form must reproduce the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer in the
                     49:  *    documentation and/or other materials provided with the distribution.
                     50:  * 3. All advertising materials mentioning features or use of this software
                     51:  *    must display the following acknowledgement:
                     52:  *      This product includes software developed by Christopher G. Demetriou
                     53:  *     for the NetBSD Project.
                     54:  * 4. The name of the author may not be used to endorse or promote products
                     55:  *    derived from this software without specific prior written permission
                     56:  *
                     57:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     58:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     59:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     60:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     61:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     62:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     63:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     64:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     65:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     66:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     67:  */
                     68:
                     69: /*
                     70:  * Copyright (c) 1992, 1993
                     71:  *     The Regents of the University of California.  All rights reserved.
                     72:  *
                     73:  * This software was developed by the Computer Systems Engineering group
                     74:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
                     75:  * contributed to Berkeley.
                     76:  *
                     77:  * All advertising materials mentioning features or use of this software
                     78:  * must display the following acknowledgement:
                     79:  *     This product includes software developed by the University of
                     80:  *     California, Lawrence Berkeley Laboratory.
                     81:  *
                     82:  * Redistribution and use in source and binary forms, with or without
                     83:  * modification, are permitted provided that the following conditions
                     84:  * are met:
                     85:  * 1. Redistributions of source code must retain the above copyright
                     86:  *    notice, this list of conditions and the following disclaimer.
                     87:  * 2. Redistributions in binary form must reproduce the above copyright
                     88:  *    notice, this list of conditions and the following disclaimer in the
                     89:  *    documentation and/or other materials provided with the distribution.
1.16      agc        90:  * 3. Neither the name of the University nor the names of its contributors
1.1       drochner   91:  *    may be used to endorse or promote products derived from this software
                     92:  *    without specific prior written permission.
                     93:  *
                     94:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     95:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     96:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     97:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     98:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     99:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                    100:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                    101:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                    102:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                    103:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                    104:  * SUCH DAMAGE.
                    105:  *
                    106:  *     @(#)event.c     8.1 (Berkeley) 6/11/93
                    107:  */
                    108:
                    109: /*
                    110:  * Internal "wscons_event" queue interface for the keyboard and mouse drivers.
                    111:  */
1.9       lukem     112:
                    113: #include <sys/cdefs.h>
1.17.2.1! yamt      114: __KERNEL_RCSID(0, "$NetBSD: wsevent.c,v 1.17 2005/12/11 12:24:12 christos Exp $");
1.1       drochner  115:
                    116: #include <sys/param.h>
1.17.2.1! yamt      117: #include <sys/kernel.h>
1.1       drochner  118: #include <sys/fcntl.h>
                    119: #include <sys/malloc.h>
                    120: #include <sys/proc.h>
                    121: #include <sys/systm.h>
                    122: #include <sys/vnode.h>
                    123: #include <sys/select.h>
                    124: #include <sys/poll.h>
                    125:
                    126: #include <dev/wscons/wsconsio.h>
                    127: #include <dev/wscons/wseventvar.h>
                    128:
                    129: /*
1.17.2.1! yamt      130:  * Size of a wsevent queue (measured in number of events).
        !           131:  * Should be a power of two so that `%' is fast.
        !           132:  * At the moment, the value below makes the queues use 2 Kbytes each; this
        !           133:  * value may need tuning.
        !           134:  */
        !           135: #define        WSEVENT_QSIZE   256
        !           136:
        !           137: /*
        !           138:  * Priority of code managing wsevent queues.  PWSEVENT is set just above
        !           139:  * PSOCK, which is just above TTIPRI, on the theory that mouse and keyboard
        !           140:  * `user' input should be quick.
        !           141:  */
        !           142: #define        PWSEVENT        23
        !           143: #define        splwsevent()    spltty()
        !           144:
        !           145: /*
1.1       drochner  146:  * Initialize a wscons_event queue.
                    147:  */
                    148: void
1.17.2.1! yamt      149: wsevent_init(struct wseventvar *ev, struct proc *p)
1.1       drochner  150: {
                    151:
1.13      christos  152:        if (ev->q != NULL) {
1.7       augustss  153: #ifdef DIAGNOSTIC
                    154:                printf("wsevent_init: already init\n");
1.13      christos  155: #endif
1.7       augustss  156:                return;
                    157:        }
1.1       drochner  158:        ev->get = ev->put = 0;
                    159:        ev->q = malloc((u_long)WSEVENT_QSIZE * sizeof(struct wscons_event),
1.10      tsutsui   160:                       M_DEVBUF, M_WAITOK|M_ZERO);
1.17.2.1! yamt      161:        ev->io = p;
1.1       drochner  162: }
                    163:
                    164: /*
                    165:  * Tear down a wscons_event queue.
                    166:  */
                    167: void
1.6       augustss  168: wsevent_fini(struct wseventvar *ev)
1.1       drochner  169: {
1.13      christos  170:        if (ev->q == NULL) {
                    171: #ifdef DIAGNOSTIC
                    172:                printf("wsevent_fini: already fini\n");
                    173: #endif
                    174:                return;
                    175:        }
1.1       drochner  176:        free(ev->q, M_DEVBUF);
1.7       augustss  177:        ev->q = NULL;
1.1       drochner  178: }
                    179:
                    180: /*
                    181:  * User-level interface: read, poll.
                    182:  * (User cannot write an event queue.)
                    183:  */
                    184: int
1.6       augustss  185: wsevent_read(struct wseventvar *ev, struct uio *uio, int flags)
1.1       drochner  186: {
                    187:        int s, n, cnt, error;
                    188:
                    189:        /*
                    190:         * Make sure we can return at least 1.
                    191:         */
                    192:        if (uio->uio_resid < sizeof(struct wscons_event))
                    193:                return (EMSGSIZE);      /* ??? */
                    194:        s = splwsevent();
                    195:        while (ev->get == ev->put) {
                    196:                if (flags & IO_NDELAY) {
                    197:                        splx(s);
                    198:                        return (EWOULDBLOCK);
                    199:                }
                    200:                ev->wanted = 1;
1.7       augustss  201:                error = tsleep(ev, PWSEVENT | PCATCH,
1.1       drochner  202:                    "wsevent_read", 0);
                    203:                if (error) {
                    204:                        splx(s);
                    205:                        return (error);
                    206:                }
                    207:        }
                    208:        /*
                    209:         * Move wscons_event from tail end of queue (there is at least one
                    210:         * there).
                    211:         */
                    212:        if (ev->put < ev->get)
                    213:                cnt = WSEVENT_QSIZE - ev->get;  /* events in [get..QSIZE) */
                    214:        else
                    215:                cnt = ev->put - ev->get;        /* events in [get..put) */
                    216:        splx(s);
                    217:        n = howmany(uio->uio_resid, sizeof(struct wscons_event));
                    218:        if (cnt > n)
                    219:                cnt = n;
1.7       augustss  220:        error = uiomove(&ev->q[ev->get],
1.1       drochner  221:            cnt * sizeof(struct wscons_event), uio);
                    222:        n -= cnt;
                    223:        /*
                    224:         * If we do not wrap to 0, used up all our space, or had an error,
                    225:         * stop.  Otherwise move from front of queue to put index, if there
                    226:         * is anything there to move.
                    227:         */
                    228:        if ((ev->get = (ev->get + cnt) % WSEVENT_QSIZE) != 0 ||
                    229:            n == 0 || error || (cnt = ev->put) == 0)
                    230:                return (error);
                    231:        if (cnt > n)
                    232:                cnt = n;
1.7       augustss  233:        error = uiomove(&ev->q[0],
1.1       drochner  234:            cnt * sizeof(struct wscons_event), uio);
                    235:        ev->get = cnt;
                    236:        return (error);
                    237: }
                    238:
                    239: int
1.17      christos  240: wsevent_poll(struct wseventvar *ev, int events, struct lwp *l)
1.1       drochner  241: {
                    242:        int revents = 0;
                    243:        int s = splwsevent();
                    244:
1.2       thorpej   245:         if (events & (POLLIN | POLLRDNORM)) {
1.1       drochner  246:                if (ev->get != ev->put)
1.2       thorpej   247:                        revents |= events & (POLLIN | POLLRDNORM);
                    248:                else
1.17      christos  249:                        selrecord(l, &ev->sel);
1.2       thorpej   250:        }
1.1       drochner  251:
                    252:        splx(s);
                    253:        return (revents);
1.11      jdolecek  254: }
                    255:
                    256: static void
                    257: filt_wseventrdetach(struct knote *kn)
                    258: {
                    259:        struct wseventvar *ev = kn->kn_hook;
                    260:        int s;
                    261:
                    262:        s = splwsevent();
1.12      christos  263:        SLIST_REMOVE(&ev->sel.sel_klist, kn, knote, kn_selnext);
1.11      jdolecek  264:        splx(s);
                    265: }
                    266:
                    267: static int
                    268: filt_wseventread(struct knote *kn, long hint)
                    269: {
                    270:        struct wseventvar *ev = kn->kn_hook;
                    271:
                    272:        if (ev->get == ev->put)
                    273:                return (0);
                    274:
                    275:        if (ev->get < ev->put)
                    276:                kn->kn_data = ev->put - ev->get;
                    277:        else
                    278:                kn->kn_data = (WSEVENT_QSIZE - ev->get) +
                    279:                    ev->put;
                    280:
                    281:        kn->kn_data *= sizeof(struct wscons_event);
                    282:
                    283:        return (1);
                    284: }
                    285:
                    286: static const struct filterops wsevent_filtops =
                    287:        { 1, NULL, filt_wseventrdetach, filt_wseventread };
                    288:
                    289: int
                    290: wsevent_kqfilter(struct wseventvar *ev, struct knote *kn)
                    291: {
                    292:        struct klist *klist;
                    293:        int s;
                    294:
                    295:        switch (kn->kn_filter) {
                    296:        case EVFILT_READ:
1.12      christos  297:                klist = &ev->sel.sel_klist;
1.11      jdolecek  298:                kn->kn_fop = &wsevent_filtops;
                    299:                break;
                    300:
                    301:        default:
                    302:                return (1);
                    303:        }
                    304:
                    305:        kn->kn_hook = ev;
                    306:
                    307:        s = splwsevent();
                    308:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
                    309:        splx(s);
                    310:
                    311:        return (0);
1.1       drochner  312: }
1.17.2.1! yamt      313:
        !           314: /*
        !           315:  * Wakes up all listener of the 'ev' queue.
        !           316:  */
        !           317: void
        !           318: wsevent_wakeup(struct wseventvar *ev)
        !           319: {
        !           320:
        !           321:        selnotify(&ev->sel, 0);
        !           322:
        !           323:        if (ev->wanted) {
        !           324:                ev->wanted = 0;
        !           325:                wakeup(ev);
        !           326:        }
        !           327:
        !           328:        if (ev->async)
        !           329:                psignal(ev->io, SIGIO);
        !           330: }
        !           331:
        !           332: /*
        !           333:  * Injects the set of events given in 'events', whose size is 'nevenets',
        !           334:  * into the 'ev' queue.  If there is not enough free space to inject them
        !           335:  * all, returns ENOSPC and the queue is left intact; otherwise returns 0
        !           336:  * and wakes up all listeners.
        !           337:  */
        !           338: int
        !           339: wsevent_inject(struct wseventvar *ev, struct wscons_event *events,
        !           340:     size_t nevents)
        !           341: {
        !           342:        int oldspl;
        !           343:        size_t avail, i;
        !           344:        struct timespec t;
        !           345:
        !           346:        /* Calculate number of free slots in the queue. */
        !           347:        if (ev->put < ev->get)
        !           348:                avail = ev->get - ev->put;
        !           349:        else
        !           350:                avail = WSEVENT_QSIZE - (ev->put - ev->get);
        !           351:        KASSERT(avail <= WSEVENT_QSIZE);
        !           352:
        !           353:        /* Fail if there is all events will not fit in the queue. */
        !           354:        if (avail < nevents)
        !           355:                return ENOSPC;
        !           356:
        !           357:        /* Use the current time for all events. */
        !           358:        oldspl = splhigh();
        !           359:        TIMEVAL_TO_TIMESPEC(&time, &t);
        !           360:        splx(oldspl);
        !           361:
        !           362:        /* Inject the events. */
        !           363:        for (i = 0; i < nevents; i++) {
        !           364:                struct wscons_event *we;
        !           365:
        !           366:                we = &ev->q[ev->put];
        !           367:                we->type = events[i].type;
        !           368:                we->value = events[i].value;
        !           369:                we->time = t;
        !           370:
        !           371:                ev->put = (ev->put + 1) % WSEVENT_QSIZE;
        !           372:        }
        !           373:
        !           374:        wsevent_wakeup(ev);
        !           375:
        !           376:        return 0;
        !           377: }

CVSweb <webmaster@jp.NetBSD.org>