155106Storek /*
2*63318Sbostic * Copyright (c) 1992, 1993
3*63318Sbostic * The Regents of the University of California. All rights reserved.
455106Storek *
555106Storek * This software was developed by the Computer Systems Engineering group
655106Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
755106Storek * contributed to Berkeley.
855106Storek *
955499Sbostic * All advertising materials mentioning features or use of this software
1055499Sbostic * must display the following acknowledgement:
1155499Sbostic * This product includes software developed by the University of
1259190Storek * California, Lawrence Berkeley Laboratory.
1355499Sbostic *
1455106Storek * %sccs.include.redist.c%
1555106Storek *
16*63318Sbostic * @(#)ms.c 8.1 (Berkeley) 06/11/93
1755106Storek *
1859190Storek * from: $Header: ms.c,v 1.5 92/11/26 01:28:47 torek Exp $ (LBL)
1955106Storek */
2055106Storek
2155106Storek /*
2255106Storek * Mouse driver.
2355106Storek */
2455106Storek
2556536Sbostic #include <sys/param.h>
2656536Sbostic #include <sys/conf.h>
2756536Sbostic #include <sys/ioctl.h>
2856536Sbostic #include <sys/kernel.h>
2956536Sbostic #include <sys/proc.h>
3056536Sbostic #include <sys/syslog.h>
3156536Sbostic #include <sys/systm.h>
3256536Sbostic #include <sys/tty.h>
3355106Storek
3456536Sbostic #include <sparc/dev/vuid_event.h>
3556536Sbostic #include <sparc/dev/event_var.h>
3655106Storek
3755106Storek /*
3855106Storek * Mouse state. A Mouse Systems mouse is a fairly simple device,
3955106Storek * producing five-byte blobs of the form:
4055106Storek *
4155106Storek * b dx dy dx dy
4255106Storek *
4355106Storek * where b is the button state, encoded as 0x80|(~buttons)---there are
4455106Storek * three buttons (4=left, 2=middle, 1=right)---and dx,dy are X and Y
4555106Storek * delta values, none of which have are in [0x80..0x87]. (This lets
4655106Storek * us sync up with the mouse after an error.)
4755106Storek */
4855106Storek struct ms_softc {
4955106Storek short ms_byteno; /* input byte number, for decode */
5055106Storek char ms_mb; /* mouse button state */
5155106Storek char ms_ub; /* user button state */
5255106Storek int ms_dx; /* delta-x */
5355106Storek int ms_dy; /* delta-y */
5455106Storek struct tty *ms_mouse; /* downlink for output to mouse */
5555106Storek void (*ms_open) __P((struct tty *)); /* enable dataflow */
5655106Storek void (*ms_close) __P((struct tty *));/* disable dataflow */
5755106Storek volatile int ms_ready; /* event queue is ready */
5855106Storek struct evvar ms_events; /* event queue state */
5955106Storek } ms_softc;
6055106Storek
6155106Storek /*
6255106Storek * Attach the mouse serial (down-link) interface.
6355106Storek * Do we need to set it to 1200 baud, 8 bits?
6455106Storek * Test by power cycling and not booting SunOS before BSD?
6555106Storek */
6655106Storek void
ms_serial(tp,iopen,iclose)6755106Storek ms_serial(tp, iopen, iclose)
6855106Storek struct tty *tp;
6955106Storek void (*iopen)(), (*iclose)();
7055106Storek {
7155106Storek
7255106Storek ms_softc.ms_mouse = tp;
7355106Storek ms_softc.ms_open = iopen;
7455106Storek ms_softc.ms_close = iclose;
7555106Storek }
7655106Storek
7755106Storek void
ms_rint(c)7855106Storek ms_rint(c)
7955106Storek register int c;
8055106Storek {
8155106Storek register struct firm_event *fe;
8255106Storek register struct ms_softc *ms = &ms_softc;
8355106Storek register int mb, ub, d, get, put, any;
8455106Storek static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 };
8555106Storek static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT };
8655106Storek
8755106Storek /*
8855106Storek * Discard input if not ready. Drop sync on parity or framing
8955106Storek * error; gain sync on button byte.
9055106Storek */
9155106Storek if (ms->ms_ready == 0)
9255106Storek return;
9355106Storek if (c & (TTY_FE|TTY_PE)) {
9455106Storek log(LOG_WARNING,
9555106Storek "mouse input parity or framing error (0x%x)\n", c);
9655106Storek ms->ms_byteno = -1;
9755106Storek return;
9855106Storek }
9955106Storek if ((unsigned)(c - 0x80) < 8) /* if in 0x80..0x87 */
10055106Storek ms->ms_byteno = 0;
10155106Storek
10255106Storek /*
10355106Storek * Run the decode loop, adding to the current information.
10455106Storek * We add, rather than replace, deltas, so that if the event queue
10555106Storek * fills, we accumulate data for when it opens up again.
10655106Storek */
10755106Storek switch (ms->ms_byteno) {
10855106Storek
10955106Storek case -1:
11055106Storek return;
11155106Storek
11255106Storek case 0:
11355106Storek /* buttons */
11455106Storek ms->ms_byteno = 1;
11555106Storek ms->ms_mb = (~c) & 0x7;
11655106Storek return;
11755106Storek
11855106Storek case 1:
11955106Storek /* first delta-x */
12055106Storek ms->ms_byteno = 2;
12155106Storek ms->ms_dx += (char)c;
12255106Storek return;
12355106Storek
12455106Storek case 2:
12555106Storek /* first delta-y */
12655106Storek ms->ms_byteno = 3;
12755106Storek ms->ms_dy += (char)c;
12855106Storek return;
12955106Storek
13055106Storek case 3:
13155106Storek /* second delta-x */
13255106Storek ms->ms_byteno = 4;
13355106Storek ms->ms_dx += (char)c;
13455106Storek return;
13555106Storek
13655106Storek case 4:
13755106Storek /* second delta-x */
13855106Storek ms->ms_byteno = -1; /* wait for button-byte again */
13955106Storek ms->ms_dy += (char)c;
14055106Storek break;
14155106Storek
14255106Storek default:
14355106Storek panic("ms_rint");
14455106Storek /* NOTREACHED */
14555106Storek }
14655106Storek
14755106Storek /*
14855106Storek * We have at least one event (mouse button, delta-X, or
14955106Storek * delta-Y; possibly all three, and possibly three separate
15055106Storek * button events). Deliver these events until we are out
15155106Storek * of changes or out of room. As events get delivered,
15255106Storek * mark them `unchanged'.
15355106Storek */
15455106Storek any = 0;
15555106Storek get = ms->ms_events.ev_get;
15655106Storek put = ms->ms_events.ev_put;
15755106Storek fe = &ms->ms_events.ev_q[put];
15855106Storek
15955106Storek /* NEXT prepares to put the next event, backing off if necessary */
16055106Storek #define NEXT \
16155106Storek if ((++put) % EV_QSIZE == get) { \
16255106Storek put--; \
16355106Storek goto out; \
16455106Storek }
16555106Storek /* ADVANCE completes the `put' of the event */
16655106Storek #define ADVANCE \
16755106Storek fe++; \
16855106Storek if (put >= EV_QSIZE) { \
16955106Storek put = 0; \
17055106Storek fe = &ms->ms_events.ev_q[0]; \
17155106Storek } \
17255106Storek any = 1
17355106Storek
17455106Storek mb = ms->ms_mb;
17555106Storek ub = ms->ms_ub;
17655106Storek while ((d = mb ^ ub) != 0) {
17755106Storek /*
17855106Storek * Mouse button change. Convert up to three changes
17955106Storek * to the `first' change, and drop it into the event queue.
18055106Storek */
18155106Storek NEXT;
18255106Storek d = to_one[d - 1]; /* from 1..7 to {1,2,4} */
18355106Storek fe->id = to_id[d - 1]; /* from {1,2,4} to ID */
18455106Storek fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
18555106Storek fe->time = time;
18655106Storek ADVANCE;
18755106Storek ub ^= d;
18855106Storek }
18955106Storek if (ms->ms_dx) {
19055106Storek NEXT;
19155106Storek fe->id = LOC_X_DELTA;
19255106Storek fe->value = ms->ms_dx;
19355106Storek fe->time = time;
19455106Storek ADVANCE;
19555106Storek ms->ms_dx = 0;
19655106Storek }
19755106Storek if (ms->ms_dy) {
19855106Storek NEXT;
19955106Storek fe->id = LOC_Y_DELTA;
20055106Storek fe->value = ms->ms_dy;
20155106Storek fe->time = time;
20255106Storek ADVANCE;
20355106Storek ms->ms_dy = 0;
20455106Storek }
20555106Storek out:
20655106Storek if (any) {
20755106Storek ms->ms_ub = ub;
20855106Storek ms->ms_events.ev_put = put;
20955106Storek EV_WAKEUP(&ms->ms_events);
21055106Storek }
21155106Storek }
21255106Storek
21355106Storek int
msopen(dev,flags,mode,p)21455106Storek msopen(dev, flags, mode, p)
21555106Storek dev_t dev;
21655106Storek int flags, mode;
21755106Storek struct proc *p;
21855106Storek {
21955106Storek int s, error;
22055106Storek
22155106Storek if (ms_softc.ms_events.ev_io)
22255106Storek return (EBUSY);
22355106Storek ms_softc.ms_events.ev_io = p;
22455106Storek ev_init(&ms_softc.ms_events); /* may cause sleep */
22555106Storek ms_softc.ms_ready = 1; /* start accepting events */
22655106Storek (*ms_softc.ms_open)(ms_softc.ms_mouse);
22755106Storek return (0);
22855106Storek }
22955106Storek
23055106Storek int
msclose(dev,flags,mode,p)23155106Storek msclose(dev, flags, mode, p)
23255106Storek dev_t dev;
23355106Storek int flags, mode;
23455106Storek struct proc *p;
23555106Storek {
23655106Storek
23755106Storek ms_softc.ms_ready = 0; /* stop accepting events */
23855106Storek ev_fini(&ms_softc.ms_events);
23955106Storek (*ms_softc.ms_close)(ms_softc.ms_mouse);
24055106Storek ms_softc.ms_events.ev_io = NULL;
24155106Storek return (0);
24255106Storek }
24355106Storek
24455106Storek int
msread(dev,uio,flags)24555106Storek msread(dev, uio, flags)
24655106Storek dev_t dev;
24755106Storek struct uio *uio;
24855106Storek int flags;
24955106Storek {
25055106Storek
25155106Storek return (ev_read(&ms_softc.ms_events, uio, flags));
25255106Storek }
25355106Storek
25455106Storek /* this routine should not exist, but is convenient to write here for now */
25555106Storek int
mswrite(dev,uio,flags)25655106Storek mswrite(dev, uio, flags)
25755106Storek dev_t dev;
25855106Storek struct uio *uio;
25955106Storek int flags;
26055106Storek {
26155106Storek
26255106Storek return (EOPNOTSUPP);
26355106Storek }
26455106Storek
26555106Storek int
msioctl(dev,cmd,data,flag,p)26655106Storek msioctl(dev, cmd, data, flag, p)
26755106Storek dev_t dev;
26855106Storek int cmd;
26955106Storek register caddr_t data;
27055106Storek int flag;
27155106Storek struct proc *p;
27255106Storek {
27355106Storek int s;
27455106Storek
27555106Storek switch (cmd) {
27655106Storek
27755106Storek case FIONBIO: /* we will remove this someday (soon???) */
27855106Storek return (0);
27955106Storek
28055106Storek case FIOASYNC:
28155106Storek ms_softc.ms_events.ev_async = *(int *)data != 0;
28255106Storek return (0);
28355106Storek
28455106Storek case TIOCSPGRP:
28555106Storek if (*(int *)data != ms_softc.ms_events.ev_io->p_pgid)
28655106Storek return (EPERM);
28755106Storek return (0);
28855106Storek
28955106Storek case VUIDGFORMAT:
29055106Storek /* we only do firm_events */
29155106Storek *(int *)data = VUID_FIRM_EVENT;
29255106Storek return (0);
29355106Storek
29455106Storek case VUIDSFORMAT:
29555106Storek if (*(int *)data != VUID_FIRM_EVENT)
29655106Storek return (EINVAL);
29755106Storek return (0);
29855106Storek }
29955106Storek return (ENOTTY);
30055106Storek }
30155106Storek
30255106Storek int
msselect(dev,rw,p)30355106Storek msselect(dev, rw, p)
30455106Storek dev_t dev;
30555106Storek int rw;
30655106Storek struct proc *p;
30755106Storek {
30855106Storek
30955106Storek return (ev_select(&ms_softc.ms_events, rw, p));
31055106Storek }
311