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