|
|
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.