1 /*- 2 * Copyright (c) 1994-1995 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 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef lint 30 static const char rcsid[] = 31 "$FreeBSD$"; 32 #endif /* not lint */ 33 34 #include <ctype.h> 35 #include <err.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 #include <fcntl.h> 41 #include <sys/kbio.h> 42 #include <sys/consio.h> 43 #include "path.h" 44 #include "lex.h" 45 46 /* 47 * HALT, PDWN, and PASTE aren't defined in 4.x, but we need them to bridge 48 * to 5.0-current so define them here as a stop gap transition measure. 49 */ 50 #ifndef HALT 51 #define HALT 0xa1 /* halt machine */ 52 #endif 53 #ifndef PDWN 54 #define PDWN 0xa2 /* halt machine and power down */ 55 #endif 56 #ifndef PASTE 57 #define PASTE 0xa3 /* paste from cut-paste buffer */ 58 #endif 59 60 char ctrl_names[32][4] = { 61 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 62 "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 63 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 64 "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us " 65 }; 66 67 char acc_names[15][5] = { 68 "dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot", 69 "duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo", 70 "dcar", 71 }; 72 73 char acc_names_u[15][5] = { 74 "DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT", 75 "DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO", 76 "DCAR", 77 }; 78 79 char fkey_table[96][MAXFK] = { 80 /* 01-04 */ "\033[M", "\033[N", "\033[O", "\033[P", 81 /* 05-08 */ "\033[Q", "\033[R", "\033[S", "\033[T", 82 /* 09-12 */ "\033[U", "\033[V", "\033[W", "\033[X", 83 /* 13-16 */ "\033[Y", "\033[Z", "\033[a", "\033[b", 84 /* 17-20 */ "\033[c", "\033[d", "\033[e", "\033[f", 85 /* 21-24 */ "\033[g", "\033[h", "\033[i", "\033[j", 86 /* 25-28 */ "\033[k", "\033[l", "\033[m", "\033[n", 87 /* 29-32 */ "\033[o", "\033[p", "\033[q", "\033[r", 88 /* 33-36 */ "\033[s", "\033[t", "\033[u", "\033[v", 89 /* 37-40 */ "\033[w", "\033[x", "\033[y", "\033[z", 90 /* 41-44 */ "\033[@", "\033[[", "\033[\\","\033[]", 91 /* 45-48 */ "\033[^", "\033[_", "\033[`", "\033[{", 92 /* 49-52 */ "\033[H", "\033[A", "\033[I", "-" , 93 /* 53-56 */ "\033[D", "\033[E", "\033[C", "+" , 94 /* 57-60 */ "\033[F", "\033[B", "\033[G", "\033[L", 95 /* 61-64 */ "\177", "\033[J", "\033[~", "\033[}", 96 /* 65-68 */ "" , "" , "" , "" , 97 /* 69-72 */ "" , "" , "" , "" , 98 /* 73-76 */ "" , "" , "" , "" , 99 /* 77-80 */ "" , "" , "" , "" , 100 /* 81-84 */ "" , "" , "" , "" , 101 /* 85-88 */ "" , "" , "" , "" , 102 /* 89-92 */ "" , "" , "" , "" , 103 /* 93-96 */ "" , "" , "" , "" , 104 }; 105 106 const int delays[] = {250, 500, 750, 1000}; 107 const int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 108 68, 76, 84, 92, 100, 110, 118, 126, 109 136, 152, 168, 184, 200, 220, 236, 252, 110 272, 304, 336, 368, 400, 440, 472, 504}; 111 const int ndelays = (sizeof(delays) / sizeof(int)); 112 const int nrepeats = (sizeof(repeats) / sizeof(int)); 113 int hex = 0; 114 int number; 115 char letter; 116 int token; 117 118 void dump_accent_definition(char *name, accentmap_t *accentmap); 119 void dump_entry(int value); 120 void dump_key_definition(char *name, keymap_t *keymap); 121 int get_accent_definition_line(accentmap_t *); 122 int get_entry(void); 123 int get_key_definition_line(keymap_t *); 124 void load_keymap(char *opt, int dumponly); 125 void load_default_functionkeys(void); 126 char * nextarg(int ac, char **av, int *indp, int oc); 127 char * mkfullname(const char *s1, const char *s2, const char *s3); 128 void print_accent_definition_line(FILE *fp, int accent, 129 struct acc_t *key); 130 void print_entry(FILE *fp, int value); 131 void print_key_definition_line(FILE *fp, int scancode, 132 struct keyent_t *key); 133 void print_keymap(void); 134 void release_keyboard(void); 135 void set_bell_values(char *opt); 136 void set_functionkey(char *keynumstr, char *string); 137 void set_keyboard(char *device); 138 void set_keyrates(char *opt); 139 void show_kbd_info(void); 140 void usage(void) __dead2; 141 142 char * 143 nextarg(int ac, char **av, int *indp, int oc) 144 { 145 if (*indp < ac) 146 return(av[(*indp)++]); 147 warnx("option requires two arguments -- %c", oc); 148 usage(); 149 } 150 151 152 char * 153 mkfullname(const char *s1, const char *s2, const char *s3) 154 { 155 static char *buf = NULL; 156 static int bufl = 0; 157 int f; 158 159 f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 160 if (f > bufl) { 161 if (buf) 162 buf = (char *)realloc(buf, f); 163 else 164 buf = (char *)malloc(f); 165 } 166 if (!buf) { 167 bufl = 0; 168 return(NULL); 169 } 170 171 bufl = f; 172 strcpy(buf, s1); 173 strcat(buf, s2); 174 strcat(buf, s3); 175 return(buf); 176 } 177 178 179 int 180 get_entry(void) 181 { 182 switch ((token = yylex())) { 183 case TNOP: 184 return NOP | 0x100; 185 case TLSH: 186 return LSH | 0x100; 187 case TRSH: 188 return RSH | 0x100; 189 case TCLK: 190 return CLK | 0x100; 191 case TNLK: 192 return NLK | 0x100; 193 case TSLK: 194 return SLK | 0x100; 195 case TBTAB: 196 return BTAB | 0x100; 197 case TLALT: 198 return LALT | 0x100; 199 case TLCTR: 200 return LCTR | 0x100; 201 case TNEXT: 202 return NEXT | 0x100; 203 case TPREV: 204 return PREV | 0x100; 205 case TRCTR: 206 return RCTR | 0x100; 207 case TRALT: 208 return RALT | 0x100; 209 case TALK: 210 return ALK | 0x100; 211 case TASH: 212 return ASH | 0x100; 213 case TMETA: 214 return META | 0x100; 215 case TRBT: 216 return RBT | 0x100; 217 case TDBG: 218 return DBG | 0x100; 219 case TSUSP: 220 return SUSP | 0x100; 221 case TSPSC: 222 return SPSC | 0x100; 223 case TPANIC: 224 return PNC | 0x100; 225 case TLSHA: 226 return LSHA | 0x100; 227 case TRSHA: 228 return RSHA | 0x100; 229 case TLCTRA: 230 return LCTRA | 0x100; 231 case TRCTRA: 232 return RCTRA | 0x100; 233 case TLALTA: 234 return LALTA | 0x100; 235 case TRALTA: 236 return RALTA | 0x100; 237 case THALT: 238 return HALT | 0x100; 239 case TPDWN: 240 return PDWN | 0x100; 241 case TPASTE: 242 return PASTE | 0x100; 243 case TACC: 244 if (ACC(number) > L_ACC) 245 return -1; 246 return ACC(number) | 0x100; 247 case TFUNC: 248 if (F(number) > L_FN) 249 return -1; 250 return F(number) | 0x100; 251 case TSCRN: 252 if (S(number) > L_SCR) 253 return -1; 254 return S(number) | 0x100; 255 case TLET: 256 return (unsigned char)letter; 257 case TNUM: 258 if (number < 0 || number > 255) 259 return -1; 260 return number; 261 default: 262 return -1; 263 } 264 } 265 266 static int 267 get_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap) 268 { 269 int c; 270 271 yyin = fd; 272 273 if (token < 0) 274 token = yylex(); 275 switch (token) { 276 case TNUM: 277 c = get_key_definition_line(keymap); 278 if (c < 0) 279 errx(1, "invalid key definition"); 280 if (c > keymap->n_keys) 281 keymap->n_keys = c; 282 break; 283 case TACC: 284 c = get_accent_definition_line(accentmap); 285 if (c < 0) 286 errx(1, "invalid accent key definition"); 287 if (c > accentmap->n_accs) 288 accentmap->n_accs = c; 289 break; 290 case 0: 291 /* EOF */ 292 return -1; 293 default: 294 errx(1, "illegal definition line"); 295 } 296 return c; 297 } 298 299 int 300 get_key_definition_line(keymap_t *map) 301 { 302 int i, def, scancode; 303 304 /* check scancode number */ 305 if (number < 0 || number >= NUM_KEYS) 306 return -1; 307 scancode = number; 308 309 /* get key definitions */ 310 map->key[scancode].spcl = 0; 311 for (i=0; i<NUM_STATES; i++) { 312 if ((def = get_entry()) == -1) 313 return -1; 314 if (def & 0x100) 315 map->key[scancode].spcl |= (0x80 >> i); 316 map->key[scancode].map[i] = def & 0xFF; 317 } 318 /* get lock state key def */ 319 if ((token = yylex()) != TFLAG) 320 return -1; 321 map->key[scancode].flgs = number; 322 token = yylex(); 323 return (scancode + 1); 324 } 325 326 int 327 get_accent_definition_line(accentmap_t *map) 328 { 329 int accent; 330 int c1, c2; 331 int i; 332 333 if (ACC(number) < F_ACC || ACC(number) > L_ACC) 334 /* number out of range */ 335 return -1; 336 accent = number; 337 if (map->acc[accent].accchar != 0) { 338 /* this entry has already been defined before! */ 339 errx(1, "duplicated accent key definition"); 340 } 341 342 switch ((token = yylex())) { 343 case TLET: 344 map->acc[accent].accchar = letter; 345 break; 346 case TNUM: 347 map->acc[accent].accchar = number; 348 break; 349 default: 350 return -1; 351 } 352 353 for (i = 0; (token = yylex()) == '(';) { 354 switch ((token = yylex())) { 355 case TLET: 356 c1 = letter; 357 break; 358 case TNUM: 359 c1 = number; 360 break; 361 default: 362 return -1; 363 } 364 switch ((token = yylex())) { 365 case TLET: 366 c2 = letter; 367 break; 368 case TNUM: 369 c2 = number; 370 break; 371 default: 372 return -1; 373 } 374 if ((token = yylex()) != ')') 375 return -1; 376 if (i >= NUM_ACCENTCHARS) { 377 warnx("too many accented characters, ignored"); 378 continue; 379 } 380 map->acc[accent].map[i][0] = c1; 381 map->acc[accent].map[i][1] = c2; 382 ++i; 383 } 384 return (accent + 1); 385 } 386 387 void 388 print_entry(FILE *fp, int value) 389 { 390 int val = value & 0xFF; 391 392 switch (value) { 393 case NOP | 0x100: 394 fprintf(fp, " nop "); 395 break; 396 case LSH | 0x100: 397 fprintf(fp, " lshift"); 398 break; 399 case RSH | 0x100: 400 fprintf(fp, " rshift"); 401 break; 402 case CLK | 0x100: 403 fprintf(fp, " clock "); 404 break; 405 case NLK | 0x100: 406 fprintf(fp, " nlock "); 407 break; 408 case SLK | 0x100: 409 fprintf(fp, " slock "); 410 break; 411 case BTAB | 0x100: 412 fprintf(fp, " btab "); 413 break; 414 case LALT | 0x100: 415 fprintf(fp, " lalt "); 416 break; 417 case LCTR | 0x100: 418 fprintf(fp, " lctrl "); 419 break; 420 case NEXT | 0x100: 421 fprintf(fp, " nscr "); 422 break; 423 case PREV | 0x100: 424 fprintf(fp, " pscr "); 425 break; 426 case RCTR | 0x100: 427 fprintf(fp, " rctrl "); 428 break; 429 case RALT | 0x100: 430 fprintf(fp, " ralt "); 431 break; 432 case ALK | 0x100: 433 fprintf(fp, " alock "); 434 break; 435 case ASH | 0x100: 436 fprintf(fp, " ashift"); 437 break; 438 case META | 0x100: 439 fprintf(fp, " meta "); 440 break; 441 case RBT | 0x100: 442 fprintf(fp, " boot "); 443 break; 444 case DBG | 0x100: 445 fprintf(fp, " debug "); 446 break; 447 case SUSP | 0x100: 448 fprintf(fp, " susp "); 449 break; 450 case SPSC | 0x100: 451 fprintf(fp, " saver "); 452 break; 453 case PNC | 0x100: 454 fprintf(fp, " panic "); 455 break; 456 case LSHA | 0x100: 457 fprintf(fp, " lshifta"); 458 break; 459 case RSHA | 0x100: 460 fprintf(fp, " rshifta"); 461 break; 462 case LCTRA | 0x100: 463 fprintf(fp, " lctrla"); 464 break; 465 case RCTRA | 0x100: 466 fprintf(fp, " rctrla"); 467 break; 468 case LALTA | 0x100: 469 fprintf(fp, " lalta "); 470 break; 471 case RALTA | 0x100: 472 fprintf(fp, " ralta "); 473 break; 474 case HALT | 0x100: 475 fprintf(fp, " halt "); 476 break; 477 case PDWN | 0x100: 478 fprintf(fp, " pdwn "); 479 break; 480 case PASTE | 0x100: 481 fprintf(fp, " paste "); 482 break; 483 default: 484 if (value & 0x100) { 485 if (val >= F_FN && val <= L_FN) 486 fprintf(fp, " fkey%02d", val - F_FN + 1); 487 else if (val >= F_SCR && val <= L_SCR) 488 fprintf(fp, " scr%02d ", val - F_SCR + 1); 489 else if (val >= F_ACC && val <= L_ACC) 490 fprintf(fp, " %-6s", acc_names[val - F_ACC]); 491 else if (hex) 492 fprintf(fp, " 0x%02x ", val); 493 else 494 fprintf(fp, " %3d ", val); 495 } 496 else { 497 if (val < ' ') 498 fprintf(fp, " %s ", ctrl_names[val]); 499 else if (val == 127) 500 fprintf(fp, " del "); 501 else if (isascii(val) && isprint(val)) 502 fprintf(fp, " '%c' ", val); 503 else if (hex) 504 fprintf(fp, " 0x%02x ", val); 505 else 506 fprintf(fp, " %3d ", val); 507 } 508 } 509 } 510 511 void 512 print_key_definition_line(FILE *fp, int scancode, struct keyent_t *key) 513 { 514 int i; 515 516 /* print scancode number */ 517 if (hex) 518 fprintf(fp, " 0x%02x ", scancode); 519 else 520 fprintf(fp, " %03d ", scancode); 521 522 /* print key definitions */ 523 for (i=0; i<NUM_STATES; i++) { 524 if (key->spcl & (0x80 >> i)) 525 print_entry(fp, key->map[i] | 0x100); 526 else 527 print_entry(fp, key->map[i]); 528 } 529 530 /* print lock state key def */ 531 switch (key->flgs) { 532 case 0: 533 fprintf(fp, " O\n"); 534 break; 535 case 1: 536 fprintf(fp, " C\n"); 537 break; 538 case 2: 539 fprintf(fp, " N\n"); 540 break; 541 case 3: 542 fprintf(fp, " B\n"); 543 break; 544 } 545 } 546 547 void 548 print_accent_definition_line(FILE *fp, int accent, struct acc_t *key) 549 { 550 int c; 551 int i; 552 553 if (key->accchar == 0) 554 return; 555 556 /* print accent number */ 557 fprintf(fp, " %-6s", acc_names[accent]); 558 if (isascii(key->accchar) && isprint(key->accchar)) 559 fprintf(fp, "'%c' ", key->accchar); 560 else if (hex) 561 fprintf(fp, "0x%02x ", key->accchar); 562 else 563 fprintf(fp, "%03d ", key->accchar); 564 565 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 566 c = key->map[i][0]; 567 if (c == 0) 568 break; 569 if ((i > 0) && ((i % 4) == 0)) 570 fprintf(fp, "\n "); 571 if (isascii(c) && isprint(c)) 572 fprintf(fp, "( '%c' ", c); 573 else if (hex) 574 fprintf(fp, "(0x%02x ", c); 575 else 576 fprintf(fp, "( %03d ", c); 577 c = key->map[i][1]; 578 if (isascii(c) && isprint(c)) 579 fprintf(fp, "'%c' ) ", c); 580 else if (hex) 581 fprintf(fp, "0x%02x) ", c); 582 else 583 fprintf(fp, "%03d ) ", c); 584 } 585 fprintf(fp, "\n"); 586 } 587 588 void 589 dump_entry(int value) 590 { 591 if (value & 0x100) { 592 value &= 0x00ff; 593 switch (value) { 594 case NOP: 595 printf(" NOP, "); 596 break; 597 case LSH: 598 printf(" LSH, "); 599 break; 600 case RSH: 601 printf(" RSH, "); 602 break; 603 case CLK: 604 printf(" CLK, "); 605 break; 606 case NLK: 607 printf(" NLK, "); 608 break; 609 case SLK: 610 printf(" SLK, "); 611 break; 612 case BTAB: 613 printf(" BTAB, "); 614 break; 615 case LALT: 616 printf(" LALT, "); 617 break; 618 case LCTR: 619 printf(" LCTR, "); 620 break; 621 case NEXT: 622 printf(" NEXT, "); 623 break; 624 case PREV: 625 printf(" PREV, "); 626 break; 627 case RCTR: 628 printf(" RCTR, "); 629 break; 630 case RALT: 631 printf(" RALT, "); 632 break; 633 case ALK: 634 printf(" ALK, "); 635 break; 636 case ASH: 637 printf(" ASH, "); 638 break; 639 case META: 640 printf(" META, "); 641 break; 642 case RBT: 643 printf(" RBT, "); 644 break; 645 case DBG: 646 printf(" DBG, "); 647 break; 648 case SUSP: 649 printf(" SUSP, "); 650 break; 651 case SPSC: 652 printf(" SPSC, "); 653 break; 654 case PNC: 655 printf(" PNC, "); 656 break; 657 case LSHA: 658 printf(" LSHA, "); 659 break; 660 case RSHA: 661 printf(" RSHA, "); 662 break; 663 case LCTRA: 664 printf("LCTRA, "); 665 break; 666 case RCTRA: 667 printf("RCTRA, "); 668 break; 669 case LALTA: 670 printf("LALTA, "); 671 break; 672 case RALTA: 673 printf("RALTA, "); 674 break; 675 case HALT: 676 printf(" HALT, "); 677 break; 678 case PDWN: 679 printf(" PDWN, "); 680 break; 681 case PASTE: 682 printf("PASTE, "); 683 break; 684 default: 685 if (value >= F_FN && value <= L_FN) 686 printf(" F(%2d),", value - F_FN + 1); 687 else if (value >= F_SCR && value <= L_SCR) 688 printf(" S(%2d),", value - F_SCR + 1); 689 else if (value >= F_ACC && value <= L_ACC) 690 printf(" %-4s, ", acc_names_u[value - F_ACC]); 691 else 692 printf(" 0x%02X, ", value); 693 break; 694 } 695 } else if (value == '\'') { 696 printf(" '\\'', "); 697 } else if (value == '\\') { 698 printf(" '\\\\', "); 699 } else if (isascii(value) && isprint(value)) { 700 printf(" '%c', ", value); 701 } else { 702 printf(" 0x%02X, ", value); 703 } 704 } 705 706 void 707 dump_key_definition(char *name, keymap_t *keymap) 708 { 709 int i, j; 710 711 printf("static keymap_t keymap_%s = { 0x%02x, {\n", 712 name, (unsigned)keymap->n_keys); 713 printf( 714 "/* alt\n" 715 " * scan cntrl alt alt cntrl\n" 716 " * code base shift cntrl shift alt shift cntrl shift spcl flgs\n" 717 " * ---------------------------------------------------------------------------\n" 718 " */\n"); 719 for (i = 0; i < keymap->n_keys; i++) { 720 printf("/*%02x*/{{", i); 721 for (j = 0; j < NUM_STATES; j++) { 722 if (keymap->key[i].spcl & (0x80 >> j)) 723 dump_entry(keymap->key[i].map[j] | 0x100); 724 else 725 dump_entry(keymap->key[i].map[j]); 726 } 727 printf("}, 0x%02X,0x%02X },\n", 728 (unsigned)keymap->key[i].spcl, 729 (unsigned)keymap->key[i].flgs); 730 } 731 printf("} };\n\n"); 732 } 733 734 void 735 dump_accent_definition(char *name, accentmap_t *accentmap) 736 { 737 int i, j; 738 int c; 739 740 printf("static accentmap_t accentmap_%s = { %d", 741 name, accentmap->n_accs); 742 if (accentmap->n_accs <= 0) { 743 printf(" };\n\n"); 744 return; 745 } 746 printf(", {\n"); 747 for (i = 0; i < NUM_DEADKEYS; i++) { 748 printf(" /* %s=%d */\n {", acc_names[i], i); 749 c = accentmap->acc[i].accchar; 750 if (c == '\'') 751 printf(" '\\'', {"); 752 else if (c == '\\') 753 printf(" '\\\\', {"); 754 else if (isascii(c) && isprint(c)) 755 printf(" '%c', {", c); 756 else if (c == 0) { 757 printf(" 0x00 }, \n"); 758 continue; 759 } else 760 printf(" 0x%02x, {", c); 761 for (j = 0; j < NUM_ACCENTCHARS; j++) { 762 c = accentmap->acc[i].map[j][0]; 763 if (c == 0) 764 break; 765 if ((j > 0) && ((j % 4) == 0)) 766 printf("\n\t "); 767 if (isascii(c) && isprint(c)) 768 printf(" { '%c',", c); 769 else 770 printf(" { 0x%02x,", c); 771 printf("0x%02x },", accentmap->acc[i].map[j][1]); 772 } 773 printf(" }, },\n"); 774 } 775 printf("} };\n\n"); 776 } 777 778 void 779 load_keymap(char *opt, int dumponly) 780 { 781 keymap_t keymap; 782 accentmap_t accentmap; 783 FILE *fd; 784 int i, j; 785 char *name, *cp; 786 char blank[] = "", keymap_path[] = KEYMAP_PATH, dotkbd[] = ".kbd"; 787 char *prefix[] = {blank, blank, keymap_path, NULL}; 788 char *postfix[] = {blank, dotkbd, NULL}; 789 790 cp = getenv("KEYMAP_PATH"); 791 if (cp != NULL) 792 asprintf(&(prefix[0]), "%s/", cp); 793 794 fd = NULL; 795 for (i=0; prefix[i] && fd == NULL; i++) { 796 for (j=0; postfix[j] && fd == NULL; j++) { 797 name = mkfullname(prefix[i], opt, postfix[j]); 798 fd = fopen(name, "r"); 799 } 800 } 801 if (fd == NULL) { 802 warn("keymap file \"%s\" not found", opt); 803 return; 804 } 805 memset(&keymap, 0, sizeof(keymap)); 806 memset(&accentmap, 0, sizeof(accentmap)); 807 token = -1; 808 while (1) { 809 if (get_definition_line(fd, &keymap, &accentmap) < 0) 810 break; 811 } 812 if (dumponly) { 813 /* fix up the filename to make it a valid C identifier */ 814 for (cp = opt; *cp; cp++) 815 if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_'; 816 printf("/*\n" 817 " * Automatically generated from %s.\n" 818 " * DO NOT EDIT!\n" 819 " */\n", name); 820 dump_key_definition(opt, &keymap); 821 dump_accent_definition(opt, &accentmap); 822 return; 823 } 824 if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) { 825 warn("setting keymap"); 826 fclose(fd); 827 return; 828 } 829 if ((accentmap.n_accs > 0) 830 && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) { 831 warn("setting accentmap"); 832 fclose(fd); 833 return; 834 } 835 } 836 837 void 838 print_keymap(void) 839 { 840 keymap_t keymap; 841 accentmap_t accentmap; 842 int i; 843 844 if (ioctl(0, GIO_KEYMAP, &keymap) < 0) 845 err(1, "getting keymap"); 846 if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) 847 memset(&accentmap, 0, sizeof(accentmap)); 848 printf( 849 "# alt\n" 850 "# scan cntrl alt alt cntrl lock\n" 851 "# code base shift cntrl shift alt shift cntrl shift state\n" 852 "# ------------------------------------------------------------------\n" 853 ); 854 for (i=0; i<keymap.n_keys; i++) 855 print_key_definition_line(stdout, i, &keymap.key[i]); 856 857 printf("\n"); 858 for (i = 0; i < NUM_DEADKEYS; i++) 859 print_accent_definition_line(stdout, i, &accentmap.acc[i]); 860 861 } 862 863 void 864 load_default_functionkeys(void) 865 { 866 fkeyarg_t fkey; 867 int i; 868 869 for (i=0; i<NUM_FKEYS; i++) { 870 fkey.keynum = i; 871 strcpy(fkey.keydef, fkey_table[i]); 872 fkey.flen = strlen(fkey_table[i]); 873 if (ioctl(0, SETFKEY, &fkey) < 0) 874 warn("setting function key"); 875 } 876 } 877 878 void 879 set_functionkey(char *keynumstr, char *string) 880 { 881 fkeyarg_t fkey; 882 883 if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 884 load_default_functionkeys(); 885 return; 886 } 887 fkey.keynum = atoi(keynumstr); 888 if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 889 warnx("function key number must be between 1 and %d", 890 NUM_FKEYS); 891 return; 892 } 893 if ((fkey.flen = strlen(string)) > MAXFK) { 894 warnx("function key string too long (%d > %d)", 895 fkey.flen, MAXFK); 896 return; 897 } 898 strcpy(fkey.keydef, string); 899 fkey.keynum -= 1; 900 if (ioctl(0, SETFKEY, &fkey) < 0) 901 warn("setting function key"); 902 } 903 904 void 905 set_bell_values(char *opt) 906 { 907 int bell, duration, pitch; 908 909 bell = 0; 910 if (!strncmp(opt, "quiet.", 6)) { 911 bell = 2; 912 opt += 6; 913 } 914 if (!strcmp(opt, "visual")) 915 bell |= 1; 916 else if (!strcmp(opt, "normal")) 917 duration = 5, pitch = 800; 918 else if (!strcmp(opt, "off")) 919 duration = 0, pitch = 0; 920 else { 921 char *v1; 922 923 bell = 0; 924 duration = strtol(opt, &v1, 0); 925 if ((duration < 0) || (*v1 != '.')) 926 goto badopt; 927 opt = ++v1; 928 pitch = strtol(opt, &v1, 0); 929 if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 930 badopt: 931 warnx("argument to -b must be duration.pitch or [quiet.]visual|normal|off"); 932 return; 933 } 934 if (pitch != 0) 935 pitch = 1193182 / pitch; /* in Hz */ 936 duration /= 10; /* in 10 m sec */ 937 } 938 939 ioctl(0, CONS_BELLTYPE, &bell); 940 if ((bell & ~2) == 0) 941 fprintf(stderr, "[=%d;%dB", pitch, duration); 942 } 943 944 void 945 set_keyrates(char *opt) 946 { 947 int arg[2]; 948 int repeat; 949 int delay; 950 int r, d; 951 952 if (!strcmp(opt, "slow")) { 953 delay = 1000, repeat = 500; 954 d = 3, r = 31; 955 } else if (!strcmp(opt, "normal")) { 956 delay = 500, repeat = 125; 957 d = 1, r = 15; 958 } else if (!strcmp(opt, "fast")) { 959 delay = repeat = 0; 960 d = r = 0; 961 } else { 962 int n; 963 char *v1; 964 965 delay = strtol(opt, &v1, 0); 966 if ((delay < 0) || (*v1 != '.')) 967 goto badopt; 968 opt = ++v1; 969 repeat = strtol(opt, &v1, 0); 970 if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 971 badopt: 972 warnx("argument to -r must be delay.repeat or slow|normal|fast"); 973 return; 974 } 975 for (n = 0; n < ndelays - 1; n++) 976 if (delay <= delays[n]) 977 break; 978 d = n; 979 for (n = 0; n < nrepeats - 1; n++) 980 if (repeat <= repeats[n]) 981 break; 982 r = n; 983 } 984 985 arg[0] = delay; 986 arg[1] = repeat; 987 if (ioctl(0, KDSETREPEAT, arg)) { 988 if (ioctl(0, KDSETRAD, (d << 5) | r)) 989 warn("setting keyboard rate"); 990 } 991 } 992 993 static const char * 994 get_kbd_type_name(int type) 995 { 996 static struct { 997 int type; 998 const char *name; 999 } name_table[] = { 1000 { KB_84, "AT 84" }, 1001 { KB_101, "AT 101/102" }, 1002 { KB_OTHER, "generic" }, 1003 }; 1004 unsigned int i; 1005 1006 for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 1007 if (type == name_table[i].type) 1008 return name_table[i].name; 1009 } 1010 return "unknown"; 1011 } 1012 1013 void 1014 show_kbd_info(void) 1015 { 1016 keyboard_info_t info; 1017 1018 if (ioctl(0, KDGKBINFO, &info) == -1) { 1019 warn("unable to obtain keyboard information"); 1020 return; 1021 } 1022 printf("kbd%d:\n", info.kb_index); 1023 printf(" %.*s%d, type:%s (%d)\n", 1024 (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 1025 get_kbd_type_name(info.kb_type), info.kb_type); 1026 } 1027 1028 void 1029 set_keyboard(char *device) 1030 { 1031 keyboard_info_t info; 1032 int fd; 1033 1034 fd = open(device, O_RDONLY); 1035 if (fd < 0) { 1036 warn("cannot open %s", device); 1037 return; 1038 } 1039 if (ioctl(fd, KDGKBINFO, &info) == -1) { 1040 warn("unable to obtain keyboard information"); 1041 close(fd); 1042 return; 1043 } 1044 /* 1045 * The keyboard device driver won't release the keyboard by 1046 * the following ioctl, but it automatically will, when the device 1047 * is closed. So, we don't check error here. 1048 */ 1049 ioctl(fd, CONS_RELKBD, 0); 1050 close(fd); 1051 #if 1 1052 printf("kbd%d\n", info.kb_index); 1053 printf(" %.*s%d, type:%s (%d)\n", 1054 (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 1055 get_kbd_type_name(info.kb_type), info.kb_type); 1056 #endif 1057 1058 if (ioctl(0, CONS_SETKBD, info.kb_index) == -1) 1059 warn("unable to set keyboard"); 1060 } 1061 1062 void 1063 release_keyboard(void) 1064 { 1065 keyboard_info_t info; 1066 1067 /* 1068 * If stdin is not associated with a keyboard, the following ioctl 1069 * will fail. 1070 */ 1071 if (ioctl(0, KDGKBINFO, &info) == -1) { 1072 warn("unable to obtain keyboard information"); 1073 return; 1074 } 1075 #if 1 1076 printf("kbd%d\n", info.kb_index); 1077 printf(" %.*s%d, type:%s (%d)\n", 1078 (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 1079 get_kbd_type_name(info.kb_type), info.kb_type); 1080 #endif 1081 if (ioctl(0, CONS_RELKBD, 0) == -1) 1082 warn("unable to release the keyboard"); 1083 } 1084 1085 1086 void 1087 usage() 1088 { 1089 fprintf(stderr, "%s\n%s\n%s\n", 1090 "usage: kbdcontrol [-dFKix] [-b duration.pitch | [quiet.]belltype]", 1091 " [-r delay.repeat | speed] [-l mapfile] [-f # string]", 1092 " [-k device] [-L mapfile]"); 1093 exit(1); 1094 } 1095 1096 1097 int 1098 main(int argc, char **argv) 1099 { 1100 int opt; 1101 1102 while((opt = getopt(argc, argv, "b:df:iKk:Fl:L:r:x")) != -1) 1103 switch(opt) { 1104 case 'b': 1105 set_bell_values(optarg); 1106 break; 1107 case 'd': 1108 print_keymap(); 1109 break; 1110 case 'l': 1111 load_keymap(optarg, 0); 1112 break; 1113 case 'L': 1114 load_keymap(optarg, 1); 1115 break; 1116 case 'f': 1117 set_functionkey(optarg, 1118 nextarg(argc, argv, &optind, 'f')); 1119 break; 1120 case 'F': 1121 load_default_functionkeys(); 1122 break; 1123 case 'i': 1124 show_kbd_info(); 1125 break; 1126 case 'K': 1127 release_keyboard(); 1128 break; 1129 case 'k': 1130 set_keyboard(optarg); 1131 break; 1132 case 'r': 1133 set_keyrates(optarg); 1134 break; 1135 case 'x': 1136 hex = 1; 1137 break; 1138 default: 1139 usage(); 1140 } 1141 if ((optind != argc) || (argc == 1)) 1142 usage(); 1143 exit(0); 1144 } 1145