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