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