xref: /csrg-svn/sys/sparc/dev/ms.c (revision 55106)
1*55106Storek /*
2*55106Storek  * Copyright (c) 1992 The Regents of the University of California.
3*55106Storek  * All rights reserved.
4*55106Storek  *
5*55106Storek  * This software was developed by the Computer Systems Engineering group
6*55106Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7*55106Storek  * contributed to Berkeley.
8*55106Storek  *
9*55106Storek  * %sccs.include.redist.c%
10*55106Storek  *
11*55106Storek  *	@(#)ms.c	7.1 (Berkeley) 07/13/92
12*55106Storek  *
13*55106Storek  * from: $Header: ms.c,v 1.4 92/06/17 05:35:50 torek Exp $ (LBL)
14*55106Storek  */
15*55106Storek 
16*55106Storek /*
17*55106Storek  * Mouse driver.
18*55106Storek  */
19*55106Storek 
20*55106Storek #include "sys/param.h"
21*55106Storek #include "sys/conf.h"
22*55106Storek #include "sys/ioctl.h"
23*55106Storek #include "sys/kernel.h"
24*55106Storek #include "sys/proc.h"
25*55106Storek #include "sys/syslog.h"
26*55106Storek #include "sys/systm.h"
27*55106Storek #include "sys/tty.h"
28*55106Storek 
29*55106Storek #include "vuid_event.h"
30*55106Storek #include "event_var.h"
31*55106Storek 
32*55106Storek /*
33*55106Storek  * Mouse state.  A Mouse Systems mouse is a fairly simple device,
34*55106Storek  * producing five-byte blobs of the form:
35*55106Storek  *
36*55106Storek  *	b dx dy dx dy
37*55106Storek  *
38*55106Storek  * where b is the button state, encoded as 0x80|(~buttons)---there are
39*55106Storek  * three buttons (4=left, 2=middle, 1=right)---and dx,dy are X and Y
40*55106Storek  * delta values, none of which have are in [0x80..0x87].  (This lets
41*55106Storek  * us sync up with the mouse after an error.)
42*55106Storek  */
43*55106Storek struct ms_softc {
44*55106Storek 	short	ms_byteno;		/* input byte number, for decode */
45*55106Storek 	char	ms_mb;			/* mouse button state */
46*55106Storek 	char	ms_ub;			/* user button state */
47*55106Storek 	int	ms_dx;			/* delta-x */
48*55106Storek 	int	ms_dy;			/* delta-y */
49*55106Storek 	struct	tty *ms_mouse;		/* downlink for output to mouse */
50*55106Storek 	void	(*ms_open) __P((struct tty *));	/* enable dataflow */
51*55106Storek 	void	(*ms_close) __P((struct tty *));/* disable dataflow */
52*55106Storek 	volatile int ms_ready;		/* event queue is ready */
53*55106Storek 	struct	evvar ms_events;	/* event queue state */
54*55106Storek } ms_softc;
55*55106Storek 
56*55106Storek /*
57*55106Storek  * Attach the mouse serial (down-link) interface.
58*55106Storek  * Do we need to set it to 1200 baud, 8 bits?
59*55106Storek  * Test by power cycling and not booting SunOS before BSD?
60*55106Storek  */
61*55106Storek void
62*55106Storek ms_serial(tp, iopen, iclose)
63*55106Storek 	struct tty *tp;
64*55106Storek 	void (*iopen)(), (*iclose)();
65*55106Storek {
66*55106Storek 
67*55106Storek 	ms_softc.ms_mouse = tp;
68*55106Storek 	ms_softc.ms_open = iopen;
69*55106Storek 	ms_softc.ms_close = iclose;
70*55106Storek }
71*55106Storek 
72*55106Storek void
73*55106Storek ms_rint(c)
74*55106Storek 	register int c;
75*55106Storek {
76*55106Storek 	register struct firm_event *fe;
77*55106Storek 	register struct ms_softc *ms = &ms_softc;
78*55106Storek 	register int mb, ub, d, get, put, any;
79*55106Storek 	static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 };
80*55106Storek 	static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT };
81*55106Storek 
82*55106Storek 	/*
83*55106Storek 	 * Discard input if not ready.  Drop sync on parity or framing
84*55106Storek 	 * error; gain sync on button byte.
85*55106Storek 	 */
86*55106Storek 	if (ms->ms_ready == 0)
87*55106Storek 		return;
88*55106Storek 	if (c & (TTY_FE|TTY_PE)) {
89*55106Storek 		log(LOG_WARNING,
90*55106Storek 		    "mouse input parity or framing error (0x%x)\n", c);
91*55106Storek 		ms->ms_byteno = -1;
92*55106Storek 		return;
93*55106Storek 	}
94*55106Storek 	if ((unsigned)(c - 0x80) < 8)	/* if in 0x80..0x87 */
95*55106Storek 		ms->ms_byteno = 0;
96*55106Storek 
97*55106Storek 	/*
98*55106Storek 	 * Run the decode loop, adding to the current information.
99*55106Storek 	 * We add, rather than replace, deltas, so that if the event queue
100*55106Storek 	 * fills, we accumulate data for when it opens up again.
101*55106Storek 	 */
102*55106Storek 	switch (ms->ms_byteno) {
103*55106Storek 
104*55106Storek 	case -1:
105*55106Storek 		return;
106*55106Storek 
107*55106Storek 	case 0:
108*55106Storek 		/* buttons */
109*55106Storek 		ms->ms_byteno = 1;
110*55106Storek 		ms->ms_mb = (~c) & 0x7;
111*55106Storek 		return;
112*55106Storek 
113*55106Storek 	case 1:
114*55106Storek 		/* first delta-x */
115*55106Storek 		ms->ms_byteno = 2;
116*55106Storek 		ms->ms_dx += (char)c;
117*55106Storek 		return;
118*55106Storek 
119*55106Storek 	case 2:
120*55106Storek 		/* first delta-y */
121*55106Storek 		ms->ms_byteno = 3;
122*55106Storek 		ms->ms_dy += (char)c;
123*55106Storek 		return;
124*55106Storek 
125*55106Storek 	case 3:
126*55106Storek 		/* second delta-x */
127*55106Storek 		ms->ms_byteno = 4;
128*55106Storek 		ms->ms_dx += (char)c;
129*55106Storek 		return;
130*55106Storek 
131*55106Storek 	case 4:
132*55106Storek 		/* second delta-x */
133*55106Storek 		ms->ms_byteno = -1;	/* wait for button-byte again */
134*55106Storek 		ms->ms_dy += (char)c;
135*55106Storek 		break;
136*55106Storek 
137*55106Storek 	default:
138*55106Storek 		panic("ms_rint");
139*55106Storek 		/* NOTREACHED */
140*55106Storek 	}
141*55106Storek 
142*55106Storek 	/*
143*55106Storek 	 * We have at least one event (mouse button, delta-X, or
144*55106Storek 	 * delta-Y; possibly all three, and possibly three separate
145*55106Storek 	 * button events).  Deliver these events until we are out
146*55106Storek 	 * of changes or out of room.  As events get delivered,
147*55106Storek 	 * mark them `unchanged'.
148*55106Storek 	 */
149*55106Storek 	any = 0;
150*55106Storek 	get = ms->ms_events.ev_get;
151*55106Storek 	put = ms->ms_events.ev_put;
152*55106Storek 	fe = &ms->ms_events.ev_q[put];
153*55106Storek 
154*55106Storek 	/* NEXT prepares to put the next event, backing off if necessary */
155*55106Storek #define	NEXT \
156*55106Storek 	if ((++put) % EV_QSIZE == get) { \
157*55106Storek 		put--; \
158*55106Storek 		goto out; \
159*55106Storek 	}
160*55106Storek 	/* ADVANCE completes the `put' of the event */
161*55106Storek #define	ADVANCE \
162*55106Storek 	fe++; \
163*55106Storek 	if (put >= EV_QSIZE) { \
164*55106Storek 		put = 0; \
165*55106Storek 		fe = &ms->ms_events.ev_q[0]; \
166*55106Storek 	} \
167*55106Storek 	any = 1
168*55106Storek 
169*55106Storek 	mb = ms->ms_mb;
170*55106Storek 	ub = ms->ms_ub;
171*55106Storek 	while ((d = mb ^ ub) != 0) {
172*55106Storek 		/*
173*55106Storek 		 * Mouse button change.  Convert up to three changes
174*55106Storek 		 * to the `first' change, and drop it into the event queue.
175*55106Storek 		 */
176*55106Storek 		NEXT;
177*55106Storek 		d = to_one[d - 1];		/* from 1..7 to {1,2,4} */
178*55106Storek 		fe->id = to_id[d - 1];		/* from {1,2,4} to ID */
179*55106Storek 		fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
180*55106Storek 		fe->time = time;
181*55106Storek 		ADVANCE;
182*55106Storek 		ub ^= d;
183*55106Storek 	}
184*55106Storek 	if (ms->ms_dx) {
185*55106Storek 		NEXT;
186*55106Storek 		fe->id = LOC_X_DELTA;
187*55106Storek 		fe->value = ms->ms_dx;
188*55106Storek 		fe->time = time;
189*55106Storek 		ADVANCE;
190*55106Storek 		ms->ms_dx = 0;
191*55106Storek 	}
192*55106Storek 	if (ms->ms_dy) {
193*55106Storek 		NEXT;
194*55106Storek 		fe->id = LOC_Y_DELTA;
195*55106Storek 		fe->value = ms->ms_dy;
196*55106Storek 		fe->time = time;
197*55106Storek 		ADVANCE;
198*55106Storek 		ms->ms_dy = 0;
199*55106Storek 	}
200*55106Storek out:
201*55106Storek 	if (any) {
202*55106Storek 		ms->ms_ub = ub;
203*55106Storek 		ms->ms_events.ev_put = put;
204*55106Storek 		EV_WAKEUP(&ms->ms_events);
205*55106Storek 	}
206*55106Storek }
207*55106Storek 
208*55106Storek int
209*55106Storek msopen(dev, flags, mode, p)
210*55106Storek 	dev_t dev;
211*55106Storek 	int flags, mode;
212*55106Storek 	struct proc *p;
213*55106Storek {
214*55106Storek 	int s, error;
215*55106Storek 
216*55106Storek 	if (ms_softc.ms_events.ev_io)
217*55106Storek 		return (EBUSY);
218*55106Storek 	ms_softc.ms_events.ev_io = p;
219*55106Storek 	ev_init(&ms_softc.ms_events);	/* may cause sleep */
220*55106Storek 	ms_softc.ms_ready = 1;		/* start accepting events */
221*55106Storek 	(*ms_softc.ms_open)(ms_softc.ms_mouse);
222*55106Storek 	return (0);
223*55106Storek }
224*55106Storek 
225*55106Storek int
226*55106Storek msclose(dev, flags, mode, p)
227*55106Storek 	dev_t dev;
228*55106Storek 	int flags, mode;
229*55106Storek 	struct proc *p;
230*55106Storek {
231*55106Storek 
232*55106Storek 	ms_softc.ms_ready = 0;		/* stop accepting events */
233*55106Storek 	ev_fini(&ms_softc.ms_events);
234*55106Storek 	(*ms_softc.ms_close)(ms_softc.ms_mouse);
235*55106Storek 	ms_softc.ms_events.ev_io = NULL;
236*55106Storek 	return (0);
237*55106Storek }
238*55106Storek 
239*55106Storek int
240*55106Storek msread(dev, uio, flags)
241*55106Storek 	dev_t dev;
242*55106Storek 	struct uio *uio;
243*55106Storek 	int flags;
244*55106Storek {
245*55106Storek 
246*55106Storek 	return (ev_read(&ms_softc.ms_events, uio, flags));
247*55106Storek }
248*55106Storek 
249*55106Storek /* this routine should not exist, but is convenient to write here for now */
250*55106Storek int
251*55106Storek mswrite(dev, uio, flags)
252*55106Storek 	dev_t dev;
253*55106Storek 	struct uio *uio;
254*55106Storek 	int flags;
255*55106Storek {
256*55106Storek 
257*55106Storek 	return (EOPNOTSUPP);
258*55106Storek }
259*55106Storek 
260*55106Storek int
261*55106Storek msioctl(dev, cmd, data, flag, p)
262*55106Storek 	dev_t dev;
263*55106Storek 	int cmd;
264*55106Storek 	register caddr_t data;
265*55106Storek 	int flag;
266*55106Storek 	struct proc *p;
267*55106Storek {
268*55106Storek 	int s;
269*55106Storek 
270*55106Storek 	switch (cmd) {
271*55106Storek 
272*55106Storek 	case FIONBIO:		/* we will remove this someday (soon???) */
273*55106Storek 		return (0);
274*55106Storek 
275*55106Storek 	case FIOASYNC:
276*55106Storek 		ms_softc.ms_events.ev_async = *(int *)data != 0;
277*55106Storek 		return (0);
278*55106Storek 
279*55106Storek 	case TIOCSPGRP:
280*55106Storek 		if (*(int *)data != ms_softc.ms_events.ev_io->p_pgid)
281*55106Storek 			return (EPERM);
282*55106Storek 		return (0);
283*55106Storek 
284*55106Storek 	case VUIDGFORMAT:
285*55106Storek 		/* we only do firm_events */
286*55106Storek 		*(int *)data = VUID_FIRM_EVENT;
287*55106Storek 		return (0);
288*55106Storek 
289*55106Storek 	case VUIDSFORMAT:
290*55106Storek 		if (*(int *)data != VUID_FIRM_EVENT)
291*55106Storek 			return (EINVAL);
292*55106Storek 		return (0);
293*55106Storek 	}
294*55106Storek 	return (ENOTTY);
295*55106Storek }
296*55106Storek 
297*55106Storek int
298*55106Storek msselect(dev, rw, p)
299*55106Storek 	dev_t dev;
300*55106Storek 	int rw;
301*55106Storek 	struct proc *p;
302*55106Storek {
303*55106Storek 
304*55106Storek 	return (ev_select(&ms_softc.ms_events, rw, p));
305*55106Storek }
306