1 /*- 2 * Copyright (c) 1994 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software withough specific prior written permission 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * $Id: kbdcontrol.c,v 1.1 1994/05/20 12:18:05 sos Exp $ 28 */ 29 30 #include <ctype.h> 31 #include <stdio.h> 32 #include <machine/console.h> 33 #include "path.h" 34 #include "lex.h" 35 36 char ctrl_names[32][4] = { 37 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 38 "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 39 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 40 "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "ns " 41 }; 42 43 char fkey_table[60][MAXFK] = { 44 /* 00-03 */ "\033[M", "\033[N", "\033[O", "\033[P", 45 /* 04-07 */ "\033[Q", "\033[R", "\033[S", "\033[T", 46 /* 08-0B */ "\033[U", "\033[V", "\033[W", "\033[X", 47 /* 0C-0F */ "\033[W", "\033[X", "\033[Y", "\033[Z", 48 /* 10-13 */ "\033[a", "\033[b", "\033[c", "\033[d", 49 /* 14-17 */ "\033[e", "\033[f", "\033[g", "\033[h", 50 /* 18-1B */ "\033[g", "\033[h", "\033[i", "\033[j", 51 /* 1C-1F */ "\033[k", "\033[l", "\033[m", "\033[n", 52 /* 20-23 */ "\033[o", "\033[p", "\033[q", "\033[r", 53 /* 24-27 */ "\033[g", "\033[h", "\033[i", "\033[j", 54 /* 28-2B */ "\033[k", "\033[l", "\033[m", "\033[n", 55 /* 2C-2F */ "\033[o", "\033[p", "\033[q", "\033[r", 56 /* 30-33 */ "\033[H", "\033[A", "\033[I", "-" , 57 /* 34-37 */ "\033[D", "\177" , "\033[C", "+" , 58 /* 38-3B */ "\033[F", "\033[B", "\033[G", "\033[L" 59 }; 60 61 const int delays[] = {250, 500, 750, 1000}; 62 const int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 63 68, 76, 84, 92, 100, 110, 118, 126, 64 136, 152, 168, 184, 200, 220, 236, 252, 65 272, 304, 336, 368, 400, 440, 472, 504}; 66 const int ndelays = (sizeof(delays) / sizeof(int)); 67 const int nrepeats = (sizeof(repeats) / sizeof(int)); 68 int hex = 0; 69 int number, verbose = 0; 70 char letter; 71 72 73 char * 74 nextarg(int ac, char **av, int *indp, int oc) 75 { 76 if (*indp < ac) 77 return(av[(*indp)++]); 78 fprintf(stderr, "%s: option requires two arguments -- %c\n", av[0], oc); 79 usage(); 80 exit(1); 81 return(""); 82 } 83 84 85 char * 86 mkfullname(const char *s1, const char *s2, const char *s3) 87 { 88 static char *buf = NULL; 89 static int bufl = 0; 90 int f; 91 92 93 f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 94 if (f > bufl) 95 if (buf) 96 buf = (char *)realloc(buf, f); 97 else 98 buf = (char *)malloc(f); 99 if (!buf) { 100 bufl = 0; 101 return(NULL); 102 } 103 104 bufl = f; 105 strcpy(buf, s1); 106 strcat(buf, s2); 107 strcat(buf, s3); 108 return(buf); 109 } 110 111 112 int 113 get_entry() 114 { 115 switch (yylex()) { 116 case TNOP: 117 return NOP | 0x100; 118 case TLSH: 119 return LSH | 0x100; 120 case TRSH: 121 return RSH | 0x100; 122 case TCLK: 123 return CLK | 0x100; 124 case TNLK: 125 return NLK | 0x100; 126 case TSLK: 127 return SLK | 0x100; 128 case TBTAB: 129 return BTAB | 0x100; 130 case TLALT: 131 return LALT | 0x100; 132 case TLCTR: 133 return LCTR | 0x100; 134 case TNEXT: 135 return NEXT | 0x100; 136 case TRCTR: 137 return RCTR | 0x100; 138 case TRALT: 139 return RALT | 0x100; 140 case TALK: 141 return ALK | 0x100; 142 case TASH: 143 return ASH | 0x100; 144 case TMETA: 145 return META | 0x100; 146 case TRBT: 147 return RBT | 0x100; 148 case TDBG: 149 return DBG | 0x100; 150 case TFUNC: 151 if (F(number) > L_FN) 152 return -1; 153 return F(number) | 0x100; 154 case TSCRN: 155 if (S(number) > L_SCR) 156 return -1; 157 return S(number) | 0x100; 158 case TLET: 159 return (unsigned char)letter; 160 case TNUM: 161 if (number < 0 || number > 255) 162 return -1; 163 return number; 164 default: 165 return -1; 166 } 167 } 168 169 170 int 171 get_key_definition_line(FILE* fd, keymap_t *map) 172 { 173 int i, def, scancode; 174 175 yyin = fd; 176 177 /* get scancode number */ 178 if (yylex() != TNUM) 179 return -1; 180 if (number < 0 || number >= NUM_KEYS) 181 return -1; 182 scancode = number; 183 184 /* get key definitions */ 185 map->key[scancode].spcl = 0; 186 for (i=0; i<NUM_STATES; i++) { 187 if ((def = get_entry()) == -1) 188 return -1; 189 if (def & 0x100) 190 map->key[scancode].spcl |= (0x80 >> i); 191 map->key[scancode].map[i] = def & 0xFF; 192 } 193 /* get lock state key def */ 194 if (yylex() != TFLAG) 195 return -1; 196 map->key[scancode].flgs = number; 197 return scancode; 198 } 199 200 201 int 202 print_entry(FILE *fp, int value) 203 { 204 int val = value & 0xFF; 205 206 switch (value) { 207 case NOP | 0x100: 208 fprintf(fp, " nop "); 209 break; 210 case LSH | 0x100: 211 fprintf(fp, " lshift"); 212 break; 213 case RSH | 0x100: 214 fprintf(fp, " rshift"); 215 break; 216 case CLK | 0x100: 217 fprintf(fp, " clock "); 218 break; 219 case NLK | 0x100: 220 fprintf(fp, " nlock "); 221 break; 222 case SLK | 0x100: 223 fprintf(fp, " slock "); 224 break; 225 case BTAB | 0x100: 226 fprintf(fp, " btab "); 227 break; 228 case LALT | 0x100: 229 fprintf(fp, " lalt "); 230 break; 231 case LCTR | 0x100: 232 fprintf(fp, " lctrl "); 233 break; 234 case NEXT | 0x100: 235 fprintf(fp, " nscr "); 236 break; 237 case RCTR | 0x100: 238 fprintf(fp, " rctrl "); 239 break; 240 case RALT | 0x100: 241 fprintf(fp, " ralt "); 242 break; 243 case ALK | 0x100: 244 fprintf(fp, " alock "); 245 break; 246 case ASH | 0x100: 247 fprintf(fp, " ashift"); 248 break; 249 case META | 0x100: 250 fprintf(fp, " meta "); 251 break; 252 case RBT | 0x100: 253 fprintf(fp, " boot "); 254 break; 255 case DBG | 0x100: 256 fprintf(fp, " debug "); 257 break; 258 default: 259 if (value & 0x100) { 260 if (val >= F_FN && val <= L_FN) 261 fprintf(fp, " fkey%02d", val - F_FN + 1); 262 else if (val >= F_SCR && val <= L_SCR) 263 fprintf(fp, " scr%02d ", val - F_SCR + 1); 264 else if (hex) 265 fprintf(fp, " 0x%02x ", val); 266 else 267 fprintf(fp, " %3d ", val); 268 } 269 else { 270 if (val < ' ') 271 fprintf(fp, " %s ", ctrl_names[val]); 272 else if (val == 127) 273 fprintf(fp, " del "); 274 else if (isprint(val)) 275 fprintf(fp, " '%c' ", val); 276 else if (hex) 277 fprintf(fp, " 0x%02x ", val); 278 else 279 fprintf(fp, " %3d ", val); 280 } 281 } 282 } 283 284 285 void 286 print_key_definition_line(FILE *fp, int scancode, struct key_t *key) 287 { 288 int i, value; 289 290 /* print scancode number */ 291 if (hex) 292 fprintf(fp, " 0x%02x ", scancode); 293 else 294 fprintf(fp, " %03d ", scancode); 295 296 /* print key definitions */ 297 for (i=0; i<NUM_STATES; i++) { 298 if (key->spcl & (0x80 >> i)) 299 print_entry(fp, key->map[i] | 0x100); 300 else 301 print_entry(fp, key->map[i]); 302 } 303 304 /* print lock state key def */ 305 switch (key->flgs) { 306 case 0: 307 fprintf(fp, " O\n"); 308 break; 309 case 1: 310 fprintf(fp, " C\n"); 311 break; 312 case 2: 313 fprintf(fp, " N\n"); 314 break; 315 } 316 } 317 318 319 void 320 load_keymap(char *opt) 321 { 322 keymap_t map; 323 FILE *fd; 324 int scancode, i; 325 char *name; 326 char *prefix[] = {"", "", KEYMAP_PATH, NULL}; 327 char *postfix[] = {"", ".kbd", ".kbd"}; 328 329 for (i=0; prefix[i]; i++) { 330 name = mkfullname(prefix[i], opt, postfix[i]); 331 if (fd = fopen(name, "r")) 332 break; 333 } 334 if (fd == NULL) { 335 perror("keymap file not found"); 336 return; 337 } 338 memset(map, 0, sizeof(map)); 339 while (1) { 340 if ((scancode = get_key_definition_line(fd, &map)) < 0) 341 break; 342 if (scancode > map.n_keys) map.n_keys = scancode; 343 } 344 if (ioctl(0, PIO_KEYMAP, &map) < 0) { 345 perror("setting keymap"); 346 fclose(fd); 347 return; 348 } 349 } 350 351 352 void 353 print_keymap() 354 { 355 keymap_t map; 356 int i; 357 358 if (ioctl(0, GIO_KEYMAP, &map) < 0) { 359 perror("getting keymap"); 360 exit(1); 361 } 362 printf( 363 "# alt\n" 364 "# scan cntrl alt alt cntrl lock\n" 365 "# code base shift cntrl shift alt shift cntrl shift state\n" 366 "# ------------------------------------------------------------------\n" 367 ); 368 for (i=0; i<map.n_keys; i++) 369 print_key_definition_line(stdout, i, &map.key[i]); 370 } 371 372 373 void 374 load_default_functionkeys() 375 { 376 fkeyarg_t fkey; 377 int i; 378 379 for (i=0; i<NUM_FKEYS; i++) { 380 fkey.keynum = i; 381 strcpy(fkey.keydef, fkey_table[i]); 382 fkey.flen = strlen(fkey_table[i]); 383 if (ioctl(0, SETFKEY, &fkey) < 0) 384 perror("setting function key"); 385 } 386 } 387 388 void 389 set_functionkey(char *keynumstr, char *string) 390 { 391 fkeyarg_t fkey; 392 int keynum; 393 394 if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 395 load_default_functionkeys(); 396 return; 397 } 398 fkey.keynum = atoi(keynumstr); 399 if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 400 fprintf(stderr, 401 "function key number must be between 1 and %d\n", 402 NUM_FKEYS); 403 return; 404 } 405 if ((fkey.flen = strlen(string)) > MAXFK) { 406 fprintf(stderr, "function key string too long (%d > %d)\n", 407 fkey.flen, MAXFK); 408 return; 409 } 410 strcpy(fkey.keydef, string); 411 if (verbose) 412 fprintf(stderr, "setting function key %d to <%s>\n", 413 fkey.keynum, fkey.keydef); 414 fkey.keynum -= 1; 415 if (ioctl(0, SETFKEY, &fkey) < 0) 416 perror("setting function key"); 417 } 418 419 420 void 421 set_bell_values(char *opt) 422 { 423 int duration, pitch; 424 425 if (!strcmp(opt, "normal")) 426 duration = 1, pitch = 15; 427 else { 428 int n; 429 char *v1; 430 431 duration = strtol(opt, &v1, 0); 432 if ((duration < 0) || (*v1 != '.')) 433 goto badopt; 434 opt = ++v1; 435 pitch = strtol(opt, &v1, 0); 436 if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 437 badopt: 438 fprintf(stderr, 439 "argument to -b must be DURATION.PITCH\n"); 440 return; 441 } 442 } 443 444 if (verbose) 445 fprintf(stderr, "setting bell values to %d.%d\n", 446 duration, pitch); 447 fprintf(stderr, "[=%d;%dB", pitch, duration); 448 } 449 450 451 void 452 set_keyrates(char *opt) 453 { 454 struct { 455 int rep:5; 456 int del:2; 457 int pad:1; 458 }rate; 459 460 if (!strcmp(opt, "slow")) 461 rate.del = 3, rate.rep = 31; 462 else if (!strcmp(opt, "normal")) 463 rate.del = 1, rate.rep = 15; 464 else if (!strcmp(opt, "fast")) 465 rate.del = rate.rep = 0; 466 else { 467 int n; 468 int delay, repeat; 469 char *v1; 470 471 delay = strtol(opt, &v1, 0); 472 if ((delay < 0) || (*v1 != '.')) 473 goto badopt; 474 opt = ++v1; 475 repeat = strtol(opt, &v1, 0); 476 if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 477 badopt: 478 fprintf(stderr, 479 "argument to -r must be delay.repeat\n"); 480 return; 481 } 482 for (n = 0; n < ndelays - 1; n++) 483 if (delay <= delays[n]) 484 break; 485 rate.del = n; 486 for (n = 0; n < nrepeats - 1; n++) 487 if (repeat <= repeats[n]) 488 break; 489 rate.rep = n; 490 } 491 492 if (verbose) 493 fprintf(stderr, "setting keyboard rate to %d.%d\n", 494 delays[rate.del], repeats[rate.rep]); 495 if (ioctl(0, KDSETRAD, rate) < 0) 496 perror("setting keyboard rate"); 497 } 498 499 500 usage() 501 { 502 fprintf(stderr, 503 "Usage: kbdcontrol -b duration.pitch (set bell duration & pitch)\n" 504 " -d (dump keyboard map to stdout)\n" 505 " -l filename (load keyboard map file)\n" 506 " -f <N> string (set function key N to send <string>)\n" 507 " -F (set function keys back to default)\n" 508 " -r delay.repeat (set keyboard delay & repeat rate)\n" 509 " -r slow (set keyboard delay & repeat to slow)\n" 510 " -r normal (set keyboard delay & repeat to normal)\n" 511 " -r fast (set keyboard delay & repeat to fast)\n" 512 " -v (verbose)\n" 513 ); 514 } 515 516 517 void 518 main(int argc, char **argv) 519 { 520 extern char *optarg; 521 extern int optind; 522 int opt; 523 524 /* 525 if (!is_syscons(0)) 526 exit(1); 527 */ 528 while((opt = getopt(argc, argv, "b:df:Fl:r:vx")) != -1) 529 switch(opt) { 530 case 'b': 531 set_bell_values(optarg); 532 break; 533 case 'd': 534 print_keymap(); 535 break; 536 case 'l': 537 load_keymap(optarg); 538 break; 539 case 'f': 540 set_functionkey(optarg, 541 nextarg(argc, argv, &optind, 'f')); 542 break; 543 case 'F': 544 load_default_functionkeys(); 545 break; 546 case 'r': 547 set_keyrates(optarg); 548 break; 549 case 'v': 550 verbose = 1; 551 break; 552 case 'x': 553 hex = 1; 554 break; 555 default: 556 usage(); 557 exit(1); 558 } 559 if ((optind != argc) || (argc == 1)) { 560 usage(); 561 exit(1); 562 } 563 exit(0); 564 } 565 566 567