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