|
|
1.1 root 1: /*
2: * Copyright (C) 1985 by Sun Microsystems, Inc.
3: */
4: #include "kbd.h"
5: #if NKBD > 0
6: /*
7: * Keyboard input line discipline.
8: * Console output line discipline.
9: */
10: #include "../h/param.h"
11: #include "../h/systm.h"
12: #include "../h/stream.h"
13: #include "../h/ttyio.h"
14: #include "../h/ttyld.h"
15: #include "../h/conf.h"
16: #include "../machine/sunromvec.h"
17: #include "../sundev/kbdvar.h"
18:
19: /*
20: * For now these are shared.
21: */
22: extern int nkeytables;
23: extern struct keyboard *keytables[];
24: extern char keystringtab[16][KTAB_STRLEN];
25:
1.1.1.2 ! root 26: #define BUSY 02
1.1 root 27: #define TIMEOUT 04
28:
29: struct kbdld {
30: /* Added for 9th edition */
31: struct queue *key_q; /* queue for the keyboard */
32: struct queue *cons_q; /* queue for output to the console */
33: short c_state; /* state of the console */
34: /* Defined by sun */
35: u_char k_id;
36: u_char k_idstate;
37: u_char k_state;
38: u_char k_rptkey;
39: u_int k_buckybits;
40: u_int k_shiftmask;
41: struct keyboard *k_curkeyboard;
42: u_int k_togglemask; /* Toggle shifts state */
43: } kbd[NKBD], nullkbd;
44:
45: /*
46: * States of keyboard ID recognizer
47: */
48: #define KID_NONE 0 /* startup */
49: #define KID_IDLE 1 /* saw IDLE code */
50: #define KID_LKSUN2 2 /* probably Sun-2 */
51: #define KID_OK 3 /* locked on ID */
52:
53: /*
54: * Constants setup during the first open of a kbd (so that hz is defined).
55: */
56: int kbd_repeatrate;
57: int kbd_repeatdelay;
58:
59: int kbdopen(), kbdclose(), kbdldin(), kbdisrv(), kbdldout();
60: static struct qinit kbdrinit = { kbdldin, kbdisrv, kbdopen, kbdclose,300, 60};
61: static struct qinit kbdwinit = { kbdldout, NULL, kbdopen, kbdclose, 200, 100 };
62: struct streamtab kbdinfo = { &kbdrinit, &kbdwinit};
63:
64: /*
65: * Keyboard and console open
66: */
67: kbdopen(qp, dev)
68: register struct queue *qp;
69: {
70: register struct kbdld *k;
71:
72: /* Set these up only once so that they could be changed from adb */
73: if (!kbd_repeatrate) {
74: kbd_repeatrate = (hz+29)/30;
75: kbd_repeatdelay = hz/2;
76: }
77: if (qp->ptr) /* already attached */
78: return(1);
79: for (k = kbd; k->key_q != 0; k++)
80: if (k >= &kbd[NKBD])
81: return(0);
82: *k = nullkbd;
83: k->key_q = qp;
84: k->cons_q = WR(qp);
85: qp->ptr = (caddr_t)k;
86: WR(qp)->ptr = (caddr_t)k;
87: kbdreset(k);
88: return(1);
89: }
90:
91: kbdclose(qp)
92: register struct queue *qp;
93: {
94: register struct kbdld *k = (struct kbdld *)qp->ptr;
95:
96: k->key_q = 0;
97: k->cons_q = 0;
98: }
99:
100: /*
101: * Console write put routine
102: */
103: kbdldout(q, bp)
104: register struct queue *q;
105: register struct block *bp;
106: {
107: register union stmsg *sp;
108: register struct kbdld *k = (struct kbdld *)q->ptr;
109:
110: switch(bp->type) {
111:
112: case M_IOCTL:
113: sp = (union stmsg *)bp->rptr;
114: switch (sp->ioc0.com) {
115:
116: case TIOCGDEV:
117: sp->ioc3.sb.ispeed =
118: sp->ioc3.sb.ospeed = B9600;
119: bp->type = M_IOCACK;
120: qreply(q, bp);
121: return;
122: case TIOCSDEV:
123: bp->wptr = bp->rptr;
124: bp->type = M_IOCACK;
125: qreply(q, bp);
126: return;
127: default:
128: bp->type = M_IOCNAK;
129: bp->wptr = bp->rptr;
130: qreply(q, bp);
131: return;
132: }
133:
134: case M_STOP:
135: k->c_state |= TTSTOP;
136: break;
137:
138: case M_START:
139: k->c_state &= ~TTSTOP;
140: kbdstart(k);
141: break;
142:
143: case M_FLUSH:
144: flushq(q, 0);
145: break;
146:
147: case M_DELAY:
148: case M_DATA:
149: putq(q, bp);
150: kbdstart(k);
151: return;
152:
153: default:
154: break;
155: }
156: freeb(bp);
157: }
158:
159: kbdtime(k)
160: register struct kbdld *k;
161: {
162: k->c_state &= ~TIMEOUT;
163: kbdstart(k);
164: }
165:
166: kbdstart(k)
167: register struct kbdld *k;
168: {
1.1.1.2 ! root 169: int kbdtocons();
! 170:
! 171: if (k->cons_q==NULL)
! 172: return;
! 173: if ((k->c_state & (BUSY|TIMEOUT|TTSTOP))==0 && k->cons_q->count) {
! 174: k->c_state |= BUSY;
! 175: softcall(kbdtocons, (caddr_t)k);
! 176: }
! 177: }
! 178:
! 179: kbdtocons(k)
! 180: register struct kbdld *k;
! 181: {
1.1 root 182: register struct block *bp;
183: register u_char *cp;
184:
185: if (k->cons_q==NULL)
186: return;
1.1.1.2 ! root 187: while ((k->c_state & TTSTOP)==0 && k->cons_q->count) {
1.1 root 188: bp = getq(k->cons_q);
189: switch (bp->type) {
190:
191: case M_DATA:
192: /* Must clear high bit for monitor */
193: for(cp = bp->rptr; cp < bp->wptr; cp++)
194: *cp &= 0177;
195: (*romp->v_fwritestr)(bp->rptr, bp->wptr - bp->rptr,
196: romp->v_fbaddr);
197: freeb(bp);
198: break;
199:
200: case M_DELAY:
201: k->c_state |= TIMEOUT;
1.1.1.2 ! root 202: k->c_state &= ~BUSY;
! 203: timeout(kbdtime, (caddr_t)k, (int)*bp->rptr);
1.1 root 204: freeb(bp);
205: return;
206: default:
207: freeb(bp);
208: break;
209: }
210: }
1.1.1.2 ! root 211: k->c_state &= ~BUSY;
1.1 root 212: }
213:
214: kbdldin(q, bp)
215: struct queue *q;
216: register struct block *bp;
217: {
218: register struct kbdld *k = (struct kbdld *)q->ptr;
219:
220: /* Pass along anything but data */
221: if (bp->type != M_DATA) {
222: (*q->next->qinfo->putp)(q->next, bp);
223: return;
224: }
225:
226: while (bp->rptr < bp->wptr)
227: kbdinput(*bp->rptr++, k);
228: freeb(bp);
229: while ((q->next->flag&QFULL)==0 && (bp = getq(q)))
230: (*q->next->qinfo->putp)(q->next, bp);
231: }
232:
233: /*
234: * keyboard server processing.
235: */
236: kbdisrv(q)
237: register struct queue *q;
238: {
239: register struct block *bp;
240:
241: while ((q->next->flag&QFULL)==0 && (bp = getq(q)))
242: (*q->next->qinfo->putp)(q->next, bp);
243: }
244:
245: /*
246: * kbdclick is used to remember the current click value of the
247: * Sun-3 keyboard. This brain damaged keyboard will reset the
248: * clicking to the "default" value after a reset command and
249: * there is no way to read out the current click value. We
250: * cannot send a click command immediately after the reset
251: * command or the keyboard gets screwed up. So we wait until
252: * we get the ID byte before we send back the click command.
253: * Unfortunately, this means that there is a small window
254: * where the keyboard can click when it really shouldn't be.
255: * A value of -1 means that kbdclick has not been initialized yet.
256: */
257: int kbdclick = -1;
258:
259: /*
260: * Send command byte to keyboard
261: */
262: kbdcmd(k, cmd)
263: register struct kbdld *k;
264: char cmd;
265: {
266: register struct queue *q = WR(k->key_q)->next;
267:
268: putd(q->qinfo->putp, q, cmd);
269: if (cmd == KBD_CMD_NOCLICK)
270: kbdclick = 0;
271: else if (cmd == KBD_CMD_CLICK)
272: kbdclick = 1;
273: }
274:
275: /*
276: * Reset the keyboard
277: */
278: kbdreset(k)
279: register struct kbdld *k;
280: {
281: k->k_idstate = KID_NONE;
282: k->k_state = NORMAL;
283: kbdcmd(k, KBD_CMD_RESET);
284: }
285:
286: kbdidletimeout(k)
287: register struct kbdld *k;
288: {
289: untimeout(kbdidletimeout, (caddr_t)k);
290: /*
291: * Double check that was waiting for idle timeout.
292: */
293: if (k->k_idstate == KID_IDLE)
294: kbdinput(IDLEKEY, k);
295: }
296:
297: /*
298: * Process a keypress
299: */
300: kbdinput(key, k)
301: register u_char key;
302: register struct kbdld *k;
303: {
304: switch (k->k_idstate) {
305:
306: case KID_NONE:
307: if (key == IDLEKEY) {
308: k->k_idstate = KID_IDLE;
309: timeout(kbdidletimeout, (caddr_t)k, hz/10);
310: } else if (key == RESETKEY)
311: k->k_idstate = KID_LKSUN2;
312: return;
313:
314: case KID_IDLE:
315: if (key == IDLEKEY)
316: kbdid(k, KB_KLUNK);
317: else if (key == RESETKEY)
318: k->k_idstate = KID_LKSUN2;
319: else if (key & 0x80)
320: kbdid(k, (int)(KB_VT100 | (key&0x40)));
321: else
322: kbdreset(k);
323: return;
324:
325: case KID_LKSUN2:
326: if (key == 0x02) { /* Sun-2 keyboard */
327: kbdid(k, KB_SUN2);
328: return;
329: }
330: if (key == 0x03) { /* Sun-3 keyboard */
331: kbdid(k, KB_SUN3);
332: /*
333: * We just did a reset command to a Sun-3 keyboard
334: * which sets the click back to the default
335: * (which is currently ON!). We use the kbdclick
336: * variable to see if the keyboard should be
337: * turned on or off. If it has not been set,
338: * then on a sun3 we use the eeprom to determine
339: * if the default value is on or off. In the
340: * sun2 case, we default to off.
341: */
342: switch (kbdclick) {
343: case 0:
344: kbdcmd(k, KBD_CMD_NOCLICK);
345: break;
346: case 1:
347: kbdcmd(k, KBD_CMD_CLICK);
348: break;
349: case -1:
350: default:
351: {
352: #ifdef sun3
353: #include "../sun3/eeprom.h"
354:
355: if (EEPROM->ee_diag.eed_keyclick ==
356: EED_KEYCLICK)
357: kbdcmd(k, KBD_CMD_CLICK);
358: else
359: #endif sun3
360: kbdcmd(k, KBD_CMD_NOCLICK);
361: }
362: break;
363: }
364: return;
365: }
366: kbdreset(k);
367: return;
368:
369: case KID_OK:
370: if (key == 0 || key == 0xFF) {
371: kbdreset(k);
372: return;
373: }
374: break;
375: }
376:
377: switch (k->k_state) {
378:
379: normalstate:
380: k->k_state = NORMAL;
381: case NORMAL:
382: if (k->k_curkeyboard && key == k->k_curkeyboard->k_abort1) {
383: k->k_state = ABORT1;
384: break;
385: }
386: kbdtranslate(k, key);
387: if (key == IDLEKEY)
388: k->k_state = IDLE1;
389: break;
390:
391: case IDLE1:
392: if (key & 0x80) { /* ID byte */
393: if (k->k_id == KB_VT100)
394: k->k_state = IDLE2;
395: else
396: kbdreset(k);
397: break;
398: }
399: if (key != IDLEKEY)
400: goto normalstate; /* real data */
401: break;
402:
403: case IDLE2:
404: if (key == IDLEKEY) k->k_state = IDLE1;
405: else goto normalstate;
406: break;
407:
408: case ABORT1:
409: if (k->k_curkeyboard) {
410: if (key == k->k_curkeyboard->k_abort2) {
411: DELAY(100000);
412: montrap(*romp->v_abortent);
413: k->k_state = NORMAL;
414: kbdtranslate(k, (u_char)IDLEKEY); /* fake */
415: return;
416: } else {
417: kbdtranslate(k, k->k_curkeyboard->k_abort1);
418: goto normalstate;
419: }
420: }
421: }
422: }
423:
424: kbdid(k, id)
425: register struct kbdld *k;
426: int id;
427: {
428: k->k_id = id & 0xF;
429: k->k_idstate = KID_OK;
430: k->k_shiftmask = 0;
431: if (id & 0x40)
432: /* Not a transition so don't send event */
433: k->k_shiftmask |= CAPSMASK;
434: k->k_buckybits = 0;
435: k->k_curkeyboard = keytables[k->k_id];
436: k->k_rptkey = IDLEKEY; /* Nothing happening now */
437: }
438:
439: /*
440: * This routine determines which table we should look in to decode
441: * the current keycode.
442: */
443: struct keymap *
444: settable(k, mask)
445: register struct kbdld *k;
446: register u_int mask;
447: {
448: register struct keyboard *kp;
449:
450: kp = k->k_curkeyboard;
451: if (kp == NULL)
452: return (NULL);
453: if (mask & UPMASK)
454: return (kp->k_up);
455: if (mask & CTRLMASK)
456: return (kp->k_control);
457: if (mask & SHIFTMASK)
458: return (kp->k_shifted);
459: if (mask & CAPSMASK)
460: return (kp->k_caps);
461: return (kp->k_normal);
462: }
463:
464: kbdrpt(k)
465: register struct kbdld *k;
466: {
467: kbdtranslate(k, k->k_rptkey);
468: if (k->k_rptkey != IDLEKEY)
469: timeout(kbdrpt, (caddr_t)k, kbd_repeatrate);
470: }
471:
472: kbdcancelrpt(k)
473: register struct kbdld *k;
474: {
475: if (k->k_rptkey != IDLEKEY) {
476: untimeout(kbdrpt, (caddr_t)k);
477: k->k_rptkey = IDLEKEY;
478: }
479: }
480:
481: kbdtranslate(k, keycode)
482: register struct kbdld *k;
483: register u_char keycode;
484: {
485: register u_char key, newstate, entry;
486: register u_char enF0;
487: register char *cp;
488: struct keymap *km;
489: register struct queue *q = k->key_q;
490:
491: newstate = STATEOF(keycode);
492: key = KEYOF(keycode);
493:
494: km = settable(k, (u_int)(k->k_shiftmask | newstate));
495: if (km == NULL) { /* gross error */
496: kbdcancelrpt(k);
497: return;
498: }
499: entry = km->keymap[key];
500: enF0 = entry & 0xF0;
501: /*
502: * Handle the state of toggle shifts specially.
503: * Toggle shifts should only come on downs.
504: */
505: if (((entry >> 4) == (SHIFTKEYS >> 4)) &&
506: ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts)) {
507: if ((1 << (entry & 0x0F)) & k->k_togglemask) {
508: newstate = RELEASED;
509: } else {
510: newstate = PRESSED;
511: }
512: }
513:
514: if (newstate == PRESSED && entry != NOSCROLL &&
515: enF0 != SHIFTKEYS && enF0 != BUCKYBITS &&
516: !(entry >= LEFTFUNC && entry <= BOTTOMFUNC+15)) {
517: if (k->k_rptkey != keycode) {
518: kbdcancelrpt(k);
519: timeout(kbdrpt, (caddr_t)k, kbd_repeatdelay);
520: k->k_rptkey = keycode;
521: }
522: } else if (key == KEYOF(k->k_rptkey)) /* key going up */
523: kbdcancelrpt(k);
524:
525: switch (entry >> 4) {
526:
527: case 0: case 1: case 2: case 3:
528: case 4: case 5: case 6: case 7:
529: putd(putq, q, entry | k->k_buckybits);
530: break;
531:
532: case SHIFTKEYS >> 4: {
533: u_int shiftbit = 1 << (entry & 0x0F);
534:
535: /* Modify toggle state (see toggle processing above) */
536: if (shiftbit & k->k_curkeyboard->k_toggleshifts) {
537: if (newstate == RELEASED) {
538: k->k_togglemask &= ~shiftbit;
539: k->k_shiftmask &= ~shiftbit;
540: } else {
541: k->k_togglemask |= shiftbit;
542: k->k_shiftmask |= shiftbit;
543: }
544: } else
545: k->k_shiftmask ^= shiftbit;
546: break;
547: }
548:
549: case BUCKYBITS >> 4:
550: k->k_buckybits ^= 1 << (7 + (entry & 0x0F));
551: break;
552:
553: case FUNNY >> 4:
554: switch (entry) {
555: case NOP:
556: break;
557:
558: /*
559: * NOSCROLL/CTRLS/CTRLQ exist so that these keys, on keyboards
560: * with NOSCROLL, interact smoothly. If a user changes
561: * his tty output control keys to be something other than those
562: * in keytables for CTRLS & CTRLQ then he effectively disables
563: * his NOSCROLL key. One could imagine computing CTRLS & CTRLQ
564: * dynamically by watching TIOCSETC ioctl's go by in kbdioctl.
565: */
566: case NOSCROLL:
567: if (k->k_shiftmask & CTLSMASK) goto sendcq;
568: else goto sendcs;
569:
570: case CTRLS:
571: sendcs:
572: k->k_shiftmask |= CTLSMASK;
573: putd(putq, q, ('S'-0x40) | k->k_buckybits);
574: break;
575:
576: case CTRLQ:
577: sendcq:
578: putd(putq, q, ('Q'-0x40) | k->k_buckybits);
579: k->k_shiftmask &= ~CTLSMASK;
580: break;
581:
582: case IDLE:
583: /*
584: * Minor hack to prevent keyboards unplugged
585: * in caps lock from retaining their capslock
586: * state when replugged. This should be
587: * solved by using the capslock info in the
588: * KBDID byte.
589: */
590: if (keycode == NOTPRESENT)
591: k->k_shiftmask = 0;
592: /* Fall thru into RESET code */
593:
594: case RESET:
595: gotreset:
596: k->k_shiftmask &= k->k_curkeyboard->k_idleshifts;
597: k->k_shiftmask |= k->k_togglemask;
598: k->k_buckybits &= k->k_curkeyboard->k_idlebuckys;
599: kbdcancelrpt(k);
600: break;
601:
602: case ERROR:
603: printf("kbd: Error detected\r\n");
604: goto gotreset;
605:
606: /*
607: * Remember when adding new entries that,
608: * if they should NOT auto-repeat,
609: * they should be put into the IF statement
610: * just above this switch block.
611: */
612: default:
613: goto badentry;
614: }
615: break;
616:
617: case STRING >> 4:
618: cp = &keystringtab[entry & 0x0F][0];
619: while (*cp != '\0') {
620: putd(putq, q, *cp);
621: cp++;
622: }
623: break;
624:
625: /*
626: * Remember when adding new entries that,
627: * if they should NOT auto-repeat,
628: * they should be put into the IF statement
629: * just above this switch block.
630: */
631: default:
632: if (entry >= LEFTFUNC && entry <= BOTTOMFUNC+15) {
633: char buf[10], *strsetwithdecimal();
634:
635: if (newstate == RELEASED)
636: break;
637: cp = strsetwithdecimal(&buf[0], (u_int)entry,
638: sizeof (buf) - 1);
639: putd(putq, q, '\033');
640: putd(putq, q, '[');
641: while (*cp != '\0') {
642: putd(putq, q, *cp);
643: cp++;
644: }
645: putd(putq, q, 'z');
646: }
647: badentry:
648: break;
649: }
650: }
651:
652: char *
653: strsetwithdecimal(buf, val, maxdigs)
654: char *buf;
655: u_int val, maxdigs;
656: {
657: int hradix = 5;
658: char *bp;
659: int lowbit;
660: char *tab = "0123456789abcdef";
661:
662: bp = buf + maxdigs;
663: *(--bp) = '\0';
664: while (val) {
665: lowbit = val & 1;
666: val = (val >> 1);
667: *(--bp) = tab[val % hradix * 2 + lowbit];
668: val /= hradix;
669: }
670: return (bp);
671: }
672: #endif NKBD > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.