|
|
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:
166: if (!key) {
167: err("invalid key #0x%x in kbtbl[%d]", kbtbl[n].k_key, n);
168: return FALSE;
169: }
170: if ((kbtbl[n].k_flags & (S|F)) == (S|F)) {
171: err("invalid flag field for key K_%d", key);
172: return FALSE;
173: }
174: if (kbtbl[n].k_flags & S) {
175: for (i = BASE; i <= ALT_GR; ++i) {
176: if (kbtbl[n].k_val[i] != kbtbl[n].k_val[BASE]) {
177: err("inconsistent shift key entry for K_%d",
178: key);
179: return FALSE;
180: }
181: if (kbtbl[n].k_val[i] < scroll
182: || kbtbl[n].k_val[i] > altgr) {
183: err("bad shift key entry for K_%d",
184: key);
185: return FALSE;
186: }
187: } /* for */
188: } else if (kbtbl[n].k_flags & F) {
189: for (i = BASE; i <= ALT_GR; ++i) {
190: if (kbtbl[n].k_val[i] != none)
191: if (kbtbl[n].k_val[i] >= numfun) {
192: err("bad function key entry for K_%d",
193: key);
194: return FALSE;
195: }
196: } /* for */
197: } /* flag key */
198:
199: key = kbtbl[n].k_key;
200: if (table[key].k_key != 0) {
201: err("multiple entries for K_%d", key);
202: return FALSE;
203: }
204: return TRUE;
205: }
206:
207: /*
208: * lookup the physical key number associated with a given
209: * code set 3 scan code.
210: *
211: * return 0 if not found.
212: */
213: lookup(sc)
214: unsigned sc;
215: {
216: register int i;
217:
218: if (sc == none)
219: return 0;
220: for (i = 0; i < sizeof(keyval)/sizeof(keyval[0]); ++i)
221: if (keyval[i] == (unsigned char)sc)
222: return (i);
223: return 0;
224: }
225:
226: usage()
227: {
228: printf("usage:\t%s [-V]\n", argv0);
229: exit(1);
230: }
231:
232: err(msg)
233: char *msg;
234: {
235: printf("%s: ERROR: %r\n", argv0, &msg);
236: ++errors;
237: }
238:
239: /*
240: * dump the cooked keyboard table to stdout
241: */
242: dump()
243: {
244: int i, j;
245:
246: for (i = 0; i < MAX_KEYS; ++i) {
247: printf("%02x: %02x ", i, table[i].k_key);
248: for (j = 0; j < 9; ++j)
249: printf("%02x ", table[i].k_val[j]);
250: printf("(%02x)\n", table[i].k_flags);
251: }
252: }
253:
254:
255: /*
256: * Simple standard output printf() using single character writes to stdout.
257: *
258: * Non-portable things:
259: * 1) alignment of arguments is assumed to be completely contiguous.
260: * 2) the smallest number is assumed to negate to itself.
261: * be held in an exact number of ints.
262: */
263: union alltypes {
264: char c;
265: int i;
266: unsigned u;
267: char *s;
268: };
269:
270: #define bump(p,s) (p+=sizeof(s)/sizeof(int))
271:
272: char *printi();
273:
274: static char null[] = "{NULL}";
275:
276: printf(args)
277: union alltypes args;
278: {
279: xprintf(&args);
280: }
281: xprintf(argp)
282: union alltypes *argp;
283: {
284: register char *cbp;
285: int *iap;
286: register c;
287: char *s;
288: char *cbs;
289: char adj, pad;
290: int prec;
291: int fwidth;
292: int pwidth;
293: register char *fmt;
294: union alltypes elem;
295: char cbuf[64];
296:
297: iap = (int *)argp;
298: fmt = *(char **)iap;
299: bump(iap, char*);
300: for (;;) {
301: while((c = *fmt++) != '%') {
302: if(c == '\0') {
303: return;
304: }
305: putchar(c);
306: }
307: pad = ' ';
308: fwidth = -1;
309: prec = -1;
310: c = *fmt++;
311: if (c == '-') {
312: adj = 1;
313: c = *fmt++;
314: } else
315: adj = 0;
316: if (c == '0') {
317: pad = '0';
318: c = *fmt++;
319: }
320: if (c == '*') {
321: fwidth = *iap++;
322: c = *fmt++;
323: } else
324: for (fwidth = 0; c>='0' && c<='9'; c = *fmt++)
325: fwidth = fwidth*10 + c-'0';
326: if (c == '.') {
327: c = *fmt++;
328: if (c == '*') {
329: prec = *iap++;
330: c = *fmt++;
331: } else
332: for (prec=0; c >= '0' && c <= '9'; c = *fmt++)
333: prec = prec*10 + c-'0';
334: }
335: cbp = cbs = cbuf;
336: switch (c) {
337:
338: case 'd':
339: elem.i = *iap++;
340: if (elem.i < 0) {
341: elem.i = -elem.i;
342: *cbp++ = '-';
343: }
344: cbp = printi(cbp, elem.i, 10);
345: break;
346:
347: case 'u':
348: cbp = printi(cbp, *iap++, 10);
349: break;
350:
351: case 'o':
352: cbp = printi(cbp, *iap++, 8);
353: break;
354:
355: case 'x':
356: cbp = printi(cbp, *iap++, 16);
357: break;
358:
359: case 's':
360: if ((s = *(char **)iap) == NULL)
361: s = null;
362: bump(iap, char*);
363: /*
364: * Do %s specially so it can be longer.
365: */
366: cbp = cbs = s;
367: while (*cbp++ != '\0')
368: if (prec>=0 && cbp-s>prec)
369: break;
370: cbp--;
371: break;
372:
373: case 'c':
374: elem.c = *iap++;
375: *cbp++ = elem.c;
376: break;
377:
378: case 'r':
379: xprintf(*(char ***)iap);
380: bump(iap, char**);
381: break;
382:
383: default:
384: putchar(c);
385: continue;
386: }
387: if ((pwidth = fwidth + cbs-cbp) < 0)
388: pwidth = 0;
389: if (!adj)
390: while (pwidth-- != 0)
391: putchar(pad);
392: while (cbs < cbp)
393: putchar(*cbs++);
394: if (adj)
395: while (pwidth-- != 0)
396: putchar(pad);
397: }
398: }
399:
400: static char digits[] = {
401: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
402: 'A', 'B', 'C', 'D', 'E', 'F'
403: };
404:
405: /*
406: * Print an unsigned integer in base b.
407: */
408: static
409: char *
410: printi(cp, n, b)
411: char *cp;
412: register unsigned n;
413: {
414: register a;
415: register char *ep;
416: char pbuf[10];
417:
418: ep = &pbuf[10];
419: *--ep = 0;
420: for ( ; a = n/b; n=a)
421: *--ep = digits[n%b];
422: *--ep = digits[n];
423: while (*ep)
424: *cp++ = *ep++;
425: return (cp);
426: }
427:
428: /* end of kbmain.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.