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