1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ralph Campbell and Rick Macklem.
7 *
8 * %sccs.include.redist.c%
9 *
10 * @(#)dtop.c 8.3 (Berkeley) 06/02/95
11 */
12
13 /*
14 * Mach Operating System
15 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
16 * All Rights Reserved.
17 *
18 * Permission to use, copy, modify and distribute this software and its
19 * documentation is hereby granted, provided that both the copyright
20 * notice and this permission notice appear in all copies of the
21 * software, derivative works or modified versions, and any portions
22 * thereof, and that both notices appear in supporting documentation.
23 *
24 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
25 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
26 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27 *
28 * Carnegie Mellon requests users of this software to return to
29 *
30 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
31 * School of Computer Science
32 * Carnegie Mellon University
33 * Pittsburgh PA 15213-3890
34 *
35 * any improvements or extensions that they make and grant Carnegie the
36 * rights to redistribute these changes.
37 */
38 /*
39 * Author: Alessandro Forin, Carnegie Mellon University
40 *
41 * Hardware-level operations for the Desktop serial line
42 * bus (i2c aka ACCESS).
43 */
44 /************************************************************
45 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
46 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
47
48 All Rights Reserved
49
50 Permission to use, copy, modify, and distribute this software and its
51 documentation for any purpose and without fee is hereby granted,
52 provided that the above copyright notice appear in all copies and that
53 both that copyright notice and this permission notice appear in
54 supporting documentation, and that the names of Digital or MIT not be
55 used in advertising or publicity pertaining to distribution of the
56 software without specific, written prior permission.
57
58 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
59 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
60 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
61 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
62 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
63 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
64 SOFTWARE.
65
66 ********************************************************/
67
68 #include <dtop.h>
69 #if NDTOP > 0
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/ioctl.h>
73 #include <sys/tty.h>
74 #include <sys/proc.h>
75 #include <sys/map.h>
76 #include <sys/buf.h>
77 #include <sys/conf.h>
78 #include <sys/file.h>
79 #include <sys/uio.h>
80 #include <sys/kernel.h>
81 #include <sys/syslog.h>
82
83 #include <machine/pmioctl.h>
84 #include <machine/machConst.h>
85 #include <machine/dc7085cons.h>
86
87 #include <pmax/pmax/pmaxtype.h>
88 #include <pmax/pmax/maxine.h>
89 #include <pmax/pmax/asic.h>
90
91 #include <pmax/dev/device.h>
92 #include <pmax/dev/dtopreg.h>
93 #include <pmax/dev/fbreg.h>
94
95 extern int pmax_boardtype;
96
97 void dtop_keyboard_repeat __P((void *));
98 int dtop_null_device_handler __P((dtop_device_t, dtop_message_t, int, int));
99 int dtop_locator_handler __P((dtop_device_t, dtop_message_t, int, int));
100 int dtop_keyboard_handler __P((dtop_device_t, dtop_message_t, int, int));
101 int dtopparam __P((struct tty *, struct termios *));
102 int dtopstop __P((struct tty *, int));
103 void dtopstart __P((struct tty *));
104 void dtopKBDPutc __P((dev_t, int));
105
106 struct tty dtop_tty[NDTOP];
107 void (*dtopDivertXInput)(); /* X windows keyboard input routine */
108 void (*dtopMouseEvent)(); /* X windows mouse motion event routine */
109 void (*dtopMouseButtons)(); /* X windows mouse buttons event routine */
110
111 #define DTOP_MAX_POLL 0x7fff /* about half a sec */
112
113 typedef volatile unsigned int *data_reg_t; /* uC */
114 #define DTOP_GET_BYTE(data) (((*(data)) >> 8) & 0xff)
115 #define DTOP_PUT_BYTE(data,c) { *(data) = (c) << 8; }
116
117 typedef volatile unsigned int *poll_reg_t; /* SIR */
118 #define DTOP_RX_AVAIL(poll) (*(poll) & 1)
119 #define DTOP_TX_AVAIL(poll) (*(poll) & 2)
120
121 #define GET_SHORT(b0,b1) (((b0)<<8)|(b1))
122
123 /*
124 * Driver status
125 */
126 struct dtop_softc {
127 data_reg_t data;
128 poll_reg_t poll;
129 char polling_mode;
130 char probed_once;
131 short bad_pkts;
132
133 struct dtop_ds {
134 int (*handler)();
135 dtop_device status;
136 } device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1];
137
138 # define DTOP_DEVICE_NO(address) (((address)-DTOP_ADDR_FIRST)>>1)
139
140 } dtop_softc[NDTOP];
141
142 typedef struct dtop_softc *dtop_softc_t;
143 struct tty dtop_tty[NDTOP];
144
145 /*
146 * lk201 keyboard divisions and up/down mode key bitmap.
147 */
148 #define NUMDIVS 14
149 static u_char divbeg[NUMDIVS] = {0xbf, 0x91, 0xbc, 0xbd, 0xb0, 0xad, 0xa6,
150 0xa9, 0x88, 0x56, 0x63, 0x6f, 0x7b, 0x7e};
151 static u_char divend[NUMDIVS] = {0xff, 0xa5, 0xbc, 0xbe, 0xb2, 0xaf, 0xa8,
152 0xac, 0x90, 0x62, 0x6e, 0x7a, 0x7d, 0x87};
153 /*
154 * Initial defaults, groups 5 and 6 are up/down
155 */
156 static u_long keymodes[8] = {0, 0, 0, 0, 0, 0x0003e000, 0, 0};
157
158 /*
159 * Definition of the driver for the auto-configuration program.
160 */
161 int dtopprobe();
162 void dtopintr();
163 struct driver dtopdriver = {
164 "dtop", dtopprobe, 0, 0, dtopintr,
165 };
166
167 dtopprobe(cp)
168 struct pmax_ctlr *cp;
169 {
170 register struct tty *tp;
171 register int cntr;
172 int dtopunit = cp->pmax_unit, i, s;
173 dtop_softc_t dtop;
174
175 if (dtopunit >= NDTOP)
176 return (0);
177 if (badaddr(cp->pmax_addr, 2))
178 return (0);
179 dtop = &dtop_softc[dtopunit];
180
181 dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
182 dtop->data = (data_reg_t)cp->pmax_addr;
183
184 for (i = 0; i < DTOP_MAX_DEVICES; i++)
185 dtop->device[i].handler = dtop_null_device_handler;
186
187 /* a lot more needed here, fornow: */
188 dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler;
189 dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler;
190 dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state =
191 K_AR_IDLE;
192
193 dtop->probed_once = 1;
194 printf("dtop%d at nexus0 csr 0x%x priority %d\n",
195 cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
196 return (1);
197 }
198
dtopopen(dev,flag,mode,p)199 dtopopen(dev, flag, mode, p)
200 dev_t dev;
201 int flag, mode;
202 struct proc *p;
203 {
204 register struct tty *tp;
205 register int unit;
206 int s, error = 0;
207
208 unit = minor(dev);
209 if (unit >= NDTOP)
210 return (ENXIO);
211 tp = &dtop_tty[unit];
212 tp->t_oproc = dtopstart;
213 tp->t_param = dtopparam;
214 tp->t_dev = dev;
215 if ((tp->t_state & TS_ISOPEN) == 0) {
216 tp->t_state |= TS_WOPEN;
217 ttychars(tp);
218 if (tp->t_ispeed == 0) {
219 tp->t_iflag = TTYDEF_IFLAG;
220 tp->t_oflag = TTYDEF_OFLAG;
221 tp->t_cflag = TTYDEF_CFLAG;
222 tp->t_lflag = TTYDEF_LFLAG;
223 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
224 }
225 (void) dtopparam(tp, &tp->t_termios);
226 ttsetwater(tp);
227 } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
228 return (EBUSY);
229 s = spltty();
230 while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
231 !(tp->t_state & TS_CARR_ON)) {
232 tp->t_state |= TS_WOPEN;
233 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
234 ttopen, 0))
235 break;
236 }
237 splx(s);
238 if (error)
239 return (error);
240 error = (*linesw[tp->t_line].l_open)(dev, tp);
241 return (error);
242 }
243
244 /*ARGSUSED*/
dtopclose(dev,flag,mode,p)245 dtopclose(dev, flag, mode, p)
246 dev_t dev;
247 int flag, mode;
248 struct proc *p;
249 {
250 register struct tty *tp;
251 register int unit;
252
253 unit = minor(dev);
254 tp = &dtop_tty[unit];
255 (*linesw[tp->t_line].l_close)(tp, flag);
256 return (ttyclose(tp));
257 }
258
dtopread(dev,uio,flag)259 dtopread(dev, uio, flag)
260 dev_t dev;
261 struct uio *uio;
262 {
263 register struct tty *tp;
264
265 tp = &dtop_tty[minor(dev)];
266 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
267 }
268
dtopwrite(dev,uio,flag)269 dtopwrite(dev, uio, flag)
270 dev_t dev;
271 struct uio *uio;
272 {
273 register struct tty *tp;
274
275 tp = &dtop_tty[minor(dev)];
276 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
277 }
278
279 /*ARGSUSED*/
dtopioctl(dev,cmd,data,flag,p)280 dtopioctl(dev, cmd, data, flag, p)
281 dev_t dev;
282 u_long cmd;
283 caddr_t data;
284 int flag;
285 struct proc *p;
286 {
287 register struct tty *tp;
288 register int unit = minor(dev);
289 int error;
290
291 tp = &dtop_tty[unit];
292 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
293 if (error >= 0)
294 return (error);
295 error = ttioctl(tp, cmd, data, flag);
296 if (error >= 0)
297 return (error);
298
299 switch (cmd) {
300
301 case TIOCSBRK:
302 ttyoutput(0, tp);
303 break;
304
305 case TIOCCBRK:
306 ttyoutput(0, tp);
307 break;
308
309 case TIOCMGET:
310 *(int *)data = DML_DTR | DML_DSR | DML_CAR;
311 break;
312
313 default:
314 return (ENOTTY);
315 }
316 return (0);
317 }
318
319 /*
320 * Interrupt routine
321 */
322 void
dtopintr(unit)323 dtopintr(unit)
324 int unit;
325 {
326 dtop_message msg;
327 int devno;
328 dtop_softc_t dtop;
329
330 dtop = &dtop_softc[unit];
331 if (dtop_get_packet(dtop, &msg) < 0) {
332 #ifdef DIAGNOSTIC
333 printf("dtop: overrun (or stray)\n");
334 #endif
335 /*
336 * Ugh! The most common occurrence of a data overrun is upon a
337 * key press and the result is a software generated "stuck key".
338 * All I can think to do is fake an "all keys up" whenever a
339 * data overrun occurs.
340 */
341 msg.src_address = 0x6c;
342 msg.code.val.len = 1;
343 msg.body[0] = DTOP_KBD_EMPTY;
344 }
345
346 /*
347 * If not probed yet, just throw the data away.
348 */
349 if (!dtop->probed_once)
350 return;
351
352 devno = DTOP_DEVICE_NO(msg.src_address);
353 if (devno < 0 || devno > 15)
354 return;
355 (void) (*dtop->device[devno].handler)
356 (&dtop->device[devno].status, &msg,
357 DTOP_EVENT_RECEIVE_PACKET, 0);
358 }
359
360 void
dtopstart(tp)361 dtopstart(tp)
362 register struct tty *tp;
363 {
364 register int cc;
365 int s;
366
367 s = spltty();
368 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
369 goto out;
370 if (tp->t_outq.c_cc <= tp->t_lowat) {
371 if (tp->t_state & TS_ASLEEP) {
372 tp->t_state &= ~TS_ASLEEP;
373 wakeup((caddr_t)&tp->t_outq);
374 }
375 selwakeup(&tp->t_wsel);
376 }
377 if (tp->t_outq.c_cc == 0)
378 goto out;
379 /* handle console specially */
380 if (tp == dtop_tty) {
381 while (tp->t_outq.c_cc > 0) {
382 cc = getc(&tp->t_outq) & 0x7f;
383 cnputc(cc);
384 }
385 /*
386 * After we flush the output queue we may need to wake
387 * up the process that made the output.
388 */
389 if (tp->t_outq.c_cc <= tp->t_lowat) {
390 if (tp->t_state & TS_ASLEEP) {
391 tp->t_state &= ~TS_ASLEEP;
392 wakeup((caddr_t)&tp->t_outq);
393 }
394 selwakeup(&tp->t_wsel);
395 }
396 }
397 out:
398 splx(s);
399 }
400
401 void
dtopKBDPutc(dev,c)402 dtopKBDPutc(dev, c)
403 dev_t dev;
404 int c;
405 {
406 register int i;
407 static int param = 0, cmd, mod, typ;
408 static u_char parms[2];
409
410 /*
411 * Emulate the lk201 command codes.
412 */
413 if (param == 0) {
414 typ = (c & 0x1);
415 cmd = ((c >> 3) & 0xf);
416 mod = ((c >> 1) & 0x3);
417 } else
418 parms[param - 1] = (c & 0x7f);
419 if (c & 0x80) {
420 if (typ) {
421 /*
422 * A peripheral command code. Someday this driver
423 * should know how to send commands to the lk501,
424 * but until then this is all essentially a no-op.
425 */
426 ;
427 } else {
428 /*
429 * Set modes. These have to be emulated in software.
430 */
431 if (cmd > 0 && cmd < 15) {
432 cmd--;
433 if (mod & 0x2)
434 for (i = divbeg[cmd]; i <= divend[cmd]; i++)
435 keymodes[i >> 5] |=
436 (1 << (i & 0x1f));
437 else
438 for (i = divbeg[cmd]; i <= divend[cmd]; i++)
439 keymodes[i >> 5] &=
440 ~(1 << (i & 0x1f));
441 }
442 }
443 param = 0;
444 } else if (++param > 2)
445 param = 2;
446 }
447
448 /*
449 * Take a packet off dtop interface
450 * A packet MUST be there, this is not checked for.
451 */
452 #define DTOP_ESC_CHAR 0xf8
dtop_escape(c)453 dtop_escape(c)
454 {
455 /* I donno much about this stuff.. */
456 switch (c) {
457 case 0xe8: return (0xf8);
458 case 0xe9: return (0xf9);
459 case 0xea: return (0xfa);
460 case 0xeb: return (0xfb);
461 default: /* printf("{esc %x}", c); */
462 return (c);
463 }
464 }
465
dtop_get_packet(dtop,pkt)466 dtop_get_packet(dtop, pkt)
467 dtop_softc_t dtop;
468 dtop_message_t pkt;
469 {
470 register poll_reg_t poll;
471 register data_reg_t data;
472 register int max, i, len;
473 register unsigned char c;
474
475 poll = dtop->poll;
476 data = dtop->data;
477
478 /*
479 * The interface does not handle us the first byte,
480 * which is our address and cannot ever be anything
481 * else but 0x50. This is a good thing, it makes
482 * the average packet exactly one word long, too.
483 */
484 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
485 DELAY(1);
486 if (max == DTOP_MAX_POLL)
487 goto bad;
488 pkt->src_address = DTOP_GET_BYTE(data);
489
490 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
491 DELAY(1);
492 if (max == DTOP_MAX_POLL)
493 goto bad;
494 pkt->code.bits = DTOP_GET_BYTE(data);
495
496 /*
497 * Now get data and checksum
498 */
499 len = pkt->code.val.len + 1;
500 c = 0;
501 for (i = 0; i < len; i++) {
502 again:
503 for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
504 DELAY(1);
505 if (max == DTOP_MAX_POLL)
506 goto bad;
507 if (c == DTOP_ESC_CHAR) {
508 c = dtop_escape(DTOP_GET_BYTE(data) & 0xff);
509 } else {
510 c = DTOP_GET_BYTE(data);
511 if (c == DTOP_ESC_CHAR)
512 goto again;
513 }
514 pkt->body[i] = c;
515 }
516 return (len);
517 bad:
518 dtop->bad_pkts++;
519 return (-1);
520 }
521
522 /*
523 * Get a keyboard char for the console
524 */
dtopKBDGetc()525 dtopKBDGetc()
526 {
527 register int c;
528 dtop_softc_t dtop;
529
530 dtop = &dtop_softc[0];
531 again:
532 c = -1;
533
534 /*
535 * Now check keyboard
536 */
537 if (DTOP_RX_AVAIL(dtop->poll)) {
538
539 dtop_message msg;
540 struct dtop_ds *ds;
541
542 if (dtop_get_packet(dtop, &msg) >= 0) {
543
544 ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)];
545 if (ds->handler == dtop_keyboard_handler) {
546
547 c = dtop_keyboard_handler(
548 &ds->status, &msg,
549 DTOP_EVENT_RECEIVE_PACKET, -1);
550
551 if (c > 0) return c;
552
553 c = -1;
554 }
555 }
556 }
557
558 if (c == -1) {
559 DELAY(100);
560 goto again;
561 }
562
563 return c;
564 }
565
566 int
dtopparam(tp,t)567 dtopparam(tp, t)
568 struct tty *tp;
569 struct termios *t;
570 {
571 if (tp->t_ispeed == 0)
572 ttymodem(tp, 0);
573 else
574 /* called too early to invoke ttymodem, sigh */
575 tp->t_state |= TS_CARR_ON;
576 return (0);
577 }
578
579 /*
580 * Stop output on a line.
581 */
582 /*ARGSUSED*/
dtopstop(tp,flag)583 dtopstop(tp, flag)
584 register struct tty *tp;
585 int flag;
586 {
587 int s;
588
589 s = spltty();
590 if (tp->t_state & TS_BUSY) {
591 if (!(tp->t_state & TS_TTSTOP))
592 tp->t_state |= TS_FLUSH;
593 }
594 splx(s);
595 }
596
597 /*
598 * Default handler function
599 */
600 int
dtop_null_device_handler(dev,msg,event,outc)601 dtop_null_device_handler(dev, msg, event, outc)
602 dtop_device_t dev;
603 dtop_message_t msg;
604 int event;
605 int outc;
606 {
607 /* See if the message was to the default address (powerup) */
608
609 /* Uhmm, donno how to handle this. Drop it */
610 if (event == DTOP_EVENT_RECEIVE_PACKET)
611 dev->unknown_report = *msg;
612 return 0;
613 }
614
615 /*
616 * Handler for locator devices (mice)
617 */
618 int
dtop_locator_handler(dev,msg,event,outc)619 dtop_locator_handler(dev, msg, event, outc)
620 dtop_device_t dev;
621 dtop_message_t msg;
622 int event;
623 int outc;
624 {
625 register unsigned short buttons;
626 register short coord;
627 register int moved = 0;
628 static MouseReport currentRep;
629 register MouseReport *mrp = ¤tRep;
630
631 if (dtopMouseButtons) {
632 mrp->state = 0;
633 /*
634 * Do the position first
635 */
636 coord = GET_SHORT(msg->body[2], msg->body[3]);
637 if (coord < 0) {
638 coord = -coord;
639 moved = 1;
640 } else if (coord > 0) {
641 mrp->state |= MOUSE_X_SIGN;
642 moved = 1;
643 }
644 mrp->dx = (coord & 0x1f);
645 coord = GET_SHORT(msg->body[4], msg->body[5]);
646 if (coord < 0) {
647 coord = -coord;
648 moved = 1;
649 } else if (coord > 0) {
650 mrp->state |= MOUSE_Y_SIGN;
651 moved = 1;
652 }
653 mrp->dy = (coord & 0x1f);
654
655 /*
656 * Time for the buttons now
657 * Shuffle button bits around to serial mouse order.
658 */
659 buttons = GET_SHORT(msg->body[0], msg->body[1]);
660 mrp->state |= (((buttons >> 1) & 0x3) | ((buttons << 2) & 0x4));
661 if (moved)
662 (*dtopMouseEvent)(mrp);
663 (*dtopMouseButtons)(mrp);
664 }
665 return (0);
666 }
667
668 /*
669 * Handler for keyboard devices
670 * Special case: outc set for recv packet means
671 * we are inside the kernel debugger
672 */
673 int
dtop_keyboard_handler(dev,msg,event,outc)674 dtop_keyboard_handler(dev, msg, event, outc)
675 dtop_device_t dev;
676 dtop_message_t msg;
677 int event;
678 int outc;
679 {
680 register u_char *ls, *le, *ns, *ne;
681 u_char save[11], retc;
682 int msg_len, c, s;
683 struct tty *tp = &dtop_tty[0];
684
685 /*
686 * Fiddle about emulating an lk201 keyboard. The lk501
687 * designers carefully ensured that keyboard handlers could be
688 * stateless, then we turn around and use lots of state to
689 * emulate the stateful lk201, since the X11R5 X servers
690 * only know about the lk201... (oh well)
691 */
692 /*
693 * Turn off any autorepeat timeout.
694 */
695 s = splhigh();
696 if (dev->keyboard.k_ar_state != K_AR_IDLE) {
697 dev->keyboard.k_ar_state = K_AR_IDLE;
698 untimeout(dtop_keyboard_repeat, (void *)dev);
699 }
700 splx(s);
701 msg_len = msg->code.val.len;
702
703 /* Check for errors */
704 c = msg->body[0];
705 if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) {
706 printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]);
707 #ifdef notdef
708 if (c != DTOP_KBD_OUT_ERR) return -1;
709 #endif
710 /*
711 * Fake an "all ups" to avoid the stuck key syndrome.
712 */
713 c = msg->body[0] = DTOP_KBD_EMPTY;
714 msg_len = 1;
715 }
716
717 dev->keyboard.last_msec = TO_MS(time);
718 /*
719 * To make things readable, do a first pass cancelling out
720 * all keys that are still pressed, and a second one generating
721 * events. While generating events, do the upstrokes first
722 * from oldest to youngest, then the downstrokes from oldest
723 * to youngest. This copes with lost packets and provides
724 * a reasonable model even if scans are too slow.
725 */
726
727 /* make a copy of new state first */
728 if (msg_len == 1)
729 save[0] = msg->body[0];
730 else if (msg_len > 0)
731 bcopy(msg->body, save, msg_len);
732
733 /*
734 * Cancel out any keys in both the last and current message as
735 * they are unchanged.
736 */
737 if (msg_len > 0 && dev->keyboard.last_codes_count > 0) {
738 ls = dev->keyboard.last_codes;
739 le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count];
740 ne = &msg->body[msg_len];
741 for (; ls < le; ls++) {
742 for (ns = msg->body; ns < ne; ns++)
743 if (*ls == *ns) {
744 *ls = *ns = 0;
745 break;
746 }
747 }
748 }
749
750 /*
751 * Now generate all upstrokes
752 */
753 le = dev->keyboard.last_codes;
754 ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1];
755 for ( ; ls >= le; ls--)
756 if (c = *ls) {
757 (void) kbdMapChar(c);
758
759 if (outc == 0 && dtopDivertXInput &&
760 (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))))
761 (*dtopDivertXInput)(c);
762 }
763 /*
764 * And finally the downstrokes
765 */
766 ne = (char*)msg->body;
767 ns = (char*)&msg->body[msg_len - 1];
768 retc = 0;
769 for ( ; ns >= ne; ns--)
770 if (*ns) {
771 c = kbdMapChar(*ns);
772 if (outc == 0) {
773 if (dtopDivertXInput) {
774 (*dtopDivertXInput)(*ns);
775 c = -1; /* consumed by X */
776 } else if (c >= 0)
777 (*linesw[tp->t_line].l_rint)(c, tp);
778 dev->keyboard.k_ar_state = K_AR_ACTIVE;
779 }
780 /* return the related keycode anyways */
781 if ((c >= 0) && (retc == 0))
782 retc = c;
783 }
784 outc = retc;
785 /* install new scan state */
786 if (msg_len == 1)
787 dev->keyboard.last_codes[0] = save[0];
788 else if (msg_len > 0)
789 bcopy(save, dev->keyboard.last_codes, msg_len);
790 dev->keyboard.last_codes_count = msg_len;
791 if (dev->keyboard.k_ar_state == K_AR_ACTIVE)
792 timeout(dtop_keyboard_repeat, (void *)dev, hz / 2);
793 return (outc);
794 }
795
796 /*
797 * Do an autorepeat as required.
798 */
799 void
dtop_keyboard_repeat(arg)800 dtop_keyboard_repeat(arg)
801 void *arg;
802 {
803 dtop_device_t dev = (dtop_device_t)arg;
804 register int i, c;
805 struct tty *tp = dtop_tty;
806 int s = spltty(), gotone = 0;
807
808 for (i = 0; i < dev->keyboard.last_codes_count; i++) {
809 c = (int)dev->keyboard.last_codes[i];
810 if (c != DTOP_KBD_EMPTY &&
811 (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))) == 0) {
812 dev->keyboard.k_ar_state = K_AR_TRIGGER;
813 if (dtopDivertXInput) {
814 (*dtopDivertXInput)(KEY_REPEAT);
815 gotone = 1;
816 continue;
817 }
818
819 if ((c = kbdMapChar(KEY_REPEAT)) >= 0) {
820 (*linesw[tp->t_line].l_rint)(c, tp);
821 gotone = 1;
822 }
823 }
824 }
825 if (gotone)
826 timeout(dtop_keyboard_repeat, arg, hz / 20);
827 else
828 dev->keyboard.k_ar_state = K_AR_IDLE;
829 splx(s);
830 }
831 #endif
832