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

Annotation of sys/dev/wscons/wsmouse.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: wsmouse.c,v 1.19 2007/04/10 22:37:17 miod Exp $ */
                      2: /* $NetBSD: wsmouse.c,v 1.35 2005/02/27 00:27:52 perry Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *      This product includes software developed by Christopher G. Demetriou
                     18:  *     for the NetBSD Project.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34: /*
                     35:  * Copyright (c) 1992, 1993
                     36:  *     The Regents of the University of California.  All rights reserved.
                     37:  *
                     38:  * This software was developed by the Computer Systems Engineering group
                     39:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
                     40:  * contributed to Berkeley.
                     41:  *
                     42:  * All advertising materials mentioning features or use of this software
                     43:  * must display the following acknowledgement:
                     44:  *     This product includes software developed by the University of
                     45:  *     California, Lawrence Berkeley Laboratory.
                     46:  *
                     47:  * Redistribution and use in source and binary forms, with or without
                     48:  * modification, are permitted provided that the following conditions
                     49:  * are met:
                     50:  * 1. Redistributions of source code must retain the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer.
                     52:  * 2. Redistributions in binary form must reproduce the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer in the
                     54:  *    documentation and/or other materials provided with the distribution.
                     55:  * 3. Neither the name of the University nor the names of its contributors
                     56:  *    may be used to endorse or promote products derived from this software
                     57:  *    without specific prior written permission.
                     58:  *
                     59:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     60:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     61:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     62:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     63:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     64:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     65:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     66:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     67:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     68:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     69:  * SUCH DAMAGE.
                     70:  *
                     71:  *     @(#)ms.c        8.1 (Berkeley) 6/11/93
                     72:  */
                     73:
                     74: /*
                     75:  * Mouse driver.
                     76:  */
                     77:
                     78: #ifndef        SMALL_KERNEL
                     79: #define        BURNER_SUPPORT
                     80: #endif
                     81:
                     82: #include <sys/param.h>
                     83: #include <sys/conf.h>
                     84: #include <sys/ioctl.h>
                     85: #include <sys/fcntl.h>
                     86: #include <sys/kernel.h>
                     87: #include <sys/proc.h>
                     88: #include <sys/syslog.h>
                     89: #include <sys/systm.h>
                     90: #include <sys/tty.h>
                     91: #include <sys/signalvar.h>
                     92: #include <sys/device.h>
                     93: #include <sys/vnode.h>
                     94: #include <sys/poll.h>
                     95:
                     96: #include <dev/wscons/wsconsio.h>
                     97: #include <dev/wscons/wsmousevar.h>
                     98: #include <dev/wscons/wseventvar.h>
                     99: #include <dev/wscons/wsdisplayvar.h>
                    100: #include <dev/rndvar.h>
                    101:
                    102: #include "wsmux.h"
                    103: #include "wsdisplay.h"
                    104: #include "wskbd.h"
                    105:
                    106: #include <dev/wscons/wsmuxvar.h>
                    107:
                    108: #if defined(WSMUX_DEBUG) && NWSMUX > 0
                    109: #define        DPRINTF(x)      if (wsmuxdebug) printf x
                    110: #define        DPRINTFN(n,x)   if (wsmuxdebug > (n)) printf x
                    111: extern int wsmuxdebug;
                    112: #else
                    113: #define        DPRINTF(x)
                    114: #define        DPRINTFN(n,x)
                    115: #endif
                    116:
                    117: #define        INVALID_X       INT_MAX
                    118: #define        INVALID_Y       INT_MAX
                    119: #define        INVALID_Z       INT_MAX
                    120: #define        INVALID_W       INT_MAX
                    121:
                    122: struct wsmouse_softc {
                    123:        struct wsevsrc  sc_base;
                    124:
                    125:        const struct wsmouse_accessops *sc_accessops;
                    126:        void            *sc_accesscookie;
                    127:
                    128:        u_int           sc_mb;          /* mouse button state */
                    129:        u_int           sc_ub;          /* user button state */
                    130:        int             sc_dx;          /* delta-x */
                    131:        int             sc_dy;          /* delta-y */
                    132:        int             sc_dz;          /* delta-z */
                    133:        int             sc_dw;          /* delta-w */
                    134:        int             sc_x;           /* absolute-x */
                    135:        int             sc_y;           /* absolute-y */
                    136:        int             sc_z;           /* absolute-z */
                    137:        int             sc_w;           /* absolute-w */
                    138:
                    139:        int             sc_refcnt;
                    140:        u_char          sc_dying;       /* device is being detached */
                    141: };
                    142:
                    143: int    wsmouse_match(struct device *, void *, void *);
                    144: void   wsmouse_attach(struct device *, struct device *, void *);
                    145: int    wsmouse_detach(struct device *, int);
                    146: int    wsmouse_activate(struct device *, enum devact);
                    147:
                    148: int    wsmouse_do_ioctl(struct wsmouse_softc *, u_long, caddr_t,
                    149:                              int, struct proc *);
                    150:
                    151: #if NWSMUX > 0
                    152: int    wsmouse_mux_open(struct wsevsrc *, struct wseventvar *);
                    153: int    wsmouse_mux_close(struct wsevsrc *);
                    154: #endif
                    155:
                    156: int    wsmousedoioctl(struct device *, u_long, caddr_t, int,
                    157:                            struct proc *);
                    158: int    wsmousedoopen(struct wsmouse_softc *, struct wseventvar *);
                    159:
                    160: struct cfdriver wsmouse_cd = {
                    161:        NULL, "wsmouse", DV_TTY
                    162: };
                    163:
                    164: struct cfattach wsmouse_ca = {
                    165:        sizeof (struct wsmouse_softc), wsmouse_match, wsmouse_attach,
                    166:        wsmouse_detach, wsmouse_activate
                    167: };
                    168:
                    169: #if NWSMUX > 0
                    170: struct wssrcops wsmouse_srcops = {
                    171:        WSMUX_MOUSE,
                    172:        wsmouse_mux_open, wsmouse_mux_close, wsmousedoioctl, NULL, NULL
                    173: };
                    174: #endif
                    175:
                    176: /*
                    177:  * Print function (for parent devices).
                    178:  */
                    179: int
                    180: wsmousedevprint(void *aux, const char *pnp)
                    181: {
                    182:
                    183:        if (pnp)
                    184:                printf("wsmouse at %s", pnp);
                    185:        return (UNCONF);
                    186: }
                    187:
                    188: int
                    189: wsmouse_match(struct device *parent, void *match, void *aux)
                    190: {
                    191:        return (1);
                    192: }
                    193:
                    194: void
                    195: wsmouse_attach(struct device *parent, struct device *self, void *aux)
                    196: {
                    197:        struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
                    198:        struct wsmousedev_attach_args *ap = aux;
                    199: #if NWSMUX > 0
                    200:        int mux, error;
                    201: #endif
                    202:
                    203:        sc->sc_accessops = ap->accessops;
                    204:        sc->sc_accesscookie = ap->accesscookie;
                    205:
                    206: #if NWSMUX > 0
                    207:        sc->sc_base.me_ops = &wsmouse_srcops;
                    208:        mux = sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux;
                    209:        if (mux >= 0) {
                    210:                error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base);
                    211:                if (error)
                    212:                        printf(" attach error=%d", error);
                    213:                else
                    214:                        printf(" mux %d", mux);
                    215:        }
                    216: #else
                    217: #if 0  /* not worth keeping, especially since the default value is not -1... */
                    218:        if (sc->sc_base.me_dv.dv_cfdata->wsmousedevcf_mux >= 0)
                    219:                printf(" (mux ignored)");
                    220: #endif
                    221: #endif /* NWSMUX > 0 */
                    222:
                    223:        printf("\n");
                    224: }
                    225:
                    226: int
                    227: wsmouse_activate(struct device *self, enum devact act)
                    228: {
                    229:        struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
                    230:
                    231:        if (act == DVACT_DEACTIVATE)
                    232:                sc->sc_dying = 1;
                    233:        return (0);
                    234: }
                    235:
                    236: /*
                    237:  * Detach a mouse.  To keep track of users of the softc we keep
                    238:  * a reference count that's incremented while inside, e.g., read.
                    239:  * If the mouse is active and the reference count is > 0 (0 is the
                    240:  * normal state) we post an event and then wait for the process
                    241:  * that had the reference to wake us up again.  Then we blow away the
                    242:  * vnode and return (which will deallocate the softc).
                    243:  */
                    244: int
                    245: wsmouse_detach(struct device *self, int flags)
                    246: {
                    247:        struct wsmouse_softc *sc = (struct wsmouse_softc *)self;
                    248:        struct wseventvar *evar;
                    249:        int maj, mn;
                    250:        int s;
                    251:
                    252: #if NWSMUX > 0
                    253:        /* Tell parent mux we're leaving. */
                    254:        if (sc->sc_base.me_parent != NULL) {
                    255:                DPRINTF(("wsmouse_detach:\n"));
                    256:                wsmux_detach_sc(&sc->sc_base);
                    257:        }
                    258: #endif
                    259:
                    260:        /* If we're open ... */
                    261:        evar = sc->sc_base.me_evp;
                    262:        if (evar != NULL && evar->io != NULL) {
                    263:                s = spltty();
                    264:                if (--sc->sc_refcnt >= 0) {
                    265:                        /* Wake everyone by generating a dummy event. */
                    266:                        if (++evar->put >= WSEVENT_QSIZE)
                    267:                                evar->put = 0;
                    268:                        WSEVENT_WAKEUP(evar);
                    269:                        /* Wait for processes to go away. */
                    270:                        if (tsleep(sc, PZERO, "wsmdet", hz * 60))
                    271:                                printf("wsmouse_detach: %s didn't detach\n",
                    272:                                       sc->sc_base.me_dv.dv_xname);
                    273:                }
                    274:                splx(s);
                    275:        }
                    276:
                    277:        /* locate the major number */
                    278:        for (maj = 0; maj < nchrdev; maj++)
                    279:                if (cdevsw[maj].d_open == wsmouseopen)
                    280:                        break;
                    281:
                    282:        /* Nuke the vnodes for any open instances (calls close). */
                    283:        mn = self->dv_unit;
                    284:        vdevgone(maj, mn, mn, VCHR);
                    285:
                    286:        return (0);
                    287: }
                    288:
                    289: void
                    290: wsmouse_input(struct device *wsmousedev, u_int btns, /* 0 is up */
                    291:     int x, int y, int z, int w, u_int flags)
                    292: {
                    293:        struct wsmouse_softc *sc = (struct wsmouse_softc *)wsmousedev;
                    294:        struct wscons_event *ev;
                    295:        struct wseventvar *evar;
                    296:        int mb, ub, d, get, put, any;
                    297:
                    298:        add_mouse_randomness(x ^ y ^ z ^ w ^ btns);
                    299:
                    300:        /*
                    301:         * Discard input if not ready.
                    302:         */
                    303:        evar = sc->sc_base.me_evp;
                    304:        if (evar == NULL)
                    305:                return;
                    306:
                    307: #ifdef DIAGNOSTIC
                    308:        if (evar->q == NULL) {
                    309:                printf("wsmouse_input: evar->q=NULL\n");
                    310:                return;
                    311:        }
                    312: #endif
                    313:
                    314: #if NWSMUX > 0
                    315:        DPRINTFN(5,("wsmouse_input: %s mux=%p, evar=%p\n",
                    316:                    sc->sc_base.me_dv.dv_xname, sc->sc_base.me_parent, evar));
                    317: #endif
                    318:
                    319:        sc->sc_mb = btns;
                    320:        if (!(flags & WSMOUSE_INPUT_ABSOLUTE_X))
                    321:                sc->sc_dx += x;
                    322:        if (!(flags & WSMOUSE_INPUT_ABSOLUTE_Y))
                    323:                sc->sc_dy += y;
                    324:        if (!(flags & WSMOUSE_INPUT_ABSOLUTE_Z))
                    325:                sc->sc_dz += z;
                    326:        if (!(flags & WSMOUSE_INPUT_ABSOLUTE_W))
                    327:                sc->sc_dw += w;
                    328:
                    329:        /*
                    330:         * We have at least one event (mouse button, delta-X, or
                    331:         * delta-Y; possibly all three, and possibly three separate
                    332:         * button events).  Deliver these events until we are out
                    333:         * of changes or out of room.  As events get delivered,
                    334:         * mark them `unchanged'.
                    335:         */
                    336:        ub = sc->sc_ub;
                    337:        any = 0;
                    338:        get = evar->get;
                    339:        put = evar->put;
                    340:        ev = &evar->q[put];
                    341:
                    342:        /* NEXT prepares to put the next event, backing off if necessary */
                    343: #define        NEXT                                                            \
                    344:        if ((++put) % WSEVENT_QSIZE == get) {                           \
                    345:                put--;                                                  \
                    346:                goto out;                                               \
                    347:        }
                    348:        /* ADVANCE completes the `put' of the event */
                    349: #define        ADVANCE                                                         \
                    350:        ev++;                                                           \
                    351:        if (put >= WSEVENT_QSIZE) {                                     \
                    352:                put = 0;                                                \
                    353:                ev = &evar->q[0];                               \
                    354:        }                                                               \
                    355:        any = 1
                    356:        /* TIMESTAMP sets `time' field of the event to the current time */
                    357: #define TIMESTAMP                                                      \
                    358:        do {                                                            \
                    359:                getnanotime(&ev->time);                                 \
                    360:        } while (0)
                    361:
                    362:        if (flags & WSMOUSE_INPUT_ABSOLUTE_X) {
                    363:                if (sc->sc_x != x) {
                    364:                        NEXT;
                    365:                        ev->type = WSCONS_EVENT_MOUSE_ABSOLUTE_X;
                    366:                        ev->value = x;
                    367:                        TIMESTAMP;
                    368:                        ADVANCE;
                    369:                        sc->sc_x = x;
                    370:                }
                    371:        } else {
                    372:                if (sc->sc_dx) {
                    373:                        NEXT;
                    374:                        ev->type = WSCONS_EVENT_MOUSE_DELTA_X;
                    375:                        ev->value = sc->sc_dx;
                    376:                        TIMESTAMP;
                    377:                        ADVANCE;
                    378:                        sc->sc_dx = 0;
                    379:                }
                    380:        }
                    381:        if (flags & WSMOUSE_INPUT_ABSOLUTE_Y) {
                    382:                if (sc->sc_y != y) {
                    383:                        NEXT;
                    384:                        ev->type = WSCONS_EVENT_MOUSE_ABSOLUTE_Y;
                    385:                        ev->value = y;
                    386:                        TIMESTAMP;
                    387:                        ADVANCE;
                    388:                        sc->sc_y = y;
                    389:                }
                    390:        } else {
                    391:                if (sc->sc_dy) {
                    392:                        NEXT;
                    393:                        ev->type = WSCONS_EVENT_MOUSE_DELTA_Y;
                    394:                        ev->value = sc->sc_dy;
                    395:                        TIMESTAMP;
                    396:                        ADVANCE;
                    397:                        sc->sc_dy = 0;
                    398:                }
                    399:        }
                    400:        if (flags & WSMOUSE_INPUT_ABSOLUTE_Z) {
                    401:                if (sc->sc_z != z) {
                    402:                        NEXT;
                    403:                        ev->type = WSCONS_EVENT_MOUSE_ABSOLUTE_Z;
                    404:                        ev->value = z;
                    405:                        TIMESTAMP;
                    406:                        ADVANCE;
                    407:                        sc->sc_z = z;
                    408:                }
                    409:        } else {
                    410:                if (sc->sc_dz) {
                    411:                        NEXT;
                    412:                        ev->type = WSCONS_EVENT_MOUSE_DELTA_Z;
                    413:                        ev->value = sc->sc_dz;
                    414:                        TIMESTAMP;
                    415:                        ADVANCE;
                    416:                        sc->sc_dz = 0;
                    417:                }
                    418:        }
                    419:        if (flags & WSMOUSE_INPUT_ABSOLUTE_W) {
                    420:                if (sc->sc_w != w) {
                    421:                        NEXT;
                    422:                        ev->type = WSCONS_EVENT_MOUSE_ABSOLUTE_W;
                    423:                        ev->value = w;
                    424:                        TIMESTAMP;
                    425:                        ADVANCE;
                    426:                        sc->sc_w = w;
                    427:                }
                    428:        } else {
                    429:                if (sc->sc_dw) {
                    430:                        NEXT;
                    431:                        ev->type = WSCONS_EVENT_MOUSE_DELTA_W;
                    432:                        ev->value = sc->sc_dw;
                    433:                        TIMESTAMP;
                    434:                        ADVANCE;
                    435:                        sc->sc_dw = 0;
                    436:                }
                    437:        }
                    438:
                    439:        mb = sc->sc_mb;
                    440:        while ((d = mb ^ ub) != 0) {
                    441:                /*
                    442:                 * Mouse button change.  Find the first change and drop
                    443:                 * it into the event queue.
                    444:                 */
                    445:                NEXT;
                    446:                ev->value = ffs(d) - 1;
                    447:
                    448:                KASSERT(ev->value >= 0);
                    449:
                    450:                d = 1 << ev->value;
                    451:                ev->type =
                    452:                    (mb & d) ? WSCONS_EVENT_MOUSE_DOWN : WSCONS_EVENT_MOUSE_UP;
                    453:                TIMESTAMP;
                    454:                ADVANCE;
                    455:                ub ^= d;
                    456:        }
                    457:
                    458:        /* XXX fake wscons_event notifying wsmoused(8) to close mouse device */
                    459:        if (flags & WSMOUSE_INPUT_WSMOUSED_CLOSE) {
                    460:                NEXT;
                    461:                ev->type = WSCONS_EVENT_WSMOUSED_CLOSE;
                    462:                ev->value = 0;
                    463:                TIMESTAMP;
                    464:                ADVANCE;
                    465:        }
                    466:
                    467: #undef TIMESTAMP
                    468: #undef ADVANCE
                    469: #undef NEXT
                    470:
                    471: out:
                    472:        if (any) {
                    473:                sc->sc_ub = ub;
                    474:                evar->put = put;
                    475:                WSEVENT_WAKEUP(evar);
                    476: #ifdef BURNER_SUPPORT
                    477:                /* wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_MOUSE); */
                    478: #endif
                    479: #if NWSMUX > 0
                    480:                DPRINTFN(5,("wsmouse_input: %s wakeup evar=%p\n",
                    481:                            sc->sc_base.me_dv.dv_xname, evar));
                    482: #endif
                    483:        }
                    484: }
                    485:
                    486: int
                    487: wsmouseopen(dev_t dev, int flags, int mode, struct proc *p)
                    488: {
                    489:        struct wsmouse_softc *sc;
                    490:        struct wseventvar *evar;
                    491:        int error, unit;
                    492:
                    493:        unit = minor(dev);
                    494:        if (unit >= wsmouse_cd.cd_ndevs ||      /* make sure it was attached */
                    495:            (sc = wsmouse_cd.cd_devs[unit]) == NULL)
                    496:                return (ENXIO);
                    497:
                    498: #if NWSMUX > 0
                    499:        DPRINTF(("wsmouseopen: %s mux=%p p=%p\n", sc->sc_base.me_dv.dv_xname,
                    500:                 sc->sc_base.me_parent, p));
                    501: #endif
                    502:
                    503:        if (sc->sc_dying)
                    504:                return (EIO);
                    505:
                    506:        if ((flags & (FREAD | FWRITE)) == FWRITE)
                    507:                return (0);                     /* always allow open for write
                    508:                                                   so ioctl() is possible. */
                    509:
                    510:        if (sc->sc_base.me_evp != NULL)
                    511:                return (EBUSY);
                    512:
                    513:        evar = &sc->sc_base.me_evar;
                    514:        wsevent_init(evar);
                    515:        evar->io = p;
                    516:
                    517:        error = wsmousedoopen(sc, evar);
                    518:        if (error) {
                    519:                DPRINTF(("wsmouseopen: %s open failed\n",
                    520:                         sc->sc_base.me_dv.dv_xname));
                    521:                sc->sc_base.me_evp = NULL;
                    522:                wsevent_fini(evar);
                    523:        }
                    524:        return (error);
                    525: }
                    526:
                    527: int
                    528: wsmouseclose(dev_t dev, int flags, int mode, struct proc *p)
                    529: {
                    530:        struct wsmouse_softc *sc =
                    531:            (struct wsmouse_softc *)wsmouse_cd.cd_devs[minor(dev)];
                    532:        struct wseventvar *evar = sc->sc_base.me_evp;
                    533:
                    534:        if ((flags & (FREAD | FWRITE)) == FWRITE)
                    535:                return (0);                     /* see wsmouseopen() */
                    536:
                    537:        if (evar == NULL)
                    538:                /* not open for read */
                    539:                return (0);
                    540:        sc->sc_base.me_evp = NULL;
                    541:        (*sc->sc_accessops->disable)(sc->sc_accesscookie);
                    542:        wsevent_fini(evar);
                    543:
                    544:        return (0);
                    545: }
                    546:
                    547: int
                    548: wsmousedoopen(struct wsmouse_softc *sc, struct wseventvar *evp)
                    549: {
                    550:        sc->sc_base.me_evp = evp;
                    551:        sc->sc_x = INVALID_X;
                    552:        sc->sc_y = INVALID_Y;
                    553:        sc->sc_z = INVALID_Z;
                    554:        sc->sc_w = INVALID_W;
                    555:
                    556:        /* enable the device, and punt if that's not possible */
                    557:        return (*sc->sc_accessops->enable)(sc->sc_accesscookie);
                    558: }
                    559:
                    560: int
                    561: wsmouseread(dev_t dev, struct uio *uio, int flags)
                    562: {
                    563:        struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)];
                    564:        int error;
                    565:
                    566:        if (sc->sc_dying)
                    567:                return (EIO);
                    568:
                    569: #ifdef DIAGNOSTIC
                    570:        if (sc->sc_base.me_evp == NULL) {
                    571:                printf("wsmouseread: evp == NULL\n");
                    572:                return (EINVAL);
                    573:        }
                    574: #endif
                    575:
                    576:        sc->sc_refcnt++;
                    577:        error = wsevent_read(sc->sc_base.me_evp, uio, flags);
                    578:        if (--sc->sc_refcnt < 0) {
                    579:                wakeup(sc);
                    580:                error = EIO;
                    581:        }
                    582:        return (error);
                    583: }
                    584:
                    585: int
                    586: wsmouseioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                    587: {
                    588:        return (wsmousedoioctl(wsmouse_cd.cd_devs[minor(dev)],
                    589:            cmd, data, flag, p));
                    590: }
                    591:
                    592: /* A wrapper around the ioctl() workhorse to make reference counting easy. */
                    593: int
                    594: wsmousedoioctl(struct device *dv, u_long cmd, caddr_t data, int flag,
                    595:     struct proc *p)
                    596: {
                    597:        struct wsmouse_softc *sc = (struct wsmouse_softc *)dv;
                    598:        int error;
                    599:
                    600:        sc->sc_refcnt++;
                    601:        error = wsmouse_do_ioctl(sc, cmd, data, flag, p);
                    602:        if (--sc->sc_refcnt < 0)
                    603:                wakeup(sc);
                    604:        return (error);
                    605: }
                    606:
                    607: int
                    608: wsmouse_do_ioctl(struct wsmouse_softc *sc, u_long cmd, caddr_t data, int flag,
                    609:     struct proc *p)
                    610: {
                    611:        int error;
                    612:
                    613:        if (sc->sc_dying)
                    614:                return (EIO);
                    615:
                    616:        /*
                    617:         * Try the generic ioctls that the wsmouse interface supports.
                    618:         */
                    619:
                    620:        switch (cmd) {
                    621:        case FIOASYNC:
                    622:        case FIOSETOWN:
                    623:        case TIOCSPGRP:
                    624:                if ((flag & FWRITE) == 0)
                    625:                        return (EACCES);
                    626:        }
                    627:
                    628:        switch (cmd) {
                    629:        case FIONBIO:           /* we will remove this someday (soon???) */
                    630:                return (0);
                    631:
                    632:        case FIOASYNC:
                    633:                if (sc->sc_base.me_evp == NULL)
                    634:                        return (EINVAL);
                    635:                sc->sc_base.me_evp->async = *(int *)data != 0;
                    636:                return (0);
                    637:
                    638:        case FIOSETOWN:
                    639:                if (sc->sc_base.me_evp == NULL)
                    640:                        return (EINVAL);
                    641:                if (-*(int *)data != sc->sc_base.me_evp->io->p_pgid
                    642:                    && *(int *)data != sc->sc_base.me_evp->io->p_pid)
                    643:                        return (EPERM);
                    644:                return (0);
                    645:
                    646:        case TIOCSPGRP:
                    647:                if (sc->sc_base.me_evp == NULL)
                    648:                        return (EINVAL);
                    649:                if (*(int *)data != sc->sc_base.me_evp->io->p_pgid)
                    650:                        return (EPERM);
                    651:                return (0);
                    652:        }
                    653:
                    654:        /*
                    655:         * Try the mouse driver for WSMOUSEIO ioctls.  It returns -1
                    656:         * if it didn't recognize the request.
                    657:         */
                    658:        error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd,
                    659:            data, flag, p);
                    660:        return (error != -1 ? error : ENOTTY);
                    661: }
                    662:
                    663: int
                    664: wsmousepoll(dev_t dev, int events, struct proc *p)
                    665: {
                    666:        struct wsmouse_softc *sc = wsmouse_cd.cd_devs[minor(dev)];
                    667:
                    668:        if (sc->sc_base.me_evp == NULL)
                    669:                return (POLLERR);
                    670:        return (wsevent_poll(sc->sc_base.me_evp, events, p));
                    671: }
                    672:
                    673: #if NWSMUX > 0
                    674: int
                    675: wsmouse_mux_open(struct wsevsrc *me, struct wseventvar *evp)
                    676: {
                    677:        struct wsmouse_softc *sc = (struct wsmouse_softc *)me;
                    678:
                    679:        if (sc->sc_base.me_evp != NULL)
                    680:                return (EBUSY);
                    681:
                    682:        return wsmousedoopen(sc, evp);
                    683: }
                    684:
                    685: int
                    686: wsmouse_mux_close(struct wsevsrc *me)
                    687: {
                    688:        struct wsmouse_softc *sc = (struct wsmouse_softc *)me;
                    689:
                    690:        sc->sc_base.me_evp = NULL;
                    691:        (*sc->sc_accessops->disable)(sc->sc_accesscookie);
                    692:
                    693:        return (0);
                    694: }
                    695:
                    696: int
                    697: wsmouse_add_mux(int unit, struct wsmux_softc *muxsc)
                    698: {
                    699:        struct wsmouse_softc *sc;
                    700:
                    701:        if (unit < 0 || unit >= wsmouse_cd.cd_ndevs ||
                    702:            (sc = wsmouse_cd.cd_devs[unit]) == NULL)
                    703:                return (ENXIO);
                    704:
                    705:        if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL)
                    706:                return (EBUSY);
                    707:
                    708:        return (wsmux_attach_sc(muxsc, &sc->sc_base));
                    709: }
                    710: #endif /* NWSMUX > 0 */

CVSweb