kbdcontrol.c revision 38044
1130561Sobrien/*- 2130561Sobrien * Copyright (c) 1994-1995 S�ren Schmidt 3130561Sobrien * All rights reserved. 4130561Sobrien * 5130561Sobrien * Redistribution and use in source and binary forms, with or without 6130561Sobrien * modification, are permitted provided that the following conditions 7130561Sobrien * are met: 8130561Sobrien * 1. Redistributions of source code must retain the above copyright 9130561Sobrien * notice, this list of conditions and the following disclaimer, 10130561Sobrien * in this position and unchanged. 11130561Sobrien * 2. Redistributions in binary form must reproduce the above copyright 12130561Sobrien * notice, this list of conditions and the following disclaimer in the 13130561Sobrien * documentation and/or other materials provided with the distribution. 14130561Sobrien * 3. The name of the author may not be used to endorse or promote products 15130561Sobrien * derived from this software withough specific prior written permission 16130561Sobrien * 17130561Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18130561Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19130561Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20218822Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21218822Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22130561Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23130561Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24130561Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25130561Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26130561Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27130561Sobrien */ 28130561Sobrien 29130561Sobrien#ifndef lint 30130561Sobrienstatic const char rcsid[] = 31130561Sobrien "$Id: kbdcontrol.c,v 1.14 1998/05/05 19:02:01 des Exp $"; 32130561Sobrien#endif /* not lint */ 33130561Sobrien 34130561Sobrien#include <ctype.h> 35130561Sobrien#include <err.h> 36130561Sobrien#include <stdio.h> 37130561Sobrien#include <stdlib.h> 38130561Sobrien#include <string.h> 39130561Sobrien#include <unistd.h> 40130561Sobrien#include <machine/console.h> 41130561Sobrien#include "path.h" 42130561Sobrien#include "lex.h" 43130561Sobrien 44130561Sobrienchar ctrl_names[32][4] = { 45130561Sobrien "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 46130561Sobrien "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 47130561Sobrien "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 48130561Sobrien "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "ns " 49130561Sobrien }; 50130561Sobrien 51130561Sobrienchar acc_names[15][5] = { 52130561Sobrien "dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot", 53130561Sobrien "duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo", 54130561Sobrien "dcar", 55130561Sobrien }; 56130561Sobrien 57130561Sobrienchar acc_names_u[15][5] = { 58130561Sobrien "DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT", 59130561Sobrien "DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO", 60130561Sobrien "DCAR", 61130561Sobrien }; 62130561Sobrien 63130561Sobrienchar fkey_table[96][MAXFK] = { 64130561Sobrien/* 01-04 */ "\033[M", "\033[N", "\033[O", "\033[P", 65130561Sobrien/* 05-08 */ "\033[Q", "\033[R", "\033[S", "\033[T", 66130561Sobrien/* 09-12 */ "\033[U", "\033[V", "\033[W", "\033[X", 67218822Sdim/* 13-16 */ "\033[Y", "\033[Z", "\033[a", "\033[b", 68218822Sdim/* 17-20 */ "\033[c", "\033[d", "\033[e", "\033[f", 69218822Sdim/* 21-24 */ "\033[g", "\033[h", "\033[i", "\033[j", 70218822Sdim/* 25-28 */ "\033[k", "\033[l", "\033[m", "\033[n", 71218822Sdim/* 29-32 */ "\033[o", "\033[p", "\033[q", "\033[r", 72218822Sdim/* 33-36 */ "\033[s", "\033[t", "\033[u", "\033[v", 73130561Sobrien/* 37-40 */ "\033[w", "\033[x", "\033[y", "\033[z", 74130561Sobrien/* 41-44 */ "\033[@", "\033[[", "\033[\\","\033[]", 75130561Sobrien/* 45-48 */ "\033[^", "\033[_", "\033[`", "\033[{", 76218822Sdim/* 49-52 */ "\033[H", "\033[A", "\033[I", "-" , 77130561Sobrien/* 53-56 */ "\033[D", "\033[E", "\033[C", "+" , 78130561Sobrien/* 57-60 */ "\033[F", "\033[B", "\033[G", "\033[L", 79130561Sobrien/* 61-64 */ "\177", "\033[J", "\033[~", "\033[}", 80130561Sobrien/* 65-68 */ "" , "" , "" , "" , 81130561Sobrien/* 69-72 */ "" , "" , "" , "" , 82130561Sobrien/* 73-76 */ "" , "" , "" , "" , 83130561Sobrien/* 77-80 */ "" , "" , "" , "" , 84130561Sobrien/* 81-84 */ "" , "" , "" , "" , 85130561Sobrien/* 85-88 */ "" , "" , "" , "" , 86130561Sobrien/* 89-92 */ "" , "" , "" , "" , 87130561Sobrien/* 93-96 */ "" , "" , "" , "" , 88130561Sobrien }; 89130561Sobrien 90130561Sobrienconst int delays[] = {250, 500, 750, 1000}; 91130561Sobrienconst int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 92130561Sobrien 68, 76, 84, 92, 100, 110, 118, 126, 93130561Sobrien 136, 152, 168, 184, 200, 220, 236, 252, 94130561Sobrien 272, 304, 336, 368, 400, 440, 472, 504}; 95130561Sobrienconst int ndelays = (sizeof(delays) / sizeof(int)); 96130561Sobrienconst int nrepeats = (sizeof(repeats) / sizeof(int)); 97130561Sobrienint hex = 0; 98130561Sobrienint number; 99130561Sobrienchar letter; 100130561Sobrienint token; 101130561Sobrien 102130561Sobrienstatic void usage __P((void)); 103130561Sobrien 104130561Sobrienchar * 105130561Sobriennextarg(int ac, char **av, int *indp, int oc) 106130561Sobrien{ 107130561Sobrien if (*indp < ac) 108130561Sobrien return(av[(*indp)++]); 109130561Sobrien warnx("option requires two arguments -- %c", oc); 110130561Sobrien usage(); 111130561Sobrien return(""); 112130561Sobrien} 113130561Sobrien 114130561Sobrien 115130561Sobrienchar * 116130561Sobrienmkfullname(const char *s1, const char *s2, const char *s3) 117130561Sobrien{ 118130561Sobrien static char *buf = NULL; 119130561Sobrien static int bufl = 0; 120218822Sdim int f; 121130561Sobrien 122130561Sobrien f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 123130561Sobrien if (f > bufl) 124130561Sobrien if (buf) 125130561Sobrien buf = (char *)realloc(buf, f); 126130561Sobrien else 127130561Sobrien buf = (char *)malloc(f); 128130561Sobrien if (!buf) { 129130561Sobrien bufl = 0; 130130561Sobrien return(NULL); 131218822Sdim } 132218822Sdim 133218822Sdim bufl = f; 134218822Sdim strcpy(buf, s1); 135218822Sdim strcat(buf, s2); 136218822Sdim strcat(buf, s3); 137218822Sdim return(buf); 138218822Sdim} 139218822Sdim 140218822Sdim 141218822Sdimint 142218822Sdimget_entry() 143218822Sdim{ 144218822Sdim switch ((token = yylex())) { 145218822Sdim case TNOP: 146218822Sdim return NOP | 0x100; 147218822Sdim case TLSH: 148218822Sdim return LSH | 0x100; 149218822Sdim case TRSH: 150218822Sdim return RSH | 0x100; 151218822Sdim case TCLK: 152218822Sdim return CLK | 0x100; 153218822Sdim case TNLK: 154218822Sdim return NLK | 0x100; 155130561Sobrien case TSLK: 156130561Sobrien return SLK | 0x100; 157130561Sobrien case TBTAB: 158 return BTAB | 0x100; 159 case TLALT: 160 return LALT | 0x100; 161 case TLCTR: 162 return LCTR | 0x100; 163 case TNEXT: 164 return NEXT | 0x100; 165 case TRCTR: 166 return RCTR | 0x100; 167 case TRALT: 168 return RALT | 0x100; 169 case TALK: 170 return ALK | 0x100; 171 case TASH: 172 return ASH | 0x100; 173 case TMETA: 174 return META | 0x100; 175 case TRBT: 176 return RBT | 0x100; 177 case TDBG: 178 return DBG | 0x100; 179 case TSUSP: 180 return SUSP | 0x100; 181 case TACC: 182 if (ACC(number) > L_ACC) 183 return -1; 184 return ACC(number) | 0x100; 185 case TFUNC: 186 if (F(number) > L_FN) 187 return -1; 188 return F(number) | 0x100; 189 case TSCRN: 190 if (S(number) > L_SCR) 191 return -1; 192 return S(number) | 0x100; 193 case TLET: 194 return (unsigned char)letter; 195 case TNUM: 196 if (number < 0 || number > 255) 197 return -1; 198 return number; 199 default: 200 return -1; 201 } 202} 203 204int 205get_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap) 206{ 207 int c; 208 209 yyin = fd; 210 211 if (token < 0) 212 token = yylex(); 213 switch (token) { 214 case TNUM: 215 c = get_key_definition_line(keymap); 216 if (c < 0) 217 errx(1, "invalid key definition"); 218 if (c > keymap->n_keys) 219 keymap->n_keys = c; 220 break; 221 case TACC: 222 c = get_accent_definition_line(accentmap); 223 if (c < 0) 224 errx(1, "invalid accent key definition"); 225 if (c > accentmap->n_accs) 226 accentmap->n_accs = c; 227 break; 228 case 0: 229 /* EOF */ 230 return -1; 231 default: 232 errx(1, "illegal definition line"); 233 } 234 return c; 235} 236 237int 238get_key_definition_line(keymap_t *map) 239{ 240 int i, def, scancode; 241 242 /* check scancode number */ 243 if (number < 0 || number >= NUM_KEYS) 244 return -1; 245 scancode = number; 246 247 /* get key definitions */ 248 map->key[scancode].spcl = 0; 249 for (i=0; i<NUM_STATES; i++) { 250 if ((def = get_entry()) == -1) 251 return -1; 252 if (def & 0x100) 253 map->key[scancode].spcl |= (0x80 >> i); 254 map->key[scancode].map[i] = def & 0xFF; 255 } 256 /* get lock state key def */ 257 if ((token = yylex()) != TFLAG) 258 return -1; 259 map->key[scancode].flgs = number; 260 token = yylex(); 261 return (scancode + 1); 262} 263 264int 265get_accent_definition_line(accentmap_t *map) 266{ 267 int accent; 268 int c1, c2; 269 int i; 270 271 if (ACC(number) < F_ACC || ACC(number) > L_ACC) 272 /* number out of range */ 273 return -1; 274 accent = number; 275 if (map->acc[accent].accchar != 0) { 276 /* this entry has already been defined before! */ 277 errx(1, "duplicated accent key definition"); 278 } 279 280 switch ((token = yylex())) { 281 case TLET: 282 map->acc[accent].accchar = letter; 283 break; 284 case TNUM: 285 map->acc[accent].accchar = number; 286 break; 287 default: 288 return -1; 289 } 290 291 for (i = 0; (token = yylex()) == '(';) { 292 switch ((token = yylex())) { 293 case TLET: 294 c1 = letter; 295 break; 296 case TNUM: 297 c1 = number; 298 break; 299 default: 300 return -1; 301 } 302 switch ((token = yylex())) { 303 case TLET: 304 c2 = letter; 305 break; 306 case TNUM: 307 c2 = number; 308 break; 309 default: 310 return -1; 311 } 312 if ((token = yylex()) != ')') 313 return -1; 314 if (i >= NUM_ACCENTCHARS) { 315 warnx("too many accented characters, ignored"); 316 continue; 317 } 318 map->acc[accent].map[i][0] = c1; 319 map->acc[accent].map[i][1] = c2; 320 ++i; 321 } 322 return (accent + 1); 323} 324 325void 326print_entry(FILE *fp, int value) 327{ 328 int val = value & 0xFF; 329 330 switch (value) { 331 case NOP | 0x100: 332 fprintf(fp, " nop "); 333 break; 334 case LSH | 0x100: 335 fprintf(fp, " lshift"); 336 break; 337 case RSH | 0x100: 338 fprintf(fp, " rshift"); 339 break; 340 case CLK | 0x100: 341 fprintf(fp, " clock "); 342 break; 343 case NLK | 0x100: 344 fprintf(fp, " nlock "); 345 break; 346 case SLK | 0x100: 347 fprintf(fp, " slock "); 348 break; 349 case BTAB | 0x100: 350 fprintf(fp, " btab "); 351 break; 352 case LALT | 0x100: 353 fprintf(fp, " lalt "); 354 break; 355 case LCTR | 0x100: 356 fprintf(fp, " lctrl "); 357 break; 358 case NEXT | 0x100: 359 fprintf(fp, " nscr "); 360 break; 361 case RCTR | 0x100: 362 fprintf(fp, " rctrl "); 363 break; 364 case RALT | 0x100: 365 fprintf(fp, " ralt "); 366 break; 367 case ALK | 0x100: 368 fprintf(fp, " alock "); 369 break; 370 case ASH | 0x100: 371 fprintf(fp, " ashift"); 372 break; 373 case META | 0x100: 374 fprintf(fp, " meta "); 375 break; 376 case RBT | 0x100: 377 fprintf(fp, " boot "); 378 break; 379 case DBG | 0x100: 380 fprintf(fp, " debug "); 381 break; 382 case SUSP | 0x100: 383 fprintf(fp, " susp "); 384 break; 385 default: 386 if (value & 0x100) { 387 if (val >= F_FN && val <= L_FN) 388 fprintf(fp, " fkey%02d", val - F_FN + 1); 389 else if (val >= F_SCR && val <= L_SCR) 390 fprintf(fp, " scr%02d ", val - F_SCR + 1); 391 else if (val >= F_ACC && val <= L_ACC) 392 fprintf(fp, " %-6s", acc_names[val - F_ACC]); 393 else if (hex) 394 fprintf(fp, " 0x%02x ", val); 395 else 396 fprintf(fp, " %3d ", val); 397 } 398 else { 399 if (val < ' ') 400 fprintf(fp, " %s ", ctrl_names[val]); 401 else if (val == 127) 402 fprintf(fp, " del "); 403 else if (isascii(val) && isprint(val)) 404 fprintf(fp, " '%c' ", val); 405 else if (hex) 406 fprintf(fp, " 0x%02x ", val); 407 else 408 fprintf(fp, " %3d ", val); 409 } 410 } 411} 412 413 414void 415print_key_definition_line(FILE *fp, int scancode, struct key_t *key) 416{ 417 int i; 418 419 /* print scancode number */ 420 if (hex) 421 fprintf(fp, " 0x%02x ", scancode); 422 else 423 fprintf(fp, " %03d ", scancode); 424 425 /* print key definitions */ 426 for (i=0; i<NUM_STATES; i++) { 427 if (key->spcl & (0x80 >> i)) 428 print_entry(fp, key->map[i] | 0x100); 429 else 430 print_entry(fp, key->map[i]); 431 } 432 433 /* print lock state key def */ 434 switch (key->flgs) { 435 case 0: 436 fprintf(fp, " O\n"); 437 break; 438 case 1: 439 fprintf(fp, " C\n"); 440 break; 441 case 2: 442 fprintf(fp, " N\n"); 443 break; 444 case 3: 445 fprintf(fp, " B\n"); 446 break; 447 } 448} 449 450void 451print_accent_definition_line(FILE *fp, int accent, struct acc_t *key) 452{ 453 int c; 454 int i; 455 456 if (key->accchar == 0) 457 return; 458 459 /* print accent number */ 460 fprintf(fp, " %-6s", acc_names[accent]); 461 if (isascii(key->accchar) && isprint(key->accchar)) 462 fprintf(fp, "'%c' ", key->accchar); 463 else if (hex) 464 fprintf(fp, "0x%02x ", key->accchar); 465 else 466 fprintf(fp, "%03d ", key->accchar); 467 468 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 469 c = key->map[i][0]; 470 if (c == 0) 471 break; 472 if ((i > 0) && ((i % 4) == 0)) 473 fprintf(fp, "\n "); 474 if (isascii(c) && isprint(c)) 475 fprintf(fp, "( '%c' ", c); 476 else if (hex) 477 fprintf(fp, "(0x%02x ", c); 478 else 479 fprintf(fp, "( %03d ", c); 480 c = key->map[i][1]; 481 if (isascii(c) && isprint(c)) 482 fprintf(fp, "'%c' ) ", c); 483 else if (hex) 484 fprintf(fp, "0x%02x) ", c); 485 else 486 fprintf(fp, "%03d ) ", c); 487 } 488 fprintf(fp, "\n"); 489} 490 491void 492dump_entry(int value) 493{ 494 if (value & 0x100) { 495 value &= 0x00ff; 496 switch (value) { 497 case NOP: 498 printf(" NOP, "); 499 break; 500 case LSH: 501 printf(" LSH, "); 502 break; 503 case RSH: 504 printf(" RSH, "); 505 break; 506 case CLK: 507 printf(" CLK, "); 508 break; 509 case NLK: 510 printf(" NLK, "); 511 break; 512 case SLK: 513 printf(" SLK, "); 514 break; 515 case BTAB: 516 printf(" BTAB, "); 517 break; 518 case LALT: 519 printf(" LALT, "); 520 break; 521 case LCTR: 522 printf(" LCTR, "); 523 break; 524 case NEXT: 525 printf(" NEXT, "); 526 break; 527 case RCTR: 528 printf(" RCTR, "); 529 break; 530 case RALT: 531 printf(" RALT, "); 532 break; 533 case ALK: 534 printf(" ALK, "); 535 break; 536 case ASH: 537 printf(" ASH, "); 538 break; 539 case META: 540 printf(" META, "); 541 break; 542 case RBT: 543 printf(" RBT, "); 544 break; 545 case DBG: 546 printf(" DBG, "); 547 break; 548 case SUSP: 549 printf(" SUSP, "); 550 break; 551 default: 552 if (value >= F_FN && value <= L_FN) 553 printf(" F(%2d),", value - F_FN + 1); 554 else if (value >= F_SCR && value <= L_SCR) 555 printf(" S(%2d),", value - F_SCR + 1); 556 else if (value >= F_ACC && value <= L_ACC) 557 printf(" %-4s, ", acc_names_u[value - F_ACC]); 558 else 559 printf(" 0x%02X, ", value); 560 break; 561 } 562 } else if (value == '\'') { 563 printf(" '\\'', "); 564 } else if (value == '\\') { 565 printf(" '\\\\', "); 566 } else if (isascii(value) && isprint(value)) { 567 printf(" '%c', ", value); 568 } else { 569 printf(" 0x%02X, ", value); 570 } 571} 572 573void 574dump_key_definition(char *name, keymap_t *keymap) 575{ 576 int i, j; 577 578 printf("static keymap_t keymap_%s = { 0x%02x, {\n", 579 name, (unsigned)keymap->n_keys); 580 printf( 581"/* alt\n" 582" * scan cntrl alt alt cntrl\n" 583" * code base shift cntrl shift alt shift cntrl shift spcl flgs\n" 584" * ---------------------------------------------------------------------------\n" 585" */\n"); 586 for (i = 0; i < keymap->n_keys; i++) { 587 printf("/*%02x*/{{", i); 588 for (j = 0; j < NUM_STATES; j++) { 589 if (keymap->key[i].spcl & (0x80 >> j)) 590 dump_entry(keymap->key[i].map[j] | 0x100); 591 else 592 dump_entry(keymap->key[i].map[j]); 593 } 594 printf("}, 0x%02X,0x%02X },\n", 595 (unsigned)keymap->key[i].spcl, 596 (unsigned)keymap->key[i].flgs); 597 } 598 printf("} };\n\n"); 599} 600 601void 602dump_accent_definition(char *name, accentmap_t *accentmap) 603{ 604 int i, j; 605 int c; 606 607 printf("static accentmap_t accentmap_%s = { %d", 608 name, accentmap->n_accs); 609 if (accentmap->n_accs <= 0) { 610 printf(" };\n\n"); 611 return; 612 } 613 printf(", {\n"); 614 for (i = 0; i < NUM_DEADKEYS; i++) { 615 printf(" /* %s=%d */\n {", acc_names[i], i); 616 c = accentmap->acc[i].accchar; 617 if (c == '\'') 618 printf(" '\\'', {"); 619 else if (c == '\\') 620 printf(" '\\\\', {"); 621 else if (isascii(c) && isprint(c)) 622 printf(" '%c', {", c); 623 else if (c == 0) { 624 printf(" 0x00 }, \n"); 625 continue; 626 } else 627 printf(" 0x%02x, {", c); 628 for (j = 0; j < NUM_ACCENTCHARS; j++) { 629 c = accentmap->acc[i].map[j][0]; 630 if (c == 0) 631 break; 632 if ((j > 0) && ((j % 4) == 0)) 633 printf("\n\t "); 634 if (isascii(c) && isprint(c)) 635 printf(" { '%c',", c); 636 else 637 printf(" { 0x%02x,", c); 638 printf("0x%02x },", accentmap->acc[i].map[j][1]); 639 } 640 printf(" }, },\n"); 641 } 642 printf("} };\n\n"); 643} 644 645void 646load_keymap(char *opt, int dumponly) 647{ 648 keymap_t keymap; 649 accentmap_t accentmap; 650 FILE *fd; 651 int i; 652 char *name, *cp; 653 char *prefix[] = {"", "", KEYMAP_PATH, KEYMAP_PATH, NULL}; 654 char *postfix[] = {"", ".kbd", "", ".kbd"}; 655 656 for (i=0; prefix[i]; i++) { 657 name = mkfullname(prefix[i], opt, postfix[i]); 658 if ((fd = fopen(name, "r"))) 659 break; 660 } 661 if (fd == NULL) { 662 warn("keymap file not found"); 663 return; 664 } 665 memset(&keymap, 0, sizeof(keymap)); 666 memset(&accentmap, 0, sizeof(accentmap)); 667 token = -1; 668 while (1) { 669 if (get_definition_line(fd, &keymap, &accentmap) < 0) 670 break; 671 } 672 if (dumponly) { 673 /* fix up the filename to make it a valid C identifier */ 674 for (cp = opt; *cp; cp++) 675 if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_'; 676 printf("/*\n" 677 " * Automatically generated from %s.\n" 678 " * DO NOT EDIT!\n" 679 " */\n", name); 680 dump_key_definition(opt, &keymap); 681 dump_accent_definition(opt, &accentmap); 682 return; 683 } 684 if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) { 685 warn("setting keymap"); 686 fclose(fd); 687 return; 688 } 689 if ((accentmap.n_accs > 0) 690 && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) { 691 warn("setting accentmap"); 692 fclose(fd); 693 return; 694 } 695} 696 697void 698print_keymap() 699{ 700 keymap_t keymap; 701 accentmap_t accentmap; 702 int i; 703 704 if (ioctl(0, GIO_KEYMAP, &keymap) < 0) 705 err(1, "getting keymap"); 706 if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) 707 memset(&accentmap, 0, sizeof(accentmap)); 708 printf( 709"# alt\n" 710"# scan cntrl alt alt cntrl lock\n" 711"# code base shift cntrl shift alt shift cntrl shift state\n" 712"# ------------------------------------------------------------------\n" 713 ); 714 for (i=0; i<keymap.n_keys; i++) 715 print_key_definition_line(stdout, i, &keymap.key[i]); 716 717 printf("\n"); 718 for (i = 0; i < NUM_DEADKEYS; i++) 719 print_accent_definition_line(stdout, i, &accentmap.acc[i]); 720 721} 722 723 724void 725load_default_functionkeys() 726{ 727 fkeyarg_t fkey; 728 int i; 729 730 for (i=0; i<NUM_FKEYS; i++) { 731 fkey.keynum = i; 732 strcpy(fkey.keydef, fkey_table[i]); 733 fkey.flen = strlen(fkey_table[i]); 734 if (ioctl(0, SETFKEY, &fkey) < 0) 735 warn("setting function key"); 736 } 737} 738 739void 740set_functionkey(char *keynumstr, char *string) 741{ 742 fkeyarg_t fkey; 743 744 if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 745 load_default_functionkeys(); 746 return; 747 } 748 fkey.keynum = atoi(keynumstr); 749 if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 750 warnx("function key number must be between 1 and %d", 751 NUM_FKEYS); 752 return; 753 } 754 if ((fkey.flen = strlen(string)) > MAXFK) { 755 warnx("function key string too long (%d > %d)", 756 fkey.flen, MAXFK); 757 return; 758 } 759 strcpy(fkey.keydef, string); 760 fkey.keynum -= 1; 761 if (ioctl(0, SETFKEY, &fkey) < 0) 762 warn("setting function key"); 763} 764 765 766void 767set_bell_values(char *opt) 768{ 769 int bell, duration, pitch; 770 771 bell = 0; 772 if (!strncmp(opt, "quiet.", 6)) { 773 bell = 2; 774 opt += 6; 775 } 776 if (!strcmp(opt, "visual")) 777 bell |= 1; 778 else if (!strcmp(opt, "normal")) 779 duration = 5, pitch = 800; 780 else { 781 char *v1; 782 783 bell = 0; 784 duration = strtol(opt, &v1, 0); 785 if ((duration < 0) || (*v1 != '.')) 786 goto badopt; 787 opt = ++v1; 788 pitch = strtol(opt, &v1, 0); 789 if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 790badopt: 791 warnx("argument to -b must be DURATION.PITCH"); 792 return; 793 } 794 if (pitch != 0) 795 pitch = 1193182 / pitch; /* in Hz */ 796 duration /= 10; /* in 10 m sec */ 797 } 798 799 ioctl(0, CONS_BELLTYPE, &bell); 800 if ((bell & ~2) == 0) 801 fprintf(stderr, "[=%d;%dB", pitch, duration); 802} 803 804 805void 806set_keyrates(char *opt) 807{ 808struct { 809 int rep:5; 810 int del:2; 811 int pad:1; 812 }rate; 813 814 if (!strcmp(opt, "slow")) 815 rate.del = 3, rate.rep = 31; 816 else if (!strcmp(opt, "normal")) 817 rate.del = 1, rate.rep = 15; 818 else if (!strcmp(opt, "fast")) 819 rate.del = rate.rep = 0; 820 else { 821 int n; 822 int delay, repeat; 823 char *v1; 824 825 delay = strtol(opt, &v1, 0); 826 if ((delay < 0) || (*v1 != '.')) 827 goto badopt; 828 opt = ++v1; 829 repeat = strtol(opt, &v1, 0); 830 if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 831badopt: 832 warnx("argument to -r must be delay.repeat"); 833 return; 834 } 835 for (n = 0; n < ndelays - 1; n++) 836 if (delay <= delays[n]) 837 break; 838 rate.del = n; 839 for (n = 0; n < nrepeats - 1; n++) 840 if (repeat <= repeats[n]) 841 break; 842 rate.rep = n; 843 } 844 845 if (ioctl(0, KDSETRAD, rate) < 0) 846 warn("setting keyboard rate"); 847} 848 849 850void 851set_history(char *opt) 852{ 853 int size; 854 855 size = atoi(opt); 856 if ((*opt == '\0') || size < 0) { 857 warnx("argument must be a positive number"); 858 return; 859 } 860 if (ioctl(0, CONS_HISTORY, &size) == -1) 861 warn("setting history buffer size"); 862} 863 864 865static void 866usage() 867{ 868 fprintf(stderr, "%s\n%s\n%s\n", 869"usage: kbdcontrol [-dFx] [-b duration.pitch | [quiet.]belltype]", 870" [-r delay.repeat | speed] [-l mapfile] [-f # string]", 871" [-h size] [-L mapfile]"); 872 exit(1); 873} 874 875 876void 877main(int argc, char **argv) 878{ 879 int opt; 880 881 while((opt = getopt(argc, argv, "b:df:h:Fl:L:r:x")) != -1) 882 switch(opt) { 883 case 'b': 884 set_bell_values(optarg); 885 break; 886 case 'd': 887 print_keymap(); 888 break; 889 case 'l': 890 load_keymap(optarg, 0); 891 break; 892 case 'L': 893 load_keymap(optarg, 1); 894 break; 895 case 'f': 896 set_functionkey(optarg, 897 nextarg(argc, argv, &optind, 'f')); 898 break; 899 case 'F': 900 load_default_functionkeys(); 901 break; 902 case 'h': 903 set_history(optarg); 904 break; 905 case 'r': 906 set_keyrates(optarg); 907 break; 908 case 'x': 909 hex = 1; 910 break; 911 default: 912 usage(); 913 } 914 if ((optind != argc) || (argc == 1)) 915 usage(); 916 exit(0); 917} 918 919 920