ms.c revision 1.5 1 /* $NetBSD: ms.c,v 1.5 1996/04/12 08:39:22 leo Exp $ */
2
3 /*
4 * Copyright (c) 1995 Leo Weppelman.
5 * All rights reserved.
6 *
7 * based on:
8 *
9 * Copyright (c) 1992, 1993
10 * The Regents of the University of California. All rights reserved.
11 *
12 * This software was developed by the Computer Systems Engineering group
13 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
14 * contributed to Berkeley.
15 *
16 * All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Lawrence Berkeley Laboratory.
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 * 3. All advertising materials mentioning features or use of this software
30 * must display the following acknowledgement:
31 * This product includes software developed by the University of
32 * California, Berkeley and its contributors.
33 * 4. Neither the name of the University nor the names of its contributors
34 * may be used to endorse or promote products derived from this software
35 * without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 *
49 * @(#)ms.c 8.1 (Berkeley) 6/11/93
50 *
51 * Header: ms.c,v 1.5 92/11/26 01:28:47 torek Exp (LBL)
52 */
53
54 /*
55 * Mouse driver.
56 */
57
58 #include <sys/param.h>
59 #include <sys/conf.h>
60 #include <sys/ioctl.h>
61 #include <sys/kernel.h>
62 #include <sys/proc.h>
63 #include <sys/systm.h>
64 #include <sys/tty.h>
65 #include <sys/signalvar.h>
66
67 #include <machine/msioctl.h>
68 #include <atari/dev/event_var.h>
69 #include <atari/dev/vuid_event.h>
70 #include <atari/dev/kbdvar.h>
71 #include <atari/dev/msvar.h>
72
73 #include "mouse.h"
74 #if NMOUSE > 0
75
76 /* there's really no more physical ports on an atari. */
77 #if NMOUSE > 1
78 #undef NMOUSE
79 #define NMOUSE 1
80 #endif
81
82 typedef void (*FPV) __P((void *));
83
84 static struct ms_softc ms_softc[NMOUSE];
85
86 dev_type_open(msopen);
87 dev_type_close(msclose);
88 dev_type_read(msread);
89 dev_type_ioctl(msioctl);
90 dev_type_select(msselect);
91
92 static void ms_3b_delay __P((struct ms_softc *));
93
94 int
95 mouseattach(cnt)
96 int cnt;
97 {
98 printf("1 mouse configured\n");
99 ms_softc[0].ms_emul3b = 1;
100 return(NMOUSE);
101 }
102
103 static void
104 ms_3b_delay(ms)
105 struct ms_softc *ms;
106 {
107 REL_MOUSE rel_ms;
108
109 rel_ms.id = TIMEOUT_ID;
110 rel_ms.dx = rel_ms.dy = 0;
111 mouse_soft(&rel_ms, sizeof(rel_ms), KBD_TIMEO_PKG);
112 }
113 /*
114 * Note that we are called from the keyboard software interrupt!
115 */
116 void
117 mouse_soft(rel_ms, size, type)
118 REL_MOUSE *rel_ms;
119 int size, type;
120 {
121 struct ms_softc *ms = &ms_softc[0];
122 struct firm_event *fe, *fe2;
123 REL_MOUSE fake_mouse;
124 int get, put;
125 int sps;
126 u_char mbut, bmask;
127 int flush_buttons;
128
129 if (ms->ms_events.ev_io == NULL)
130 return;
131
132 switch (type) {
133 case KBD_JOY1_PKG:
134 /*
135 * There are some mice that have their middle button
136 * wired to the 'up' bit of joystick 1....
137 * Simulate a mouse packet with dx = dy = 0, the middle
138 * button state set by UP and the other buttons unchanged.
139 * Flush all button changes.
140 */
141 flush_buttons = 1;
142 fake_mouse.id = (rel_ms->dx & 1 ? 4 : 0) | (ms->ms_buttons & 3);
143 fake_mouse.dx = fake_mouse.dy = 0;
144 rel_ms = &fake_mouse;
145 break;
146 case KBD_TIMEO_PKG:
147 /*
148 * Timeout package. No button changes and no movement.
149 * Flush all button changes.
150 */
151 flush_buttons = 1;
152 fake_mouse.id = ms->ms_buttons;
153 fake_mouse.dx = fake_mouse.dy = 0;
154 rel_ms = &fake_mouse;
155 break;
156 case KBD_RMS_PKG:
157 /*
158 * Normal mouse package. Always copy the middle button
159 * status. The emulation code decides if button changes
160 * must be flushed.
161 */
162 rel_ms->id = (ms->ms_buttons & 4) | (rel_ms->id & 3);
163 flush_buttons = (ms->ms_emul3b) ? 0 : 1;
164 break;
165 default:
166 return;
167 }
168
169 sps = splev();
170 get = ms->ms_events.ev_get;
171 put = ms->ms_events.ev_put;
172 fe = &ms->ms_events.ev_q[put];
173
174 if ((type != KBD_TIMEO_PKG) && ms->ms_emul3b && ms->ms_bq_idx)
175 untimeout((FPV)ms_3b_delay, (void *)ms);
176
177 /*
178 * Button states are encoded in the lower 3 bits of 'id'
179 */
180 if (!(mbut = (rel_ms->id ^ ms->ms_buttons)) && (put != get)) {
181 /*
182 * Compact dx/dy messages. Always generate an event when
183 * a button is pressed or the event queue is empty.
184 */
185 ms->ms_dx += rel_ms->dx;
186 ms->ms_dy += rel_ms->dy;
187 goto out;
188 }
189 rel_ms->dx += ms->ms_dx;
190 rel_ms->dy += ms->ms_dy;
191 ms->ms_dx = ms->ms_dy = 0;
192
193 /*
194 * Output location events _before_ button events ie. make sure
195 * the button is pressed at the correct location.
196 */
197 if (rel_ms->dx) {
198 if ((++put) % EV_QSIZE == get) {
199 put--;
200 goto out;
201 }
202 fe->id = LOC_X_DELTA;
203 fe->value = rel_ms->dx;
204 fe->time = time;
205 if (put >= EV_QSIZE) {
206 put = 0;
207 fe = &ms->ms_events.ev_q[0];
208 }
209 else fe++;
210 }
211 if (rel_ms->dy) {
212 if ((++put) % EV_QSIZE == get) {
213 put--;
214 goto out;
215 }
216 fe->id = LOC_Y_DELTA;
217 fe->value = rel_ms->dy;
218 fe->time = time;
219 if (put >= EV_QSIZE) {
220 put = 0;
221 fe = &ms->ms_events.ev_q[0];
222 }
223 else fe++;
224 }
225 if (mbut && (type != KBD_TIMEO_PKG)) {
226 for (bmask = 1; bmask < 0x08; bmask <<= 1) {
227 if (!(mbut & bmask))
228 continue;
229 fe2 = &ms->ms_bq[ms->ms_bq_idx++];
230 if (bmask == 1)
231 fe2->id = MS_RIGHT;
232 else if (bmask == 2)
233 fe2->id = MS_LEFT;
234 else fe2->id = MS_MIDDLE;
235 fe2->value = rel_ms->id & bmask ? VKEY_DOWN : VKEY_UP;
236 fe2->time = time;
237 }
238 }
239
240 /*
241 * Handle 3rd button emulation.
242 */
243 if (ms->ms_emul3b && ms->ms_bq_idx && (type != KBD_TIMEO_PKG)) {
244 /*
245 * If the middle button is pressed, any change to
246 * one of the other buttons releases all.
247 */
248 if ((ms->ms_buttons & 4) && (mbut & 3)) {
249 ms->ms_bq[0].id = MS_MIDDLE;
250 ms->ms_bq_idx = 1;
251 rel_ms->id = 0;
252 flush_buttons = 1;
253 goto out;
254 }
255 if (ms->ms_bq_idx == 2) {
256 if (ms->ms_bq[0].value == ms->ms_bq[1].value) {
257 /* Must be 2 button presses! */
258 ms->ms_bq[0].id = MS_MIDDLE;
259 ms->ms_bq_idx = 1;
260 rel_ms->id = 7;
261 }
262 }
263 else if (ms->ms_bq[0].value == VKEY_DOWN) {
264 timeout((FPV)ms_3b_delay, (void *)ms, 10);
265 goto out;
266 }
267 flush_buttons = 1;
268 }
269 out:
270 if (flush_buttons) {
271 int i;
272
273 for (i = 0; i < ms->ms_bq_idx; i++) {
274 if ((++put) % EV_QSIZE == get) {
275 ms->ms_bq_idx = 0;
276 put--;
277 goto out;
278 }
279 *fe = ms->ms_bq[i];
280 if (put >= EV_QSIZE) {
281 put = 0;
282 fe = &ms->ms_events.ev_q[0];
283 }
284 else fe++;
285 }
286 ms->ms_bq_idx = 0;
287 }
288 ms->ms_events.ev_put = put;
289 ms->ms_buttons = rel_ms->id;
290 splx(sps);
291 EV_WAKEUP(&ms->ms_events);
292 }
293
294 int
295 msopen(dev, flags, mode, p)
296 dev_t dev;
297 int flags, mode;
298 struct proc *p;
299 {
300 u_char report_ms_joy[] = { 0x14, 0x08 };
301 struct ms_softc *ms;
302 int unit;
303
304 unit = minor(dev);
305 ms = &ms_softc[unit];
306
307 if (unit >= NMOUSE)
308 return(EXDEV);
309
310 if (ms->ms_events.ev_io)
311 return(EBUSY);
312
313 ms->ms_events.ev_io = p;
314 ms->ms_dx = ms->ms_dy = 0;
315 ms->ms_buttons = 0;
316 ms->ms_bq[0].id = ms->ms_bq[1].id = 0;
317 ms->ms_bq_idx = 0;
318 ev_init(&ms->ms_events); /* may cause sleep */
319
320 /*
321 * Enable mouse reporting.
322 */
323 kbd_write(report_ms_joy, sizeof(report_ms_joy));
324 return(0);
325 }
326
327 int
328 msclose(dev, flags, mode, p)
329 dev_t dev;
330 int flags, mode;
331 struct proc *p;
332 {
333 u_char disable_ms_joy[] = { 0x12, 0x1a };
334 int unit;
335 struct ms_softc *ms;
336
337 unit = minor (dev);
338 ms = &ms_softc[unit];
339
340 /*
341 * Turn off mouse interrogation.
342 */
343 kbd_write(disable_ms_joy, sizeof(disable_ms_joy));
344 ev_fini(&ms->ms_events);
345 ms->ms_events.ev_io = NULL;
346 return(0);
347 }
348
349 int
350 msread(dev, uio, flags)
351 dev_t dev;
352 struct uio *uio;
353 int flags;
354 {
355 struct ms_softc *ms;
356
357 ms = &ms_softc[minor(dev)];
358 return(ev_read(&ms->ms_events, uio, flags));
359 }
360
361 int
362 msioctl(dev, cmd, data, flag, p)
363 dev_t dev;
364 u_long cmd;
365 register caddr_t data;
366 int flag;
367 struct proc *p;
368 {
369 struct ms_softc *ms;
370 int unit;
371
372 unit = minor(dev);
373 ms = &ms_softc[unit];
374
375 switch (cmd) {
376 case MIOCS3B_EMUL:
377 ms->ms_emul3b = (*(int *)data != 0) ? 1 : 0;
378 return (0);
379 case MIOCG3B_EMUL:
380 *(int *)data = ms->ms_emul3b;
381 return (0);
382 case FIONBIO: /* we will remove this someday (soon???) */
383 return(0);
384 case FIOASYNC:
385 ms->ms_events.ev_async = *(int *)data != 0;
386 return(0);
387 case TIOCSPGRP:
388 if (*(int *)data != ms->ms_events.ev_io->p_pgid)
389 return(EPERM);
390 return(0);
391 case VUIDGFORMAT: /* we only do firm_events */
392 *(int *)data = VUID_FIRM_EVENT;
393 return(0);
394 case VUIDSFORMAT:
395 if (*(int *)data != VUID_FIRM_EVENT)
396 return(EINVAL);
397 return(0);
398 }
399 return(ENOTTY);
400 }
401
402 int
403 msselect(dev, rw, p)
404 dev_t dev;
405 int rw;
406 struct proc *p;
407 {
408 struct ms_softc *ms;
409
410 ms = &ms_softc[minor(dev)];
411 return(ev_select(&ms->ms_events, rw, p));
412 }
413 #endif /* NMOUSE > 0 */
414