ms.c revision 1.9 1 1.9 is /* $NetBSD: ms.c,v 1.9 1996/04/24 11:41:16 is Exp $ */
2 1.5 cgd
3 1.1 mw /*
4 1.1 mw * based on:
5 1.1 mw *
6 1.1 mw * Copyright (c) 1992, 1993
7 1.1 mw * The Regents of the University of California. All rights reserved.
8 1.1 mw *
9 1.1 mw * This software was developed by the Computer Systems Engineering group
10 1.1 mw * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11 1.1 mw * contributed to Berkeley.
12 1.1 mw *
13 1.1 mw * All advertising materials mentioning features or use of this software
14 1.1 mw * must display the following acknowledgement:
15 1.1 mw * This product includes software developed by the University of
16 1.1 mw * California, Lawrence Berkeley Laboratory.
17 1.1 mw *
18 1.1 mw * Redistribution and use in source and binary forms, with or without
19 1.1 mw * modification, are permitted provided that the following conditions
20 1.1 mw * are met:
21 1.1 mw * 1. Redistributions of source code must retain the above copyright
22 1.1 mw * notice, this list of conditions and the following disclaimer.
23 1.1 mw * 2. Redistributions in binary form must reproduce the above copyright
24 1.1 mw * notice, this list of conditions and the following disclaimer in the
25 1.1 mw * documentation and/or other materials provided with the distribution.
26 1.1 mw * 3. All advertising materials mentioning features or use of this software
27 1.1 mw * must display the following acknowledgement:
28 1.1 mw * This product includes software developed by the University of
29 1.1 mw * California, Berkeley and its contributors.
30 1.1 mw * 4. Neither the name of the University nor the names of its contributors
31 1.1 mw * may be used to endorse or promote products derived from this software
32 1.1 mw * without specific prior written permission.
33 1.1 mw *
34 1.1 mw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35 1.1 mw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36 1.1 mw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37 1.1 mw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38 1.1 mw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39 1.1 mw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40 1.1 mw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41 1.1 mw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42 1.1 mw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43 1.1 mw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 1.1 mw * SUCH DAMAGE.
45 1.1 mw *
46 1.1 mw * @(#)ms.c 8.1 (Berkeley) 6/11/93
47 1.1 mw *
48 1.5 cgd * Header: ms.c,v 1.5 92/11/26 01:28:47 torek Exp (LBL)
49 1.1 mw */
50 1.1 mw
51 1.1 mw /*
52 1.1 mw * Mouse driver.
53 1.1 mw */
54 1.1 mw
55 1.2 chopps #include <sys/param.h>
56 1.9 is #include <sys/device.h>
57 1.2 chopps #include <sys/ioctl.h>
58 1.2 chopps #include <sys/kernel.h>
59 1.2 chopps #include <sys/proc.h>
60 1.2 chopps #include <sys/syslog.h>
61 1.2 chopps #include <sys/systm.h>
62 1.2 chopps #include <sys/tty.h>
63 1.8 veego #include <sys/signalvar.h>
64 1.1 mw
65 1.2 chopps #include <amiga/dev/event_var.h>
66 1.2 chopps #include <amiga/dev/vuid_event.h>
67 1.1 mw
68 1.2 chopps #include <amiga/amiga/custom.h>
69 1.2 chopps #include <amiga/amiga/cia.h>
70 1.9 is #include <amiga/amiga/device.h>
71 1.1 mw
72 1.8 veego #include <sys/conf.h>
73 1.8 veego #include <machine/conf.h>
74 1.8 veego
75 1.9 is void msattach __P((struct device *, struct device *, void *));
76 1.9 is int msmatch __P((struct device *, void *, void *));
77 1.1 mw
78 1.3 chopps void msintr __P((void *));
79 1.3 chopps void ms_enable __P((dev_t));
80 1.3 chopps void ms_disable __P((dev_t));
81 1.9 is
82 1.9 is struct ms_softc {
83 1.9 is struct device sc_dev;
84 1.9 is
85 1.9 is u_char ms_horc; /* horizontal counter on last scan */
86 1.9 is u_char ms_verc; /* vertical counter on last scan */
87 1.9 is char ms_mb; /* mouse button state */
88 1.9 is char ms_ub; /* user button state */
89 1.9 is int ms_dx; /* delta-x */
90 1.9 is int ms_dy; /* delta-y */
91 1.9 is volatile int ms_ready; /* event queue is ready */
92 1.9 is struct evvar ms_events; /* event queue state */
93 1.9 is };
94 1.9 is
95 1.9 is struct cfattach ms_ca = {
96 1.9 is sizeof(struct ms_softc), msmatch, msattach
97 1.9 is };
98 1.9 is
99 1.9 is struct cfdriver ms_cd = {
100 1.9 is NULL, "ms", DV_DULL, NULL, 0
101 1.9 is };
102 1.1 mw
103 1.3 chopps int
104 1.9 is msmatch(pdp, match, auxp)
105 1.9 is struct device *pdp;
106 1.9 is void *match, *auxp;
107 1.3 chopps {
108 1.9 is struct cfdata *cfp = (struct cfdata *)match;
109 1.9 is
110 1.9 is if (matchname((char *)auxp, "ms") &&
111 1.9 is cfp->cf_unit >= 0 && cfp->cf_unit <= 1) /* only two units */
112 1.9 is return 1;
113 1.9 is
114 1.9 is return 0;
115 1.3 chopps }
116 1.1 mw
117 1.9 is
118 1.9 is void
119 1.9 is msattach(pdp, dp, auxp)
120 1.9 is struct device *pdp, *dp;
121 1.9 is void *auxp;
122 1.9 is {
123 1.9 is printf("\n");
124 1.9 is }
125 1.9 is
126 1.9 is
127 1.3 chopps /*
128 1.3 chopps * Amiga mice are hooked up to one of the two "game" ports, where
129 1.3 chopps * the main mouse is usually on the first port, and port 2 can
130 1.3 chopps * be used by a joystick. Nevertheless, we support two mouse
131 1.3 chopps * devices, /dev/mouse0 and /dev/mouse1 (with a link of /dev/mouse to
132 1.3 chopps * the device that represents the port of the mouse in use).
133 1.3 chopps */
134 1.1 mw
135 1.3 chopps /*
136 1.3 chopps * enable scanner, called when someone opens the device.
137 1.3 chopps * Assume caller already validated range of dev.
138 1.3 chopps */
139 1.1 mw void
140 1.3 chopps ms_enable(dev)
141 1.3 chopps dev_t dev;
142 1.1 mw {
143 1.3 chopps struct ms_softc *ms;
144 1.1 mw
145 1.9 is ms = (struct ms_softc *)getsoftc(ms_cd, minor(dev));
146 1.3 chopps /*
147 1.3 chopps * use this as flag to the "interrupt" to tell it when to
148 1.3 chopps * shut off (when it's reset to 0).
149 1.3 chopps */
150 1.3 chopps ms->ms_ready = 1;
151 1.1 mw
152 1.3 chopps timeout(msintr, (void *)minor(dev), 2);
153 1.1 mw }
154 1.1 mw
155 1.3 chopps /*
156 1.3 chopps * disable scanner. Just set ms_ready to 0, and after the next
157 1.3 chopps * timeout taken, no further timeouts will be initiated.
158 1.3 chopps */
159 1.1 mw void
160 1.3 chopps ms_disable(dev)
161 1.3 chopps dev_t dev;
162 1.1 mw {
163 1.3 chopps struct ms_softc *ms;
164 1.3 chopps int s;
165 1.1 mw
166 1.9 is ms = (struct ms_softc *)getsoftc(ms_cd, minor(dev));
167 1.3 chopps s = splhigh ();
168 1.3 chopps ms->ms_ready = 0;
169 1.3 chopps /*
170 1.3 chopps * sync with the interrupt
171 1.3 chopps */
172 1.3 chopps tsleep(ms, PZERO - 1, "mouse-disable", 0);
173 1.3 chopps splx(s);
174 1.1 mw }
175 1.1 mw
176 1.1 mw
177 1.3 chopps /*
178 1.3 chopps * we're emulating a mousesystems serial mouse here..
179 1.3 chopps */
180 1.1 mw void
181 1.3 chopps msintr(arg)
182 1.3 chopps void *arg;
183 1.1 mw {
184 1.3 chopps static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 };
185 1.3 chopps static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT };
186 1.3 chopps struct ms_softc *ms;
187 1.3 chopps struct firm_event *fe;
188 1.3 chopps int mb, ub, d, get, put, any, unit;
189 1.3 chopps u_char pra, *horc, *verc;
190 1.3 chopps u_short pot, count;
191 1.3 chopps short dx, dy;
192 1.3 chopps
193 1.3 chopps unit = (int)arg;
194 1.9 is ms = (struct ms_softc *)getsoftc(ms_cd, unit);
195 1.3 chopps horc = ((u_char *) &count) + 1;
196 1.3 chopps verc = (u_char *) &count;
197 1.3 chopps
198 1.3 chopps /*
199 1.3 chopps * first read the three buttons.
200 1.3 chopps */
201 1.3 chopps pot = custom.potgor;
202 1.3 chopps pra = ciaa.pra;
203 1.3 chopps pot >>= unit == 0 ? 8 : 12; /* contains right and middle button */
204 1.3 chopps pra >>= unit == 0 ? 6 : 7; /* contains left button */
205 1.3 chopps mb = (pot & 4) / 4 + (pot & 1) * 2 + (pra & 1) * 4;
206 1.3 chopps mb ^= 0x07;
207 1.3 chopps
208 1.3 chopps /*
209 1.3 chopps * read current values of counter registers
210 1.3 chopps */
211 1.3 chopps if (unit == 0)
212 1.3 chopps count = custom.joy0dat;
213 1.3 chopps else
214 1.3 chopps count = custom.joy1dat;
215 1.1 mw
216 1.3 chopps /*
217 1.3 chopps * take care of wraparound
218 1.3 chopps */
219 1.3 chopps dx = *horc - ms->ms_horc;
220 1.3 chopps if (dx < -127)
221 1.3 chopps dx += 255;
222 1.3 chopps else if (dx > 127)
223 1.3 chopps dx -= 255;
224 1.3 chopps dy = *verc - ms->ms_verc;
225 1.3 chopps if (dy < -127)
226 1.3 chopps dy += 255;
227 1.3 chopps else if (dy > 127)
228 1.3 chopps dy -= 255;
229 1.3 chopps
230 1.3 chopps /*
231 1.3 chopps * remember current values for next scan
232 1.3 chopps */
233 1.3 chopps ms->ms_horc = *horc;
234 1.3 chopps ms->ms_verc = *verc;
235 1.3 chopps
236 1.3 chopps ms->ms_dx = dx;
237 1.3 chopps ms->ms_dy = dy;
238 1.3 chopps ms->ms_mb = mb;
239 1.1 mw
240 1.3 chopps if (dx || dy || ms->ms_ub != ms->ms_mb) {
241 1.3 chopps /*
242 1.3 chopps * We have at least one event (mouse button, delta-X, or
243 1.3 chopps * delta-Y; possibly all three, and possibly three separate
244 1.3 chopps * button events). Deliver these events until we are out of
245 1.3 chopps * changes or out of room. As events get delivered, mark them
246 1.3 chopps * `unchanged'.
247 1.3 chopps */
248 1.3 chopps any = 0;
249 1.3 chopps get = ms->ms_events.ev_get;
250 1.3 chopps put = ms->ms_events.ev_put;
251 1.3 chopps fe = &ms->ms_events.ev_q[put];
252 1.3 chopps
253 1.3 chopps mb = ms->ms_mb;
254 1.3 chopps ub = ms->ms_ub;
255 1.3 chopps while ((d = mb ^ ub) != 0) {
256 1.3 chopps /*
257 1.3 chopps * Mouse button change. Convert up to three changes
258 1.3 chopps * to the `first' change, and drop it into the event
259 1.3 chopps * queue.
260 1.3 chopps */
261 1.3 chopps if ((++put) % EV_QSIZE == get) {
262 1.3 chopps put--;
263 1.3 chopps goto out;
264 1.3 chopps }
265 1.3 chopps
266 1.3 chopps d = to_one[d - 1]; /* from 1..7 to {1,2,4} */
267 1.3 chopps fe->id = to_id[d - 1]; /* from {1,2,4} to ID */
268 1.3 chopps fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
269 1.3 chopps fe->time = time;
270 1.3 chopps fe++;
271 1.3 chopps
272 1.3 chopps if (put >= EV_QSIZE) {
273 1.3 chopps put = 0;
274 1.3 chopps fe = &ms->ms_events.ev_q[0];
275 1.3 chopps }
276 1.3 chopps any = 1;
277 1.3 chopps
278 1.3 chopps ub ^= d;
279 1.3 chopps }
280 1.3 chopps if (ms->ms_dx) {
281 1.3 chopps if ((++put) % EV_QSIZE == get) {
282 1.3 chopps put--;
283 1.3 chopps goto out;
284 1.3 chopps }
285 1.3 chopps
286 1.3 chopps fe->id = LOC_X_DELTA;
287 1.3 chopps fe->value = ms->ms_dx;
288 1.3 chopps fe->time = time;
289 1.4 chopps fe++;
290 1.3 chopps
291 1.3 chopps if (put >= EV_QSIZE) {
292 1.3 chopps put = 0;
293 1.3 chopps fe = &ms->ms_events.ev_q[0];
294 1.3 chopps }
295 1.3 chopps any = 1;
296 1.3 chopps
297 1.3 chopps ms->ms_dx = 0;
298 1.3 chopps }
299 1.3 chopps if (ms->ms_dy) {
300 1.3 chopps if ((++put) % EV_QSIZE == get) {
301 1.3 chopps put--;
302 1.3 chopps goto out;
303 1.3 chopps }
304 1.3 chopps
305 1.3 chopps fe->id = LOC_Y_DELTA;
306 1.3 chopps fe->value = ms->ms_dy;
307 1.3 chopps fe->time = time;
308 1.4 chopps fe++;
309 1.3 chopps
310 1.3 chopps if (put >= EV_QSIZE) {
311 1.3 chopps put = 0;
312 1.3 chopps fe = &ms->ms_events.ev_q[0];
313 1.3 chopps }
314 1.3 chopps any = 1;
315 1.1 mw
316 1.3 chopps ms->ms_dy = 0;
317 1.3 chopps }
318 1.1 mw out:
319 1.3 chopps if (any) {
320 1.3 chopps ms->ms_ub = ub;
321 1.3 chopps ms->ms_events.ev_put = put;
322 1.3 chopps EV_WAKEUP(&ms->ms_events);
323 1.3 chopps }
324 1.1 mw }
325 1.1 mw
326 1.3 chopps /*
327 1.3 chopps * reschedule handler, or if terminating,
328 1.3 chopps * handshake with ms_disable
329 1.3 chopps */
330 1.3 chopps if (ms->ms_ready)
331 1.3 chopps timeout(msintr, (void *)unit, 2);
332 1.3 chopps else
333 1.3 chopps wakeup(ms);
334 1.1 mw }
335 1.1 mw
336 1.1 mw int
337 1.3 chopps msopen(dev, flags, mode, p)
338 1.3 chopps dev_t dev;
339 1.3 chopps int flags, mode;
340 1.3 chopps struct proc *p;
341 1.1 mw {
342 1.3 chopps struct ms_softc *ms;
343 1.8 veego int unit;
344 1.3 chopps
345 1.3 chopps unit = minor(dev);
346 1.9 is ms = (struct ms_softc *)getsoftc(ms_cd, unit);
347 1.3 chopps
348 1.9 is if (ms == NULL)
349 1.3 chopps return(EXDEV);
350 1.3 chopps
351 1.3 chopps if (ms->ms_events.ev_io)
352 1.3 chopps return(EBUSY);
353 1.3 chopps
354 1.3 chopps ms->ms_events.ev_io = p;
355 1.3 chopps ev_init(&ms->ms_events); /* may cause sleep */
356 1.3 chopps ms_enable(dev);
357 1.3 chopps return(0);
358 1.1 mw }
359 1.1 mw
360 1.1 mw int
361 1.3 chopps msclose(dev, flags, mode, p)
362 1.3 chopps dev_t dev;
363 1.3 chopps int flags, mode;
364 1.3 chopps struct proc *p;
365 1.1 mw {
366 1.3 chopps int unit;
367 1.3 chopps struct ms_softc *ms;
368 1.1 mw
369 1.3 chopps unit = minor (dev);
370 1.9 is ms = (struct ms_softc *)getsoftc(ms_cd, unit);
371 1.3 chopps
372 1.3 chopps ms_disable(dev);
373 1.3 chopps ev_fini(&ms->ms_events);
374 1.3 chopps ms->ms_events.ev_io = NULL;
375 1.3 chopps return(0);
376 1.1 mw }
377 1.1 mw
378 1.1 mw int
379 1.3 chopps msread(dev, uio, flags)
380 1.3 chopps dev_t dev;
381 1.3 chopps struct uio *uio;
382 1.3 chopps int flags;
383 1.1 mw {
384 1.3 chopps struct ms_softc *ms;
385 1.1 mw
386 1.9 is ms = (struct ms_softc *)getsoftc(ms_cd, minor(dev));
387 1.3 chopps return(ev_read(&ms->ms_events, uio, flags));
388 1.1 mw }
389 1.1 mw
390 1.1 mw int
391 1.3 chopps msioctl(dev, cmd, data, flag, p)
392 1.6 chopps dev_t dev;
393 1.6 chopps u_long cmd;
394 1.6 chopps register caddr_t data;
395 1.6 chopps int flag;
396 1.6 chopps struct proc *p;
397 1.1 mw {
398 1.3 chopps struct ms_softc *ms;
399 1.3 chopps int unit;
400 1.1 mw
401 1.3 chopps unit = minor(dev);
402 1.9 is ms = (struct ms_softc *)getsoftc(ms_cd, unit);
403 1.1 mw
404 1.3 chopps switch (cmd) {
405 1.3 chopps case FIONBIO: /* we will remove this someday (soon???) */
406 1.3 chopps return(0);
407 1.3 chopps case FIOASYNC:
408 1.3 chopps ms->ms_events.ev_async = *(int *)data != 0;
409 1.3 chopps return(0);
410 1.3 chopps case TIOCSPGRP:
411 1.3 chopps if (*(int *)data != ms->ms_events.ev_io->p_pgid)
412 1.3 chopps return(EPERM);
413 1.3 chopps return(0);
414 1.3 chopps case VUIDGFORMAT: /* we only do firm_events */
415 1.3 chopps *(int *)data = VUID_FIRM_EVENT;
416 1.3 chopps return(0);
417 1.3 chopps case VUIDSFORMAT:
418 1.3 chopps if (*(int *)data != VUID_FIRM_EVENT)
419 1.3 chopps return(EINVAL);
420 1.3 chopps return(0);
421 1.3 chopps }
422 1.3 chopps return(ENOTTY);
423 1.1 mw }
424 1.1 mw
425 1.1 mw int
426 1.3 chopps msselect(dev, rw, p)
427 1.3 chopps dev_t dev;
428 1.3 chopps int rw;
429 1.3 chopps struct proc *p;
430 1.1 mw {
431 1.3 chopps struct ms_softc *ms;
432 1.1 mw
433 1.9 is ms = (struct ms_softc *)getsoftc(ms_cd, minor(dev));
434 1.3 chopps return(ev_select(&ms->ms_events, rw, p));
435 1.1 mw }
436