|
|
1.1 root 1: /*
2: * driver routine for loadable keyboard tables.
3: *
4: * prior to firing off the ioctl() which loads the new keyboard tables,
5: * permform some simple validity checks on the table.
6: * if errors are found, bail out without setting the new table.
7: *
8: * this version removes all references to stdio since we need to put over
9: * a dozen cooked keyboard tables on the boot disk - space is at a premium.
10: *
11: * Version 1.1, 6/25/91
12: */
13:
14: #include <sgtty.h>
15: #include <sys/kb.h>
16: #include <sys/kbscan.h>
17: #include <errno.h>
18: #include <sys/mdata.h>
19:
20: #define VERSION "1.1"
21: #define FALSE (0 != 0)
22: #define TRUE (0 == 0)
23: #define NULL ((char *)0)
24: #define putchar(c) { char b = c; write(1, &b, 1); }
25:
26: /*
27: * globals
28: */
29: char *argv0; /* name of this executable */
30: int errors; /* for exit status */
31: char verbose; /* step-by-step details */
32: char debug; /* print out cooked table & exit */
33: KBTBL table[MAX_KEYS]; /* cooked table for ioctl() */
34: FNKEY *arena; /* function key arena */
35: unsigned char fnbuffer[(sizeof(FNKEY) + MAX_FCHAR)]; /* function key area */
36:
37: /*
38: * The following table maps the specified key number to
39: * a scan code set 3 value.
40: * Note that K_14, K_65 through K_74 and K_107
41: * are provided for compatibility with
42: * the old XT layout AT keyboards.
43: */
44: unsigned char keyval[] = { /* code set 3 mapped value */
45: none, K_1, K_2, K_3, K_4, K_5, K_6, K_7,
46: K_8, K_9, K_10, K_11, K_12, K_13, K_14, K_15,
47: K_16, K_17, K_18, K_19, K_20, K_21, K_22, K_23,
48: K_24, K_25, K_26, K_27, K_28, K_29, K_30, K_31,
49: K_32, K_33, K_34, K_35, K_36, K_37, K_38, K_39,
50: K_40, K_41, K_42, K_43, K_44, K_45, K_46, K_47,
51: K_48, K_49, K_50, K_51, K_52, K_53, K_54, K_55,
52: none, K_57, K_58, none, K_60, K_61, K_62, none,
53: K_64, K_65, K_66, K_67, K_68, K_69, K_70, K_71,
54: K_72, K_73, K_74, K_75, K_76, none, none, K_79,
55: K_80, K_81, none, K_83, K_84, K_85, K_86, none,
56: none, K_89, K_90, K_91, K_92, K_93, none, K_95,
57: K_96, K_97, K_98, K_99, K_100, K_101, K_102, K_103,
58: K_104, K_105, K_106, K_107, K_108, none, K_110, none,
59: K_112, K_113, K_114, K_115, K_116, K_117, K_118, K_119,
60: K_120, K_121, K_122, K_123, K_124, K_125, K_126, none
61: };
62:
63: /*
64: * externs from user-defined keyboard table
65: */
66: extern KBTBL kbtbl[]; /* actual table */
67: extern char tbl_name[]; /* name of table as text */
68: extern unsigned char *funkey[]; /* function key definitions */
69: extern int numfun; /* # of function keys in tbl */
70: extern int numkey; /* number of keys in kbtbl[] */
71:
72: main(argc, argv)
73: char *argv[];
74: {
75: unsigned char *cp, *ncp;
76: int i, j;
77: int fd; /* console file descriptor */
78:
79: argv0 = argv[0];
80: arena = (FNKEY *) fnbuffer;
81:
82: if (argc > 1) {
83: if (strcmp(argv[1], "-V") == 0)
84: printf("Version %s\n", VERSION);
85: else if (strcmp(argv[1], "-D") == 0)
86: ++debug;
87: else
88: usage();
89: }
90:
91: if ((fd = open("/dev/console", 2)) < 0) {
92: err("unable to access console");
93: exit(errors);
94: }
95:
96: /*
97: * loop through the user's keyboard table validating each entry.
98: * if the entry is good, copy it to the destination table.
99: */
100: for (i = 0; i < numkey; ++i) { /* loop thru user's keys */
101: if (ok_entry(i)) {
102: j = kbtbl[i].k_key; /* map key */
103: table[j] = kbtbl[i]; /* copy entry */
104: } else
105: ++errors;
106: }
107:
108: if (errors)
109: exit(errors);
110: /*
111: * build a function key arena consisting of the user defined
112: * special and function keys.
113: */
114: ncp = arena->k_fnval;
115: for (i = 0; i < numfun; ++i) {
116: cp = funkey[i];
117: do {
118: if (ncp >= &arena->k_fnval[MAX_FCHAR]) {
119: err("function key table overflow");
120: exit(errors);
121: }
122: *ncp++ = *cp;
123: } while (*cp++ != DELIM);
124: }
125: arena->k_nfkeys = numfun;
126:
127: if (debug) {
128: dump(); /* print out cooked table */
129: exit(0);
130: }
131:
132: /*
133: * load the cooked keyboard table into the driver via a
134: * special ioctl() call.
135: */
136: ioctl(fd, TIOCSETKBT, table);
137: if (errno) {
138: err("keyboard table ioctl() failed, errno=%d", errno);
139: exit(errors);
140: }
141:
142: /*
143: * load the cooked function key table into the driver via a
144: * special ioctl() call.
145: */
146: ioctl(fd, TIOCSETF, arena);
147: if (errno) {
148: err("function key ioctl() failed, errno=%d", errno);
149: exit(errors);
150: }
151:
152: printf("Loaded %s\n", tbl_name);
153: close(fd);
154: exit(errors);
155: }
156:
157: /*
158: * validate a table entry
159: */
160: ok_entry(n)
161: register int n;
162: {
163: int i;
164: int key = lookup(kbtbl[n].k_key);
165: unsigned char kval;
166:
167: if (!key) {
168: err("invalid key #0x%x in kbtbl[%d]", kbtbl[n].k_key, n);
169: return FALSE;
170: }
171: if ((kbtbl[n].k_flags & (S|F)) == (S|F)) {
172: err("invalid flag field for key K_%d", key);
173: return FALSE;
174: }
175: if (kbtbl[n].k_flags & S) {
176: for (i = BASE; i <= ALT_GR; ++i) {
177: kval = kbtbl[n].k_val[i];
178: if (kval != kbtbl[n].k_val[BASE]) {
179: err("inconsistent shift key entry for K_%d",
180: key);
181: return FALSE;
182: }
183: if (kval < scroll || kval > altgr) {
184: err("bad shift key entry for K_%d",
185: key);
186: return FALSE;
187: }
188: } /* for */
189: } else if (kbtbl[n].k_flags & F) {
190: for (i = BASE; i <= ALT_GR; ++i) {
191: kval = kbtbl[n].k_val[i];
192: if (kval != none)
193: if (kval >= numfun
194: && !VTKEY(kval) /* && kval != fgk*/) {
195: printf("val=%d\n", kval);
196: err("bad function key entry K_%d",
197: key);
198: return FALSE;
199: }
200: } /* for */
201: } /* flag key */
202:
203: if (table[kbtbl[n].k_key].k_key != 0) {
204: err("multiple entries for K_%d", key);
205: return FALSE;
206: }
207: return TRUE;
208: }
209:
210: /*
211: * lookup the physical key number associated with a given
212: * code set 3 scan code.
213: *
214: * return 0 if not found.
215: */
216: lookup(sc)
217: unsigned sc;
218: {
219: register int i;
220:
221: if (sc == none)
222: return 0;
223: for (i = 0; i < sizeof(keyval)/sizeof(keyval[0]); ++i)
224: if (keyval[i] == (unsigned char)sc)
225: return (i);
226: return 0;
227: }
228:
229: usage()
230: {
231: printf("usage:\t%s [-V]\n", argv0);
232: exit(1);
233: }
234:
235: err(msg)
236: char *msg;
237: {
238: printf("%s: ERROR: %r\n", argv0, &msg);
239: ++errors;
240: }
241:
242: /*
243: * dump the cooked keyboard table to stdout
244: */
245: dump()
246: {
247: int i, j;
248:
249: for (i = 0; i < MAX_KEYS; ++i) {
250: printf("%02x: %02x ", i, table[i].k_key);
251: for (j = 0; j < 9; ++j)
252: printf("%02x ", table[i].k_val[j]);
253: printf("(%02x)\n", table[i].k_flags);
254: }
255: }
256:
257:
258: /*
259: * Simple standard output printf() using single character writes to stdout.
260: *
261: * Non-portable things:
262: * 1) alignment of arguments is assumed to be completely contiguous.
263: * 2) the smallest number is assumed to negate to itself.
264: * be held in an exact number of ints.
265: */
266: union alltypes {
267: char c;
268: int i;
269: unsigned u;
270: char *s;
271: };
272:
273: #define bump(p,s) (p+=sizeof(s)/sizeof(int))
274:
275: char *printi();
276:
277: static char null[] = "{NULL}";
278:
279: printf(args)
280: union alltypes args;
281: {
282: xprintf(&args);
283: }
284: xprintf(argp)
285: union alltypes *argp;
286: {
287: register char *cbp;
288: int *iap;
289: register c;
290: char *s;
291: char *cbs;
292: char adj, pad;
293: int prec;
294: int fwidth;
295: int pwidth;
296: register char *fmt;
297: union alltypes elem;
298: char cbuf[64];
299:
300: iap = (int *)argp;
301: fmt = *(char **)iap;
302: bump(iap, char*);
303: for (;;) {
304: while((c = *fmt++) != '%') {
305: if(c == '\0') {
306: return;
307: }
308: putchar(c);
309: }
310: pad = ' ';
311: fwidth = -1;
312: prec = -1;
313: c = *fmt++;
314: if (c == '-') {
315: adj = 1;
316: c = *fmt++;
317: } else
318: adj = 0;
319: if (c == '0') {
320: pad = '0';
321: c = *fmt++;
322: }
323: if (c == '*') {
324: fwidth = *iap++;
325: c = *fmt++;
326: } else
327: for (fwidth = 0; c>='0' && c<='9'; c = *fmt++)
328: fwidth = fwidth*10 + c-'0';
329: if (c == '.') {
330: c = *fmt++;
331: if (c == '*') {
332: prec = *iap++;
333: c = *fmt++;
334: } else
335: for (prec=0; c >= '0' && c <= '9'; c = *fmt++)
336: prec = prec*10 + c-'0';
337: }
338: cbp = cbs = cbuf;
339: switch (c) {
340:
341: case 'd':
342: elem.i = *iap++;
343: if (elem.i < 0) {
344: elem.i = -elem.i;
345: *cbp++ = '-';
346: }
347: cbp = printi(cbp, elem.i, 10);
348: break;
349:
350: case 'u':
351: cbp = printi(cbp, *iap++, 10);
352: break;
353:
354: case 'o':
355: cbp = printi(cbp, *iap++, 8);
356: break;
357:
358: case 'x':
359: cbp = printi(cbp, *iap++, 16);
360: break;
361:
362: case 's':
363: if ((s = *(char **)iap) == NULL)
364: s = null;
365: bump(iap, char*);
366: /*
367: * Do %s specially so it can be longer.
368: */
369: cbp = cbs = s;
370: while (*cbp++ != '\0')
371: if (prec>=0 && cbp-s>prec)
372: break;
373: cbp--;
374: break;
375:
376: case 'c':
377: elem.c = *iap++;
378: *cbp++ = elem.c;
379: break;
380:
381: case 'r':
382: xprintf(*(char ***)iap);
383: bump(iap, char**);
384: break;
385:
386: default:
387: putchar(c);
388: continue;
389: }
390: if ((pwidth = fwidth + cbs-cbp) < 0)
391: pwidth = 0;
392: if (!adj)
393: while (pwidth-- != 0)
394: putchar(pad);
395: while (cbs < cbp)
396: putchar(*cbs++);
397: if (adj)
398: while (pwidth-- != 0)
399: putchar(pad);
400: }
401: }
402:
403: static char digits[] = {
404: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
405: 'A', 'B', 'C', 'D', 'E', 'F'
406: };
407:
408: /*
409: * Print an unsigned integer in base b.
410: */
411: static
412: char *
413: printi(cp, n, b)
414: char *cp;
415: register unsigned n;
416: {
417: register a;
418: register char *ep;
419: char pbuf[10];
420:
421: ep = &pbuf[10];
422: *--ep = 0;
423: for ( ; a = n/b; n=a)
424: *--ep = digits[n%b];
425: *--ep = digits[n];
426: while (*ep)
427: *cp++ = *ep++;
428: return (cp);
429: }
430:
431: /* end of kbmain.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.