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