1 /*
2 * Mach Operating System
3 * Copyright (c) 1992 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: dtop_handlers.c,v $
29 * Revision 2.8 93/05/15 19:37:47 mrt
30 * machparam.h -> machspl.h
31 *
32 * Revision 2.7 93/05/10 20:07:30 rvb
33 * No more sys/types.h
34 * [93/05/06 09:55:58 af]
35 *
36 * Revision 2.6 93/01/14 17:15:42 danner
37 * My attempt at DO-key finessing.
38 * [92/12/14 af]
39 * Proper spl typing.
40 * [92/11/30 af]
41 *
42 * Throw away the kdb hot key from the keyboard input buffer if
43 * lk201_input returned -2. This prevents bogus autorepeat of the
44 * hot key and bogus kdb interrupts.
45 * [92/10/24 jvh]
46 *
47 * Revision 2.5 92/05/22 15:47:38 jfriedl
48 * Got autorepeat to work under X11: just generate two events
49 * (up+down) instead of the single metronome one that would
50 * not really work.
51 * [92/05/20 22:43:35 af]
52 *
53 * Revision 2.3.1.1 92/05/04 14:16:54 af
54 * Fixed to not call autorepeat when invoked from debugger.
55 * It might be too early (e.g. boothowto=0xc) for timeout().
56 * [92/05/04 af]
57 *
58 * Revision 2.3 92/03/05 17:08:21 rpd
59 * Changed locators handler to always pass relative coords
60 * to screen_motion_event.
61 * [92/03/05 af]
62 *
63 * Revision 2.2 92/03/02 18:32:22 rpd
64 * Created from DEC specs:
65 * "DESKTOPinterconnect Description and Protocol Specification"
66 * Version 0.9, Jun 17 1991
67 * "Open Desktop Bus, Locator Device Protocol Specification"
68 * Version 0.4, Dec 13 1990
69 * "Open Desktop Bus, Keyboard Device Protocol Specification"
70 * Version 0.7, Jan 9 1991
71 * [92/01/19 af]
72 *
73 */
74 /*
75 * File: dtop_handlers.c
76 * Author: Alessandro Forin, Carnegie Mellon University
77 * Date: 1/92
78 *
79 * Handler functions for devices attached to the DESKTOP bus.
80 */
81
82 #include <dtop.h>
83 #if NDTOP > 0
84
85 #include <mach_kdb.h>
86
87 #include <machine/machspl.h> /* spl definitions */
88 #include <mach/std_types.h>
89 #include <device/io_req.h>
90 #include <device/tty.h>
91
92 #include <chips/busses.h>
93 #include <chips/serial_defs.h>
94 #include <chips/screen_defs.h>
95 #include <mips/PMAX/tc.h>
96
97 #include <chips/dtop.h>
98 #include <chips/lk201.h>
99
100 /*
101 * Default handler function
102 */
103 int
104 dtop_null_device_handler(
105 dtop_device_t dev,
106 dtop_message_t msg,
107 int event,
108 unsigned char outc)
109 {
110 /* See if the message was to the default address (powerup) */
111
112 /* Uhmm, donno how to handle this. Drop it */
113 if (event == DTOP_EVENT_RECEIVE_PACKET)
114 dev->unknown_report = *msg;
115 return 0;
116 }
117
118 /*
119 * Handler for locator devices (mice)
120 */
121 int
122 dtop_locator_handler(
123 dtop_device_t dev,
124 dtop_message_t msg,
125 int event,
126 unsigned char outc)
127 {
128 register unsigned short buttons;
129 register short coord;
130 #if BYTE_MSF
131 # define get_short(b0,b1) (((b1)<<8)|(b0))
132 #else
133 # define get_short(b0,b1) (((b0)<<8)|(b1))
134 #endif
135
136 /*
137 * Do the position first
138 */
139 {
140 register int i;
141 register boolean_t moved;
142 int delta_coords[L_COORD_MAX];
143
144 /*
145 * Get all coords, see if it moved at all (buttons!)
146 */
147 moved = FALSE;
148 for (i = 0; i < dev->locator.n_coords; i++) {
149
150 coord = get_short(msg->body[2+(i<<1)],
151 msg->body[3+(i<<1)]);
152
153 if (dev->locator.relative) {
154 /*
155 * Flame on
156 * I am getting tired of this, why do they have to
157 * keep this bug around ? Religion ? Damn, they
158 * design a keyboard for X11 use and forget the mouse ?
159 * Flame off
160 */
161 #define BOGUS_DEC_X_AXIS
162 #ifdef BOGUS_DEC_X_AXIS
163 if (i == 1) coord = - coord;
164 #endif /* BOGUS_DEC_X_AXIS */
165 /* dev->locator.coordinate[i] += coord; */
166 } else {
167 register unsigned int old_coord;
168
169 old_coord = dev->locator.coordinate[i];
170 dev->locator.coordinate[i] = coord;
171 coord = old_coord - coord;
172 }
173 delta_coords[i] = coord;
174 if (coord != 0)
175 moved = TRUE;
176 }
177 if (moved) {
178 /* scale and threshold done higher up */
179 screen_motion_event( 0,
180 dev->locator.type,
181 delta_coords[0],
182 delta_coords[1]);
183 }
184 }
185
186 /*
187 * Time for the buttons now
188 */
189 #define new_buttons coord
190 new_buttons = get_short(msg->body[0],msg->body[1]);
191 buttons = new_buttons ^ dev->locator.prev_buttons;
192 if (buttons) {
193 register int i, type;
194
195 dev->locator.prev_buttons = new_buttons;
196 for (i = 0; buttons; i++, buttons >>= 1) {
197
198 if ((buttons & 1) == 0) continue;
199
200 type = (new_buttons & (1<<i)) ?
201 EVT_BUTTON_DOWN : EVT_BUTTON_UP;
202 screen_keypress_event( 0,
203 dev->locator.type,
204 dev->locator.button_code[i],
205 type);
206 }
207 }
208 #undef new_buttons
209 }
210
211 /*
212 * Handler for keyboard devices
213 * Special case: outc set for recv packet means
214 * we are inside the kernel debugger
215 */
216 int
217 dtop_keyboard_handler(
218 dtop_device_t dev,
219 dtop_message_t msg,
220 int event,
221 unsigned char outc)
222 {
223 char save[11];
224 register int msg_len, c;
225
226 /*
227 * Well, really this code handles just an lk401 and in
228 * a very primitive way at that. Should at least emulate
229 * an lk201 decently, and make that a pluggable module.
230 * Sigh.
231 */
232
233 if (event != DTOP_EVENT_RECEIVE_PACKET) {
234 switch (event) {
235 case DTOP_EVENT_POLL:
236 {
237 register unsigned int t, t0;
238
239 /*
240 * Note we will always have at least the
241 * end-of-list marker present (a zero)
242 * Here stop and trigger of autorepeat.
243 * Do not repeat shift keys, either.
244 */
245 {
246 register unsigned char uc, i = 0;
247
248 rpt_char:
249 uc = dev->keyboard.last_codes[i];
250
251 if (uc == DTOP_KBD_EMPTY) {
252 dev->keyboard.k_ar_state = K_AR_OFF;
253 return 0;
254 }
255 if ((uc >= LK_R_SHIFT) && (uc <= LK_R_ALT)) {
256 /* sometimes swapped. Grrr. */
257 if (++i < dev->keyboard.last_codes_count)
258 goto rpt_char;
259 dev->keyboard.k_ar_state = K_AR_OFF;
260 return 0;
261 }
262 c = uc;
263 }
264
265 /*
266 * Got a char. See if enough time from stroke,
267 * or from last repeat.
268 */
269 t0 = (dev->keyboard.k_ar_state == K_AR_TRIGGER) ? 30 : 500;
270 t = approx_time_in_msec();
271 if ((t - dev->keyboard.last_msec) < t0)
272 return 0;
273
274 dev->keyboard.k_ar_state = K_AR_TRIGGER;
275
276 /*
277 * Simplest thing to do is to mimic lk201
278 */
279 outc = lk201_input(0, LK_REPEAT);
280 if ( ! screen_keypress_event( 0,
281 DEV_KEYBD,
282 c,
283 EVT_BUTTON_UP)) {
284 if (outc > 0) cons_input(0, outc, 0);
285 } else
286 screen_keypress_event( 0,
287 DEV_KEYBD,
288 c,
289 EVT_BUTTON_DOWN);
290 return 0;
291 }
292 default: gimmeabreak();/*fornow*/
293 }
294 return -1;
295 }
296
297 msg_len = msg->code.val.len;
298
299 /* Check for errors */
300 c = msg->body[0];
301 if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) {
302 printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]);
303 if (c != DTOP_KBD_OUT_ERR) return -1;
304 /* spec sez if scan list overflow still there is data */
305 msg->body[0] = 0;
306 }
307
308 dev->keyboard.last_msec = approx_time_in_msec();
309
310 switch (dev->keyboard.k_ar_state) {
311 case K_AR_IDLE:
312 /* if from debugger, timeouts might not be working yet */
313 if (outc == 0xff)
314 break;
315 dtop_keyboard_autorepeat( dev );
316 /* fall through */
317 case K_AR_TRIGGER:
318 dev->keyboard.k_ar_state = K_AR_ACTIVE;
319 break;
320 case K_AR_ACTIVE:
321 break;
322 case K_AR_OFF: gimmeabreak(); /* ??? */
323 dev->keyboard.k_ar_state = K_AR_IDLE;
324 }
325
326 /*
327 * We can only assume that pressed keys are reported in the
328 * same order (a minimum of sanity, please) across scans.
329 * To make things readable, do a first pass cancelling out
330 * all keys that are still pressed, and a second one generating
331 * events. While generating events, do the upstrokes first
332 * from oldest to youngest, then the downstrokes from oldest
333 * to youngest. This copes with lost packets and provides
334 * a reasonable model even if scans are too slow.
335 */
336
337 /* make a copy of new state first */
338 {
339 register char *p, *q, *e;
340
341 p = save;
342 q = (char*)msg->body;
343 e = (char*)&msg->body[msg_len];
344
345 while (q < e)
346 *p++ = *q++;
347 }
348
349 /*
350 * Do the cancelling pass
351 */
352 {
353 register char *ls, *le, *ns, *ne, *sync;
354
355 ls = (char*)dev->keyboard.last_codes;
356 le = (char*)&dev->keyboard.last_codes[dev->keyboard.last_codes_count];
357 ns = (char*)msg->body;
358 ne = (char*)&msg->body[msg_len];
359
360 /* sync marks where to restart scanning, saving
361 time thanks to ordering constraints */
362 for (sync = ns; ls < le; ls++) {
363 register char c = *ls;
364 for (ns = sync; ns < ne; ns++)
365 if (c == *ns) {
366 *ls = *ns = 0;
367 sync = ns + 1;
368 break;
369 }
370 /* we could already tell if c is an upstroke,
371 but see the above discussion about errors */
372 }
373 }
374 /*
375 * Now generate all upstrokes
376 */
377 {
378 register char *ls, *le;
379 register unsigned char c;
380
381 le = (char*)dev->keyboard.last_codes;
382 ls = (char*)&dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1];
383
384 for ( ; ls >= le; ls--)
385 if (c = *ls) {
386 /* keep kernel notion of lk201 state consistent */
387 (void) lk201_input(0,c);
388
389 if (outc == 0)
390 screen_keypress_event(0,
391 DEV_KEYBD,
392 c,
393 EVT_BUTTON_UP);
394 }
395 }
396 /*
397 * And finally the downstrokes
398 */
399 {
400 register char *ns, *ne, c, retc;
401
402 ne = (char*)msg->body;
403 ns = (char*)&msg->body[msg_len - 1];
404 retc = 0;
405
406 for ( ; ns >= ne; ns--)
407 if (c = *ns) {
408 register unsigned char data;
409
410 data = c;
411 c = lk201_input(0, data);
412
413 if (c == -2) { /* just returned from kdb */
414 /* NOTE: many things have happened while
415 we were sitting on the stack, now it
416 is last_codes that holds the truth */
417 #if 1
418 /* But the truth might not be welcome.
419 If we get out because we hit RETURN
420 on the rconsole line all is well,
421 but if we did it from the keyboard
422 we get here on the downstroke. Then
423 we will get the upstroke which we
424 would give to X11. People complained
425 about this extra keypress.. so they
426 lose everything. */
427
428 dev->keyboard.last_codes_count = 1;
429 dev->keyboard.last_codes[0] = 0;
430 #endif
431 return -1;
432 }
433
434 /*
435 * If X11 had better code for the keyboard this
436 * would be an EVT_BUTTON_DOWN. But that would
437 * screwup the REPEAT function. Grrr.
438 */
439 /* outc non zero sez we are in the debugger */
440 if (outc == 0) {
441 if (screen_keypress_event(0,
442 DEV_KEYBD,
443 data,
444 EVT_BUTTON_DOWN))
445 c = -1; /* consumed by X */
446 else
447 if (c > 0) cons_input(0, c, 0);
448 }
449 /* return the xlated keycode anyways */
450 if ((c > 0) && (retc == 0))
451 retc = c;
452 }
453 outc = retc;
454 }
455 /* install new scan state */
456 {
457 register char *p, *q, *e;
458
459 p = (char*)dev->keyboard.last_codes;
460 q = (char*)save;
461 e = (char*)&save[msg_len];
462
463 while (q < e)
464 *p++ = *q++;
465 dev->keyboard.last_codes_count = msg_len;
466 }
467 return outc;
468 }
469
470 /*
471 * Polled operations: we must do autorepeat by hand. Sigh.
472 */
473 dtop_keyboard_autorepeat(
474 dtop_device_t dev)
475 {
476 spl_t s = spltty();
477
478 if (dev->keyboard.k_ar_state != K_AR_IDLE)
479 dtop_keyboard_handler( dev, 0, DTOP_EVENT_POLL, 0);
480
481 if (dev->keyboard.k_ar_state == K_AR_OFF)
482 dev->keyboard.k_ar_state = K_AR_IDLE;
483 else
484 timeout( dtop_keyboard_autorepeat, dev, dev->keyboard.poll_frequency);
485
486 splx(s);
487 }
488
489 #endif /*NDTOP>0*/
Cache object: a5221c4c18ee02db8d7e2c38b93ff9a0
|