xref: /csrg-svn/sys/sparc/dev/ms.c (revision 63318)
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