ms.c revision 1.2 1 /* $NetBSD: ms.c,v 1.2 1996/05/21 15:32:31 oki Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by the University of
27 * California, Berkeley and its contributors.
28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * SUCH DAMAGE.
43 *
44 * @(#)ms.c 8.1 (Berkeley) 6/11/93
45 */
46
47 /*
48 * Mouse driver.
49 */
50
51 #include <sys/param.h>
52 #include <sys/conf.h>
53 #include <sys/ioctl.h>
54 #include <sys/kernel.h>
55 #include <sys/proc.h>
56 #include <sys/syslog.h>
57 #include <sys/systm.h>
58 #include <sys/tty.h>
59
60 #include <x68k/dev/event_var.h>
61 #include <machine/vuid_event.h>
62
63 #include <x68k/x68k/iodevice.h>
64
65 /*
66 * Mouse state. A SHARP X1/X680x0 mouse is a fairly simple device,
67 * producing three-byte blobs of the form:
68 *
69 * b dx dy
70 *
71 * where b is the button state, encoded as 0x80|(buttons)---there are
72 * two buttons (2=left, 1=right)---and dx,dy are X and Y delta values.
73 */
74 struct ms_softc {
75 short ms_byteno; /* input byte number, for decode */
76 char ms_mb; /* mouse button state */
77 char ms_ub; /* user button state */
78 int ms_dx; /* delta-x */
79 int ms_dy; /* delta-y */
80 struct tty *ms_mouse; /* downlink for output to mouse */
81 void (*ms_open) __P((struct tty *)); /* enable dataflow */
82 void (*ms_close) __P((struct tty *));/* disable dataflow */
83 volatile int ms_ready; /* event queue is ready */
84 struct evvar ms_events; /* event queue state */
85 } ms_softc;
86
87 /*
88 * Attach the mouse serial (down-link) interface.
89 * Do we need to set it to 4800 baud, 8 bits?
90 * Test by power cycling and not booting Human68k before BSD?
91 */
92 void
93 ms_serial(tp, iopen, iclose)
94 struct tty *tp;
95 void (*iopen)(), (*iclose)();
96 {
97
98 ms_softc.ms_mouse = tp;
99 ms_softc.ms_open = iopen;
100 ms_softc.ms_close = iclose;
101 }
102
103 void
104 ms_modem(onoff)
105 register int onoff;
106 {
107 static int oonoff;
108
109 if (ms_softc.ms_ready == 1) {
110 if (ms_softc.ms_byteno == -1)
111 ms_softc.ms_byteno = onoff = 0;
112 if (oonoff != onoff) {
113 zs_msmodem(onoff);
114 oonoff = onoff;
115 }
116 }
117 }
118
119 void
120 ms_rint(c)
121 register int c;
122 {
123 register struct firm_event *fe;
124 register struct ms_softc *ms = &ms_softc;
125 register int mb, ub, d, get, put, any;
126 static const char to_one[] = { 1, 2, 3 };
127 static const int to_id[] = { MS_LEFT, MS_RIGHT, MS_MIDDLE };
128
129 /*
130 * Discard input if not ready. Drop sync on parity or framing
131 * error; gain sync on button byte.
132 */
133 if (ms->ms_ready == 0)
134 return;
135 if (c & (TTY_FE|TTY_PE)) {
136 log(LOG_WARNING,
137 "mouse input parity or framing error (0x%x)\n", c);
138 ms->ms_byteno = -1;
139 return;
140 }
141
142 /*
143 * Run the decode loop, adding to the current information.
144 * We add, rather than replace, deltas, so that if the event queue
145 * fills, we accumulate data for when it opens up again.
146 */
147 switch (ms->ms_byteno) {
148
149 case -1:
150 return;
151
152 case 0:
153 /* buttons */
154 ms->ms_byteno = 1;
155 ms->ms_mb = c & 0x7;
156 return;
157
158 case 1:
159 /* delta-x */
160 ms->ms_byteno = 2;
161 ms->ms_dx += (char)c;
162 return;
163
164 case 2:
165 /* delta-y */
166 ms->ms_byteno = -1 /* wait for button-byte again */;
167 ms->ms_dy += (char)c;
168 break;
169
170 default:
171 panic("ms_rint");
172 /* NOTREACHED */
173 }
174
175 /*
176 * We have at least one event (mouse button, delta-X, or
177 * delta-Y; possibly all three, and possibly three separate
178 * button events). Deliver these events until we are out
179 * of changes or out of room. As events get delivered,
180 * mark them `unchanged'.
181 */
182 any = 0;
183 get = ms->ms_events.ev_get;
184 put = ms->ms_events.ev_put;
185 fe = &ms->ms_events.ev_q[put];
186
187 /* NEXT prepares to put the next event, backing off if necessary */
188 #define NEXT \
189 if ((++put) % EV_QSIZE == get) { \
190 put--; \
191 goto out; \
192 }
193 /* ADVANCE completes the `put' of the event */
194 #define ADVANCE \
195 fe++; \
196 if (put >= EV_QSIZE) { \
197 put = 0; \
198 fe = &ms->ms_events.ev_q[0]; \
199 } \
200 any = 1
201
202 mb = ms->ms_mb;
203 ub = ms->ms_ub;
204 while ((d = mb ^ ub) != 0) {
205 /*
206 * Mouse button change. Convert up to three changes
207 * to the `first' change, and drop it into the event queue.
208 */
209 NEXT;
210 d = to_one[d - 1]; /* from 1..7 to {1,2,4} */
211 fe->id = to_id[d - 1]; /* from {1,2,4} to ID */
212 fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
213 fe->time = time;
214 ADVANCE;
215 ub ^= d;
216 }
217 if (ms->ms_dx) {
218 NEXT;
219 fe->id = LOC_X_DELTA;
220 fe->value = ms->ms_dx;
221 fe->time = time;
222 ADVANCE;
223 ms->ms_dx = 0;
224 }
225 if (ms->ms_dy) {
226 NEXT;
227 fe->id = LOC_Y_DELTA;
228 fe->value = -ms->ms_dy; /* XXX? */
229 fe->time = time;
230 ADVANCE;
231 ms->ms_dy = 0;
232 }
233 out:
234 if (any) {
235 ms->ms_ub = ub;
236 ms->ms_events.ev_put = put;
237 EV_WAKEUP(&ms->ms_events);
238 }
239 }
240
241 int
242 msopen(dev, flags, mode, p)
243 dev_t dev;
244 int flags, mode;
245 struct proc *p;
246 {
247 if (ms_softc.ms_events.ev_io)
248 return (EBUSY);
249 ms_softc.ms_events.ev_io = p;
250 ev_init(&ms_softc.ms_events); /* may cause sleep */
251 ms_softc.ms_ready = 1; /* start accepting events */
252 (*ms_softc.ms_open)(ms_softc.ms_mouse);
253 return (0);
254 }
255 int
256 msclose(dev, flags, mode, p)
257 dev_t dev;
258 int flags, mode;
259 struct proc *p;
260 {
261
262 ms_modem(0);
263 ms_softc.ms_ready = 0; /* stop accepting events */
264 ev_fini(&ms_softc.ms_events);
265 (*ms_softc.ms_close)(ms_softc.ms_mouse);
266 ms_softc.ms_events.ev_io = NULL;
267 return (0);
268 }
269
270 int
271 msread(dev, uio, flags)
272 dev_t dev;
273 struct uio *uio;
274 int flags;
275 {
276
277 return (ev_read(&ms_softc.ms_events, uio, flags));
278 }
279
280 /* this routine should not exist, but is convenient to write here for now */
281 int
282 mswrite(dev, uio, flags)
283 dev_t dev;
284 struct uio *uio;
285 int flags;
286 {
287
288 return (EOPNOTSUPP);
289 }
290
291 int
292 msioctl(dev, cmd, data, flag, p)
293 dev_t dev;
294 u_long cmd;
295 register caddr_t data;
296 int flag;
297 struct proc *p;
298 {
299 switch (cmd) {
300
301 case FIONBIO: /* we will remove this someday (soon???) */
302 return (0);
303
304 case FIOASYNC:
305 ms_softc.ms_events.ev_async = *(int *)data != 0;
306 return (0);
307
308 case TIOCSPGRP:
309 if (*(int *)data != ms_softc.ms_events.ev_io->p_pgid)
310 return (EPERM);
311 return (0);
312
313 case VUIDGFORMAT:
314 /* we only do firm_events */
315 *(int *)data = VUID_FIRM_EVENT;
316 return (0);
317
318 case VUIDSFORMAT:
319 if (*(int *)data != VUID_FIRM_EVENT)
320 return (EINVAL);
321 return (0);
322 }
323 return (ENOTTY);
324 }
325
326 int
327 msselect(dev, rw, p)
328 dev_t dev;
329 int rw;
330 struct proc *p;
331 {
332
333 return (ev_select(&ms_softc.ms_events, rw, p));
334 }
335
336 void
337 mouseattach(){} /* XXX pseudo-device */
338