ms.c revision 1.4 1 /* $NetBSD: ms.c,v 1.4 1997/10/12 06:42:18 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 cdev_decl(ms);
88
89 void ms_serial __P((struct tty *, void(*)(struct tty *),
90 void(*)(struct tty *)));
91 void ms_modem __P((int));
92 void ms_rint __P((int));
93 void mouseattach __P((void));
94
95 /*
96 * Attach the mouse serial (down-link) interface.
97 * Do we need to set it to 4800 baud, 8 bits?
98 * Test by power cycling and not booting Human68k before BSD?
99 */
100 void
101 ms_serial(tp, iopen, iclose)
102 struct tty *tp;
103 void (*iopen) __P((struct tty *));
104 void (*iclose) __P((struct tty *));
105 {
106
107 ms_softc.ms_mouse = tp;
108 ms_softc.ms_open = iopen;
109 ms_softc.ms_close = iclose;
110 }
111
112 void
113 ms_modem(onoff)
114 register int onoff;
115 {
116 static int oonoff;
117
118 if (ms_softc.ms_ready == 1) {
119 if (ms_softc.ms_byteno == -1)
120 ms_softc.ms_byteno = onoff = 0;
121 if (oonoff != onoff) {
122 zs_msmodem(onoff);
123 oonoff = onoff;
124 }
125 }
126 }
127
128 void
129 ms_rint(c)
130 register int c;
131 {
132 register struct firm_event *fe;
133 register struct ms_softc *ms = &ms_softc;
134 register int mb, ub, d, get, put, any;
135 static const char to_one[] = { 1, 2, 3 };
136 static const int to_id[] = { MS_LEFT, MS_RIGHT, MS_MIDDLE };
137
138 /*
139 * Discard input if not ready. Drop sync on parity or framing
140 * error; gain sync on button byte.
141 */
142 if (ms->ms_ready == 0)
143 return;
144 if (c & (TTY_FE|TTY_PE)) {
145 log(LOG_WARNING,
146 "mouse input parity or framing error (0x%x)\n", c);
147 ms->ms_byteno = -1;
148 return;
149 }
150
151 /*
152 * Run the decode loop, adding to the current information.
153 * We add, rather than replace, deltas, so that if the event queue
154 * fills, we accumulate data for when it opens up again.
155 */
156 switch (ms->ms_byteno) {
157
158 case -1:
159 return;
160
161 case 0:
162 /* buttons */
163 ms->ms_byteno = 1;
164 ms->ms_mb = c & 0x7;
165 return;
166
167 case 1:
168 /* delta-x */
169 ms->ms_byteno = 2;
170 ms->ms_dx += (char)c;
171 return;
172
173 case 2:
174 /* delta-y */
175 ms->ms_byteno = -1 /* wait for button-byte again */;
176 ms->ms_dy += (char)c;
177 break;
178
179 default:
180 panic("ms_rint");
181 /* NOTREACHED */
182 }
183
184 /*
185 * We have at least one event (mouse button, delta-X, or
186 * delta-Y; possibly all three, and possibly three separate
187 * button events). Deliver these events until we are out
188 * of changes or out of room. As events get delivered,
189 * mark them `unchanged'.
190 */
191 any = 0;
192 get = ms->ms_events.ev_get;
193 put = ms->ms_events.ev_put;
194 fe = &ms->ms_events.ev_q[put];
195
196 /* NEXT prepares to put the next event, backing off if necessary */
197 #define NEXT \
198 if ((++put) % EV_QSIZE == get) { \
199 put--; \
200 goto out; \
201 }
202 /* ADVANCE completes the `put' of the event */
203 #define ADVANCE \
204 fe++; \
205 if (put >= EV_QSIZE) { \
206 put = 0; \
207 fe = &ms->ms_events.ev_q[0]; \
208 } \
209 any = 1
210
211 mb = ms->ms_mb;
212 ub = ms->ms_ub;
213 while ((d = mb ^ ub) != 0) {
214 /*
215 * Mouse button change. Convert up to three changes
216 * to the `first' change, and drop it into the event queue.
217 */
218 NEXT;
219 d = to_one[d - 1]; /* from 1..7 to {1,2,4} */
220 fe->id = to_id[d - 1]; /* from {1,2,4} to ID */
221 fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
222 fe->time = time;
223 ADVANCE;
224 ub ^= d;
225 }
226 if (ms->ms_dx) {
227 NEXT;
228 fe->id = LOC_X_DELTA;
229 fe->value = ms->ms_dx;
230 fe->time = time;
231 ADVANCE;
232 ms->ms_dx = 0;
233 }
234 if (ms->ms_dy) {
235 NEXT;
236 fe->id = LOC_Y_DELTA;
237 fe->value = -ms->ms_dy; /* XXX? */
238 fe->time = time;
239 ADVANCE;
240 ms->ms_dy = 0;
241 }
242 out:
243 if (any) {
244 ms->ms_ub = ub;
245 ms->ms_events.ev_put = put;
246 EV_WAKEUP(&ms->ms_events);
247 }
248 }
249
250 int
251 msopen(dev, flags, mode, p)
252 dev_t dev;
253 int flags, mode;
254 struct proc *p;
255 {
256 if (ms_softc.ms_events.ev_io)
257 return (EBUSY);
258 ms_softc.ms_events.ev_io = p;
259 ev_init(&ms_softc.ms_events); /* may cause sleep */
260 ms_softc.ms_ready = 1; /* start accepting events */
261 (*ms_softc.ms_open)(ms_softc.ms_mouse);
262 return (0);
263 }
264 int
265 msclose(dev, flags, mode, p)
266 dev_t dev;
267 int flags, mode;
268 struct proc *p;
269 {
270
271 ms_modem(0);
272 ms_softc.ms_ready = 0; /* stop accepting events */
273 ev_fini(&ms_softc.ms_events);
274 (*ms_softc.ms_close)(ms_softc.ms_mouse);
275 ms_softc.ms_events.ev_io = NULL;
276 return (0);
277 }
278
279 int
280 msread(dev, uio, flags)
281 dev_t dev;
282 struct uio *uio;
283 int flags;
284 {
285
286 return (ev_read(&ms_softc.ms_events, uio, flags));
287 }
288
289 /* this routine should not exist, but is convenient to write here for now */
290 int
291 mswrite(dev, uio, flags)
292 dev_t dev;
293 struct uio *uio;
294 int flags;
295 {
296
297 return (EOPNOTSUPP);
298 }
299
300 int
301 msioctl(dev, cmd, data, flag, p)
302 dev_t dev;
303 u_long cmd;
304 register caddr_t data;
305 int flag;
306 struct proc *p;
307 {
308 switch (cmd) {
309
310 case FIONBIO: /* we will remove this someday (soon???) */
311 return (0);
312
313 case FIOASYNC:
314 ms_softc.ms_events.ev_async = *(int *)data != 0;
315 return (0);
316
317 case TIOCSPGRP:
318 if (*(int *)data != ms_softc.ms_events.ev_io->p_pgid)
319 return (EPERM);
320 return (0);
321
322 case VUIDGFORMAT:
323 /* we only do firm_events */
324 *(int *)data = VUID_FIRM_EVENT;
325 return (0);
326
327 case VUIDSFORMAT:
328 if (*(int *)data != VUID_FIRM_EVENT)
329 return (EINVAL);
330 return (0);
331 }
332 return (ENOTTY);
333 }
334
335 int
336 mspoll(dev, events, p)
337 dev_t dev;
338 int events;
339 struct proc *p;
340 {
341
342 return (ev_poll(&ms_softc.ms_events, events, p));
343 }
344
345 void
346 mouseattach(){} /* XXX pseudo-device */
347