diff options
Diffstat (limited to 'sys/arch/alpha/wscons/ms.c')
-rw-r--r-- | sys/arch/alpha/wscons/ms.c | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/sys/arch/alpha/wscons/ms.c b/sys/arch/alpha/wscons/ms.c new file mode 100644 index 00000000000..240a0b4bfd6 --- /dev/null +++ b/sys/arch/alpha/wscons/ms.c @@ -0,0 +1,285 @@ +/* $NetBSD: ms.c,v 1.1 1996/04/12 02:00:47 cgd Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ms.c 8.1 (Berkeley) 6/11/93 + */ + +/* + * Mouse driver. + */ + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/ioctl.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/syslog.h> +#include <sys/systm.h> +#include <sys/tty.h> + +#include <machine/vuid_event.h> +#include <alpha/wscons/event_var.h> +#include <alpha/wscons/wsconsvar.h> + +struct ms_softc { + struct device *ms_dev; + struct wscons_mdev_spec ms_spec; + char ms_mb; /* mouse button state */ + char ms_ub; /* user button state */ + int ms_dx; /* delta-x */ + int ms_dy; /* delta-y */ + volatile int ms_ready; /* event queue is ready */ + struct evvar ms_events; /* event queue state */ +} ms_softc; + +void +msattach(mdev, mspec) + struct device *mdev; + struct wscons_mdev_spec *mspec; +{ + register struct ms_softc *m = &ms_softc; + + m->ms_dev = mdev; + m->ms_spec = *mspec; +} + +void +ms_event(buttons, dx, dy) + char buttons; /* 0 is up */ + int dx, dy; +{ + register struct firm_event *fe; + register struct ms_softc *ms = &ms_softc; + register int mb, ub, d, get, put, any; + static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 }; + static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT }; + + /* + * Discard input if not ready. + */ + if (ms->ms_ready == 0) + return; + + ms->ms_mb = (buttons) & 0x7; + ms->ms_dx += dx; + ms->ms_dy += dy; + + /* + * We have at least one event (mouse button, delta-X, or + * delta-Y; possibly all three, and possibly three separate + * button events). Deliver these events until we are out + * of changes or out of room. As events get delivered, + * mark them `unchanged'. + */ + any = 0; + get = ms->ms_events.ev_get; + put = ms->ms_events.ev_put; + fe = &ms->ms_events.ev_q[put]; + + /* NEXT prepares to put the next event, backing off if necessary */ +#define NEXT \ + if ((++put) % EV_QSIZE == get) { \ + put--; \ + goto out; \ + } + /* ADVANCE completes the `put' of the event */ +#define ADVANCE \ + fe++; \ + if (put >= EV_QSIZE) { \ + put = 0; \ + fe = &ms->ms_events.ev_q[0]; \ + } \ + any = 1 + + mb = ms->ms_mb; + ub = ms->ms_ub; + while ((d = mb ^ ub) != 0) { + /* + * Mouse button change. Convert up to three changes + * to the `first' change, and drop it into the event queue. + */ + NEXT; + d = to_one[d - 1]; /* from 1..7 to {1,2,4} */ + fe->id = to_id[d - 1]; /* from {1,2,4} to ID */ + fe->value = mb & d ? VKEY_DOWN : VKEY_UP; + fe->time = time; + ADVANCE; + ub ^= d; + } + if (ms->ms_dx) { + NEXT; + fe->id = LOC_X_DELTA; + fe->value = ms->ms_dx; + fe->time = time; + ADVANCE; + ms->ms_dx = 0; + } + if (ms->ms_dy) { + NEXT; + fe->id = LOC_Y_DELTA; + fe->value = ms->ms_dy; + fe->time = time; + ADVANCE; + ms->ms_dy = 0; + } +out: + if (any) { + ms->ms_ub = ub; + ms->ms_events.ev_put = put; + EV_WAKEUP(&ms->ms_events); + } +} + +int +msopen(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; +{ + int s, error; + + if (ms_softc.ms_dev == NULL) /* never attached! */ + return (ENXIO); + + if (ms_softc.ms_events.ev_io) + return (EBUSY); + + ms_softc.ms_events.ev_io = p; + ev_init(&ms_softc.ms_events); /* may cause sleep */ + + ms_softc.ms_ready = 1; /* start accepting events */ + + error = (*ms_softc.ms_spec.wm_enable)(ms_softc.ms_dev); + + if (error) { + ms_softc.ms_ready = 0; /* stop accepting events */ + ev_fini(&ms_softc.ms_events); + ms_softc.ms_events.ev_io = NULL; + return (error); + } + + return (0); +} + +int +msclose(dev, flags, mode, p) + dev_t dev; + int flags, mode; + struct proc *p; +{ + + (*ms_softc.ms_spec.wm_disable)(ms_softc.ms_dev); + + ms_softc.ms_ready = 0; /* stop accepting events */ + ev_fini(&ms_softc.ms_events); + ms_softc.ms_events.ev_io = NULL; + return (0); +} + +int +msread(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + + return (ev_read(&ms_softc.ms_events, uio, flags)); +} + +/* this routine should not exist, but is convenient to write here for now */ +int +mswrite(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + + return (EOPNOTSUPP); +} + +int +msioctl(dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + register caddr_t data; + int flag; + struct proc *p; +{ + int s; + + switch (cmd) { + + case FIONBIO: /* we will remove this someday (soon???) */ + return (0); + + case FIOASYNC: + ms_softc.ms_events.ev_async = *(int *)data != 0; + return (0); + + case TIOCSPGRP: + if (*(int *)data != ms_softc.ms_events.ev_io->p_pgid) + return (EPERM); + return (0); + + case VUIDGFORMAT: + /* we only do firm_events */ + *(int *)data = VUID_FIRM_EVENT; + return (0); + + case VUIDSFORMAT: + if (*(int *)data != VUID_FIRM_EVENT) + return (EINVAL); + return (0); + } + return (ENOTTY); +} + +int +msselect(dev, rw, p) + dev_t dev; + int rw; + struct proc *p; +{ + + return (ev_select(&ms_softc.ms_events, rw, p)); +} |