kbdcontrol.c revision 66834
1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 1994-1995 S�ren Schmidt 3191783Srmacklem * All rights reserved. 4191783Srmacklem * 5191783Srmacklem * Redistribution and use in source and binary forms, with or without 6191783Srmacklem * modification, are permitted provided that the following conditions 7191783Srmacklem * are met: 8191783Srmacklem * 1. Redistributions of source code must retain the above copyright 9191783Srmacklem * notice, this list of conditions and the following disclaimer, 10191783Srmacklem * in this position and unchanged. 11191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 12191783Srmacklem * notice, this list of conditions and the following disclaimer in the 13191783Srmacklem * documentation and/or other materials provided with the distribution. 14191783Srmacklem * 3. The name of the author may not be used to endorse or promote products 15191783Srmacklem * derived from this software withough specific prior written permission 16191783Srmacklem * 17191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18191783Srmacklem * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19191783Srmacklem * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20191783Srmacklem * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21191783Srmacklem * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22191783Srmacklem * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23191783Srmacklem * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24191783Srmacklem * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25191783Srmacklem * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26191783Srmacklem * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27191783Srmacklem */ 28191783Srmacklem 29191783Srmacklem#ifndef lint 30191783Srmacklemstatic const char rcsid[] = 31191783Srmacklem "$FreeBSD: head/usr.sbin/kbdcontrol/kbdcontrol.c 66834 2000-10-08 21:34:00Z phk $"; 32191783Srmacklem#endif /* not lint */ 33191783Srmacklem 34191783Srmacklem#include <ctype.h> 35191783Srmacklem#include <err.h> 36191783Srmacklem#include <stdio.h> 37191783Srmacklem#include <stdlib.h> 38191783Srmacklem#include <string.h> 39191783Srmacklem#include <unistd.h> 40191783Srmacklem#include <fcntl.h> 41191783Srmacklem#include <sys/kbio.h> 42191783Srmacklem#include <sys/consio.h> 43191783Srmacklem#include "path.h" 44191783Srmacklem#include "lex.h" 45191783Srmacklem 46191783Srmacklemchar ctrl_names[32][4] = { 47191783Srmacklem "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 48191783Srmacklem "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 49191783Srmacklem "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 50191783Srmacklem "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us " 51191783Srmacklem }; 52191783Srmacklem 53191783Srmacklemchar acc_names[15][5] = { 54191783Srmacklem "dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot", 55191783Srmacklem "duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo", 56191783Srmacklem "dcar", 57191783Srmacklem }; 58191783Srmacklem 59191783Srmacklemchar acc_names_u[15][5] = { 60191783Srmacklem "DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT", 61191783Srmacklem "DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO", 62191783Srmacklem "DCAR", 63191783Srmacklem }; 64191783Srmacklem 65191783Srmacklemchar fkey_table[96][MAXFK] = { 66191783Srmacklem/* 01-04 */ "\033[M", "\033[N", "\033[O", "\033[P", 67191783Srmacklem/* 05-08 */ "\033[Q", "\033[R", "\033[S", "\033[T", 68191783Srmacklem/* 09-12 */ "\033[U", "\033[V", "\033[W", "\033[X", 69191783Srmacklem/* 13-16 */ "\033[Y", "\033[Z", "\033[a", "\033[b", 70191783Srmacklem/* 17-20 */ "\033[c", "\033[d", "\033[e", "\033[f", 71191783Srmacklem/* 21-24 */ "\033[g", "\033[h", "\033[i", "\033[j", 72191783Srmacklem/* 25-28 */ "\033[k", "\033[l", "\033[m", "\033[n", 73191783Srmacklem/* 29-32 */ "\033[o", "\033[p", "\033[q", "\033[r", 74191783Srmacklem/* 33-36 */ "\033[s", "\033[t", "\033[u", "\033[v", 75191783Srmacklem/* 37-40 */ "\033[w", "\033[x", "\033[y", "\033[z", 76191783Srmacklem/* 41-44 */ "\033[@", "\033[[", "\033[\\","\033[]", 77191783Srmacklem/* 45-48 */ "\033[^", "\033[_", "\033[`", "\033[{", 78191783Srmacklem/* 49-52 */ "\033[H", "\033[A", "\033[I", "-" , 79191783Srmacklem/* 53-56 */ "\033[D", "\033[E", "\033[C", "+" , 80191783Srmacklem/* 57-60 */ "\033[F", "\033[B", "\033[G", "\033[L", 81191783Srmacklem/* 61-64 */ "\177", "\033[J", "\033[~", "\033[}", 82191783Srmacklem/* 65-68 */ "" , "" , "" , "" , 83191783Srmacklem/* 69-72 */ "" , "" , "" , "" , 84191783Srmacklem/* 73-76 */ "" , "" , "" , "" , 85191783Srmacklem/* 77-80 */ "" , "" , "" , "" , 86191783Srmacklem/* 81-84 */ "" , "" , "" , "" , 87191783Srmacklem/* 85-88 */ "" , "" , "" , "" , 88191783Srmacklem/* 89-92 */ "" , "" , "" , "" , 89191783Srmacklem/* 93-96 */ "" , "" , "" , "" , 90191783Srmacklem }; 91191783Srmacklem 92191783Srmacklemconst int delays[] = {250, 500, 750, 1000}; 93191783Srmacklemconst int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 94191783Srmacklem 68, 76, 84, 92, 100, 110, 118, 126, 95191783Srmacklem 136, 152, 168, 184, 200, 220, 236, 252, 96191783Srmacklem 272, 304, 336, 368, 400, 440, 472, 504}; 97191783Srmacklemconst int ndelays = (sizeof(delays) / sizeof(int)); 98191783Srmacklemconst int nrepeats = (sizeof(repeats) / sizeof(int)); 99191783Srmacklemint hex = 0; 100191783Srmacklemint number; 101191783Srmacklemchar letter; 102191783Srmacklemint token; 103191783Srmacklem 104191783Srmacklemstatic void usage __P((void)); 105191783Srmacklem 106191783Srmacklemchar * 107191783Srmacklemnextarg(int ac, char **av, int *indp, int oc) 108191783Srmacklem{ 109191783Srmacklem if (*indp < ac) 110191783Srmacklem return(av[(*indp)++]); 111191783Srmacklem warnx("option requires two arguments -- %c", oc); 112191783Srmacklem usage(); 113191783Srmacklem return(""); 114191783Srmacklem} 115191783Srmacklem 116191783Srmacklem 117191783Srmacklemchar * 118191783Srmacklemmkfullname(const char *s1, const char *s2, const char *s3) 119191783Srmacklem{ 120191783Srmacklem static char *buf = NULL; 121191783Srmacklem static int bufl = 0; 122191783Srmacklem int f; 123191783Srmacklem 124191783Srmacklem f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 125191783Srmacklem if (f > bufl) 126191783Srmacklem if (buf) 127191783Srmacklem buf = (char *)realloc(buf, f); 128191783Srmacklem else 129191783Srmacklem buf = (char *)malloc(f); 130191783Srmacklem if (!buf) { 131191783Srmacklem bufl = 0; 132191783Srmacklem return(NULL); 133191783Srmacklem } 134191783Srmacklem 135191783Srmacklem bufl = f; 136191783Srmacklem strcpy(buf, s1); 137191783Srmacklem strcat(buf, s2); 138191783Srmacklem strcat(buf, s3); 139191783Srmacklem return(buf); 140191783Srmacklem} 141191783Srmacklem 142191783Srmacklem 143191783Srmacklemint 144191783Srmacklemget_entry() 145191783Srmacklem{ 146191783Srmacklem switch ((token = yylex())) { 147191783Srmacklem case TNOP: 148191783Srmacklem return NOP | 0x100; 149191783Srmacklem case TLSH: 150191783Srmacklem return LSH | 0x100; 151191783Srmacklem case TRSH: 152191783Srmacklem return RSH | 0x100; 153191783Srmacklem case TCLK: 154191783Srmacklem return CLK | 0x100; 155191783Srmacklem case TNLK: 156191783Srmacklem return NLK | 0x100; 157191783Srmacklem case TSLK: 158191783Srmacklem return SLK | 0x100; 159191783Srmacklem case TBTAB: 160191783Srmacklem return BTAB | 0x100; 161191783Srmacklem case TLALT: 162191783Srmacklem return LALT | 0x100; 163191783Srmacklem case TLCTR: 164191783Srmacklem return LCTR | 0x100; 165191783Srmacklem case TNEXT: 166191783Srmacklem return NEXT | 0x100; 167191783Srmacklem case TPREV: 168191783Srmacklem return PREV | 0x100; 169191783Srmacklem case TRCTR: 170191783Srmacklem return RCTR | 0x100; 171191783Srmacklem case TRALT: 172191783Srmacklem return RALT | 0x100; 173191783Srmacklem case TALK: 174191783Srmacklem return ALK | 0x100; 175191783Srmacklem case TASH: 176191783Srmacklem return ASH | 0x100; 177191783Srmacklem case TMETA: 178191783Srmacklem return META | 0x100; 179191783Srmacklem case TRBT: 180191783Srmacklem return RBT | 0x100; 181191783Srmacklem case TDBG: 182191783Srmacklem return DBG | 0x100; 183191783Srmacklem case TSUSP: 184191783Srmacklem return SUSP | 0x100; 185191783Srmacklem case TSPSC: 186191783Srmacklem return SPSC | 0x100; 187191783Srmacklem case TPANIC: 188191783Srmacklem return PNC | 0x100; 189191783Srmacklem case TLSHA: 190191783Srmacklem return LSHA | 0x100; 191191783Srmacklem case TRSHA: 192191783Srmacklem return RSHA | 0x100; 193191783Srmacklem case TLCTRA: 194191783Srmacklem return LCTRA | 0x100; 195191783Srmacklem case TRCTRA: 196191783Srmacklem return RCTRA | 0x100; 197191783Srmacklem case TLALTA: 198191783Srmacklem return LALTA | 0x100; 199191783Srmacklem case TRALTA: 200191783Srmacklem return RALTA | 0x100; 201191783Srmacklem case THALT: 202191783Srmacklem return HALT | 0x100; 203191783Srmacklem case TPDWN: 204191783Srmacklem return PDWN | 0x100; 205191783Srmacklem case TACC: 206191783Srmacklem if (ACC(number) > L_ACC) 207191783Srmacklem return -1; 208 return ACC(number) | 0x100; 209 case TFUNC: 210 if (F(number) > L_FN) 211 return -1; 212 return F(number) | 0x100; 213 case TSCRN: 214 if (S(number) > L_SCR) 215 return -1; 216 return S(number) | 0x100; 217 case TLET: 218 return (unsigned char)letter; 219 case TNUM: 220 if (number < 0 || number > 255) 221 return -1; 222 return number; 223 default: 224 return -1; 225 } 226} 227 228int 229get_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap) 230{ 231 int c; 232 233 yyin = fd; 234 235 if (token < 0) 236 token = yylex(); 237 switch (token) { 238 case TNUM: 239 c = get_key_definition_line(keymap); 240 if (c < 0) 241 errx(1, "invalid key definition"); 242 if (c > keymap->n_keys) 243 keymap->n_keys = c; 244 break; 245 case TACC: 246 c = get_accent_definition_line(accentmap); 247 if (c < 0) 248 errx(1, "invalid accent key definition"); 249 if (c > accentmap->n_accs) 250 accentmap->n_accs = c; 251 break; 252 case 0: 253 /* EOF */ 254 return -1; 255 default: 256 errx(1, "illegal definition line"); 257 } 258 return c; 259} 260 261int 262get_key_definition_line(keymap_t *map) 263{ 264 int i, def, scancode; 265 266 /* check scancode number */ 267 if (number < 0 || number >= NUM_KEYS) 268 return -1; 269 scancode = number; 270 271 /* get key definitions */ 272 map->key[scancode].spcl = 0; 273 for (i=0; i<NUM_STATES; i++) { 274 if ((def = get_entry()) == -1) 275 return -1; 276 if (def & 0x100) 277 map->key[scancode].spcl |= (0x80 >> i); 278 map->key[scancode].map[i] = def & 0xFF; 279 } 280 /* get lock state key def */ 281 if ((token = yylex()) != TFLAG) 282 return -1; 283 map->key[scancode].flgs = number; 284 token = yylex(); 285 return (scancode + 1); 286} 287 288int 289get_accent_definition_line(accentmap_t *map) 290{ 291 int accent; 292 int c1, c2; 293 int i; 294 295 if (ACC(number) < F_ACC || ACC(number) > L_ACC) 296 /* number out of range */ 297 return -1; 298 accent = number; 299 if (map->acc[accent].accchar != 0) { 300 /* this entry has already been defined before! */ 301 errx(1, "duplicated accent key definition"); 302 } 303 304 switch ((token = yylex())) { 305 case TLET: 306 map->acc[accent].accchar = letter; 307 break; 308 case TNUM: 309 map->acc[accent].accchar = number; 310 break; 311 default: 312 return -1; 313 } 314 315 for (i = 0; (token = yylex()) == '(';) { 316 switch ((token = yylex())) { 317 case TLET: 318 c1 = letter; 319 break; 320 case TNUM: 321 c1 = number; 322 break; 323 default: 324 return -1; 325 } 326 switch ((token = yylex())) { 327 case TLET: 328 c2 = letter; 329 break; 330 case TNUM: 331 c2 = number; 332 break; 333 default: 334 return -1; 335 } 336 if ((token = yylex()) != ')') 337 return -1; 338 if (i >= NUM_ACCENTCHARS) { 339 warnx("too many accented characters, ignored"); 340 continue; 341 } 342 map->acc[accent].map[i][0] = c1; 343 map->acc[accent].map[i][1] = c2; 344 ++i; 345 } 346 return (accent + 1); 347} 348 349void 350print_entry(FILE *fp, int value) 351{ 352 int val = value & 0xFF; 353 354 switch (value) { 355 case NOP | 0x100: 356 fprintf(fp, " nop "); 357 break; 358 case LSH | 0x100: 359 fprintf(fp, " lshift"); 360 break; 361 case RSH | 0x100: 362 fprintf(fp, " rshift"); 363 break; 364 case CLK | 0x100: 365 fprintf(fp, " clock "); 366 break; 367 case NLK | 0x100: 368 fprintf(fp, " nlock "); 369 break; 370 case SLK | 0x100: 371 fprintf(fp, " slock "); 372 break; 373 case BTAB | 0x100: 374 fprintf(fp, " btab "); 375 break; 376 case LALT | 0x100: 377 fprintf(fp, " lalt "); 378 break; 379 case LCTR | 0x100: 380 fprintf(fp, " lctrl "); 381 break; 382 case NEXT | 0x100: 383 fprintf(fp, " nscr "); 384 break; 385 case PREV | 0x100: 386 fprintf(fp, " pscr "); 387 break; 388 case RCTR | 0x100: 389 fprintf(fp, " rctrl "); 390 break; 391 case RALT | 0x100: 392 fprintf(fp, " ralt "); 393 break; 394 case ALK | 0x100: 395 fprintf(fp, " alock "); 396 break; 397 case ASH | 0x100: 398 fprintf(fp, " ashift"); 399 break; 400 case META | 0x100: 401 fprintf(fp, " meta "); 402 break; 403 case RBT | 0x100: 404 fprintf(fp, " boot "); 405 break; 406 case DBG | 0x100: 407 fprintf(fp, " debug "); 408 break; 409 case SUSP | 0x100: 410 fprintf(fp, " susp "); 411 break; 412 case SPSC | 0x100: 413 fprintf(fp, " saver "); 414 break; 415 case PNC | 0x100: 416 fprintf(fp, " panic "); 417 break; 418 case LSHA | 0x100: 419 fprintf(fp, " lshifta"); 420 break; 421 case RSHA | 0x100: 422 fprintf(fp, " rshifta"); 423 break; 424 case LCTRA | 0x100: 425 fprintf(fp, " lctrla"); 426 break; 427 case RCTRA | 0x100: 428 fprintf(fp, " rctrla"); 429 break; 430 case LALTA | 0x100: 431 fprintf(fp, " lalta "); 432 break; 433 case RALTA | 0x100: 434 fprintf(fp, " ralta "); 435 break; 436 case HALT | 0x100: 437 fprintf(fp, " halt "); 438 break; 439 case PDWN | 0x100: 440 fprintf(fp, " pdwn "); 441 break; 442 default: 443 if (value & 0x100) { 444 if (val >= F_FN && val <= L_FN) 445 fprintf(fp, " fkey%02d", val - F_FN + 1); 446 else if (val >= F_SCR && val <= L_SCR) 447 fprintf(fp, " scr%02d ", val - F_SCR + 1); 448 else if (val >= F_ACC && val <= L_ACC) 449 fprintf(fp, " %-6s", acc_names[val - F_ACC]); 450 else if (hex) 451 fprintf(fp, " 0x%02x ", val); 452 else 453 fprintf(fp, " %3d ", val); 454 } 455 else { 456 if (val < ' ') 457 fprintf(fp, " %s ", ctrl_names[val]); 458 else if (val == 127) 459 fprintf(fp, " del "); 460 else if (isascii(val) && isprint(val)) 461 fprintf(fp, " '%c' ", val); 462 else if (hex) 463 fprintf(fp, " 0x%02x ", val); 464 else 465 fprintf(fp, " %3d ", val); 466 } 467 } 468} 469 470 471void 472print_key_definition_line(FILE *fp, int scancode, struct keyent_t *key) 473{ 474 int i; 475 476 /* print scancode number */ 477 if (hex) 478 fprintf(fp, " 0x%02x ", scancode); 479 else 480 fprintf(fp, " %03d ", scancode); 481 482 /* print key definitions */ 483 for (i=0; i<NUM_STATES; i++) { 484 if (key->spcl & (0x80 >> i)) 485 print_entry(fp, key->map[i] | 0x100); 486 else 487 print_entry(fp, key->map[i]); 488 } 489 490 /* print lock state key def */ 491 switch (key->flgs) { 492 case 0: 493 fprintf(fp, " O\n"); 494 break; 495 case 1: 496 fprintf(fp, " C\n"); 497 break; 498 case 2: 499 fprintf(fp, " N\n"); 500 break; 501 case 3: 502 fprintf(fp, " B\n"); 503 break; 504 } 505} 506 507void 508print_accent_definition_line(FILE *fp, int accent, struct acc_t *key) 509{ 510 int c; 511 int i; 512 513 if (key->accchar == 0) 514 return; 515 516 /* print accent number */ 517 fprintf(fp, " %-6s", acc_names[accent]); 518 if (isascii(key->accchar) && isprint(key->accchar)) 519 fprintf(fp, "'%c' ", key->accchar); 520 else if (hex) 521 fprintf(fp, "0x%02x ", key->accchar); 522 else 523 fprintf(fp, "%03d ", key->accchar); 524 525 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 526 c = key->map[i][0]; 527 if (c == 0) 528 break; 529 if ((i > 0) && ((i % 4) == 0)) 530 fprintf(fp, "\n "); 531 if (isascii(c) && isprint(c)) 532 fprintf(fp, "( '%c' ", c); 533 else if (hex) 534 fprintf(fp, "(0x%02x ", c); 535 else 536 fprintf(fp, "( %03d ", c); 537 c = key->map[i][1]; 538 if (isascii(c) && isprint(c)) 539 fprintf(fp, "'%c' ) ", c); 540 else if (hex) 541 fprintf(fp, "0x%02x) ", c); 542 else 543 fprintf(fp, "%03d ) ", c); 544 } 545 fprintf(fp, "\n"); 546} 547 548void 549dump_entry(int value) 550{ 551 if (value & 0x100) { 552 value &= 0x00ff; 553 switch (value) { 554 case NOP: 555 printf(" NOP, "); 556 break; 557 case LSH: 558 printf(" LSH, "); 559 break; 560 case RSH: 561 printf(" RSH, "); 562 break; 563 case CLK: 564 printf(" CLK, "); 565 break; 566 case NLK: 567 printf(" NLK, "); 568 break; 569 case SLK: 570 printf(" SLK, "); 571 break; 572 case BTAB: 573 printf(" BTAB, "); 574 break; 575 case LALT: 576 printf(" LALT, "); 577 break; 578 case LCTR: 579 printf(" LCTR, "); 580 break; 581 case NEXT: 582 printf(" NEXT, "); 583 break; 584 case PREV: 585 printf(" PREV, "); 586 break; 587 case RCTR: 588 printf(" RCTR, "); 589 break; 590 case RALT: 591 printf(" RALT, "); 592 break; 593 case ALK: 594 printf(" ALK, "); 595 break; 596 case ASH: 597 printf(" ASH, "); 598 break; 599 case META: 600 printf(" META, "); 601 break; 602 case RBT: 603 printf(" RBT, "); 604 break; 605 case DBG: 606 printf(" DBG, "); 607 break; 608 case SUSP: 609 printf(" SUSP, "); 610 break; 611 case SPSC: 612 printf(" SPSC, "); 613 break; 614 case PNC: 615 printf(" PNC, "); 616 break; 617 case LSHA: 618 printf(" LSHA, "); 619 break; 620 case RSHA: 621 printf(" RSHA, "); 622 break; 623 case LCTRA: 624 printf("LCTRA, "); 625 break; 626 case RCTRA: 627 printf("RCTRA, "); 628 break; 629 case LALTA: 630 printf("LALTA, "); 631 break; 632 case RALTA: 633 printf("RALTA, "); 634 break; 635 case HALT: 636 printf(" HALT, "); 637 break; 638 case PDWN: 639 printf(" PDWN, "); 640 break; 641 default: 642 if (value >= F_FN && value <= L_FN) 643 printf(" F(%2d),", value - F_FN + 1); 644 else if (value >= F_SCR && value <= L_SCR) 645 printf(" S(%2d),", value - F_SCR + 1); 646 else if (value >= F_ACC && value <= L_ACC) 647 printf(" %-4s, ", acc_names_u[value - F_ACC]); 648 else 649 printf(" 0x%02X, ", value); 650 break; 651 } 652 } else if (value == '\'') { 653 printf(" '\\'', "); 654 } else if (value == '\\') { 655 printf(" '\\\\', "); 656 } else if (isascii(value) && isprint(value)) { 657 printf(" '%c', ", value); 658 } else { 659 printf(" 0x%02X, ", value); 660 } 661} 662 663void 664dump_key_definition(char *name, keymap_t *keymap) 665{ 666 int i, j; 667 668 printf("static keymap_t keymap_%s = { 0x%02x, {\n", 669 name, (unsigned)keymap->n_keys); 670 printf( 671"/* alt\n" 672" * scan cntrl alt alt cntrl\n" 673" * code base shift cntrl shift alt shift cntrl shift spcl flgs\n" 674" * ---------------------------------------------------------------------------\n" 675" */\n"); 676 for (i = 0; i < keymap->n_keys; i++) { 677 printf("/*%02x*/{{", i); 678 for (j = 0; j < NUM_STATES; j++) { 679 if (keymap->key[i].spcl & (0x80 >> j)) 680 dump_entry(keymap->key[i].map[j] | 0x100); 681 else 682 dump_entry(keymap->key[i].map[j]); 683 } 684 printf("}, 0x%02X,0x%02X },\n", 685 (unsigned)keymap->key[i].spcl, 686 (unsigned)keymap->key[i].flgs); 687 } 688 printf("} };\n\n"); 689} 690 691void 692dump_accent_definition(char *name, accentmap_t *accentmap) 693{ 694 int i, j; 695 int c; 696 697 printf("static accentmap_t accentmap_%s = { %d", 698 name, accentmap->n_accs); 699 if (accentmap->n_accs <= 0) { 700 printf(" };\n\n"); 701 return; 702 } 703 printf(", {\n"); 704 for (i = 0; i < NUM_DEADKEYS; i++) { 705 printf(" /* %s=%d */\n {", acc_names[i], i); 706 c = accentmap->acc[i].accchar; 707 if (c == '\'') 708 printf(" '\\'', {"); 709 else if (c == '\\') 710 printf(" '\\\\', {"); 711 else if (isascii(c) && isprint(c)) 712 printf(" '%c', {", c); 713 else if (c == 0) { 714 printf(" 0x00 }, \n"); 715 continue; 716 } else 717 printf(" 0x%02x, {", c); 718 for (j = 0; j < NUM_ACCENTCHARS; j++) { 719 c = accentmap->acc[i].map[j][0]; 720 if (c == 0) 721 break; 722 if ((j > 0) && ((j % 4) == 0)) 723 printf("\n\t "); 724 if (isascii(c) && isprint(c)) 725 printf(" { '%c',", c); 726 else 727 printf(" { 0x%02x,", c); 728 printf("0x%02x },", accentmap->acc[i].map[j][1]); 729 } 730 printf(" }, },\n"); 731 } 732 printf("} };\n\n"); 733} 734 735void 736load_keymap(char *opt, int dumponly) 737{ 738 keymap_t keymap; 739 accentmap_t accentmap; 740 FILE *fd; 741 int i; 742 char *name, *cp; 743 char *prefix[] = {"", "", KEYMAP_PATH, KEYMAP_PATH, NULL}; 744 char *postfix[] = {"", ".kbd", "", ".kbd"}; 745 746 for (i=0; prefix[i]; i++) { 747 name = mkfullname(prefix[i], opt, postfix[i]); 748 if ((fd = fopen(name, "r"))) 749 break; 750 } 751 if (fd == NULL) { 752 warn("keymap file not found"); 753 return; 754 } 755 memset(&keymap, 0, sizeof(keymap)); 756 memset(&accentmap, 0, sizeof(accentmap)); 757 token = -1; 758 while (1) { 759 if (get_definition_line(fd, &keymap, &accentmap) < 0) 760 break; 761 } 762 if (dumponly) { 763 /* fix up the filename to make it a valid C identifier */ 764 for (cp = opt; *cp; cp++) 765 if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_'; 766 printf("/*\n" 767 " * Automatically generated from %s.\n" 768 " * DO NOT EDIT!\n" 769 " */\n", name); 770 dump_key_definition(opt, &keymap); 771 dump_accent_definition(opt, &accentmap); 772 return; 773 } 774 if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) { 775 warn("setting keymap"); 776 fclose(fd); 777 return; 778 } 779 if ((accentmap.n_accs > 0) 780 && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) { 781 warn("setting accentmap"); 782 fclose(fd); 783 return; 784 } 785} 786 787void 788print_keymap() 789{ 790 keymap_t keymap; 791 accentmap_t accentmap; 792 int i; 793 794 if (ioctl(0, GIO_KEYMAP, &keymap) < 0) 795 err(1, "getting keymap"); 796 if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) 797 memset(&accentmap, 0, sizeof(accentmap)); 798 printf( 799"# alt\n" 800"# scan cntrl alt alt cntrl lock\n" 801"# code base shift cntrl shift alt shift cntrl shift state\n" 802"# ------------------------------------------------------------------\n" 803 ); 804 for (i=0; i<keymap.n_keys; i++) 805 print_key_definition_line(stdout, i, &keymap.key[i]); 806 807 printf("\n"); 808 for (i = 0; i < NUM_DEADKEYS; i++) 809 print_accent_definition_line(stdout, i, &accentmap.acc[i]); 810 811} 812 813 814void 815load_default_functionkeys() 816{ 817 fkeyarg_t fkey; 818 int i; 819 820 for (i=0; i<NUM_FKEYS; i++) { 821 fkey.keynum = i; 822 strcpy(fkey.keydef, fkey_table[i]); 823 fkey.flen = strlen(fkey_table[i]); 824 if (ioctl(0, SETFKEY, &fkey) < 0) 825 warn("setting function key"); 826 } 827} 828 829void 830set_functionkey(char *keynumstr, char *string) 831{ 832 fkeyarg_t fkey; 833 834 if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 835 load_default_functionkeys(); 836 return; 837 } 838 fkey.keynum = atoi(keynumstr); 839 if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 840 warnx("function key number must be between 1 and %d", 841 NUM_FKEYS); 842 return; 843 } 844 if ((fkey.flen = strlen(string)) > MAXFK) { 845 warnx("function key string too long (%d > %d)", 846 fkey.flen, MAXFK); 847 return; 848 } 849 strcpy(fkey.keydef, string); 850 fkey.keynum -= 1; 851 if (ioctl(0, SETFKEY, &fkey) < 0) 852 warn("setting function key"); 853} 854 855 856void 857set_bell_values(char *opt) 858{ 859 int bell, duration, pitch; 860 861 bell = 0; 862 if (!strncmp(opt, "quiet.", 6)) { 863 bell = 2; 864 opt += 6; 865 } 866 if (!strcmp(opt, "visual")) 867 bell |= 1; 868 else if (!strcmp(opt, "normal")) 869 duration = 5, pitch = 800; 870 else if (!strcmp(opt, "off")) 871 duration = 0, pitch = 0; 872 else { 873 char *v1; 874 875 bell = 0; 876 duration = strtol(opt, &v1, 0); 877 if ((duration < 0) || (*v1 != '.')) 878 goto badopt; 879 opt = ++v1; 880 pitch = strtol(opt, &v1, 0); 881 if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 882badopt: 883 warnx("argument to -b must be DURATION.PITCH"); 884 return; 885 } 886 if (pitch != 0) 887 pitch = 1193182 / pitch; /* in Hz */ 888 duration /= 10; /* in 10 m sec */ 889 } 890 891 ioctl(0, CONS_BELLTYPE, &bell); 892 if ((bell & ~2) == 0) 893 fprintf(stderr, "[=%d;%dB", pitch, duration); 894} 895 896 897void 898set_keyrates(char *opt) 899{ 900 int arg[2]; 901 int repeat; 902 int delay; 903 int r, d; 904 905 if (!strcmp(opt, "slow")) { 906 delay = 1000, repeat = 500; 907 d = 3, r = 31; 908 } else if (!strcmp(opt, "normal")) { 909 delay = 500, repeat = 125; 910 d = 1, r = 15; 911 } else if (!strcmp(opt, "fast")) { 912 delay = repeat = 0; 913 d = r = 0; 914 } else { 915 int n; 916 char *v1; 917 918 delay = strtol(opt, &v1, 0); 919 if ((delay < 0) || (*v1 != '.')) 920 goto badopt; 921 opt = ++v1; 922 repeat = strtol(opt, &v1, 0); 923 if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 924badopt: 925 warnx("argument to -r must be delay.repeat"); 926 return; 927 } 928 for (n = 0; n < ndelays - 1; n++) 929 if (delay <= delays[n]) 930 break; 931 d = n; 932 for (n = 0; n < nrepeats - 1; n++) 933 if (repeat <= repeats[n]) 934 break; 935 r = n; 936 } 937 938 arg[0] = delay; 939 arg[1] = repeat; 940 if (ioctl(0, KDSETREPEAT, arg)) { 941 if (ioctl(0, KDSETRAD, (d << 5) | r)) 942 warn("setting keyboard rate"); 943 } 944} 945 946 947void 948set_history(char *opt) 949{ 950 int size; 951 952 size = atoi(opt); 953 if ((*opt == '\0') || size < 0) { 954 warnx("argument must be a positive number"); 955 return; 956 } 957 if (ioctl(0, CONS_HISTORY, &size) == -1) 958 warn("setting history buffer size"); 959} 960 961static char 962*get_kbd_type_name(int type) 963{ 964 static struct { 965 int type; 966 char *name; 967 } name_table[] = { 968 { KB_84, "AT 84" }, 969 { KB_101, "AT 101/102" }, 970 { KB_OTHER, "generic" }, 971 }; 972 int i; 973 974 for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 975 if (type == name_table[i].type) 976 return name_table[i].name; 977 } 978 return "unknown"; 979} 980 981void 982show_kbd_info(void) 983{ 984 keyboard_info_t info; 985 986 if (ioctl(0, KDGKBINFO, &info) == -1) { 987 warn("unable to obtain keyboard information"); 988 return; 989 } 990 printf("kbd%d:\n", info.kb_index); 991 printf(" %.*s%d, type:%s (%d)\n", 992 sizeof(info.kb_name), info.kb_name, info.kb_unit, 993 get_kbd_type_name(info.kb_type), info.kb_type); 994} 995 996 997void 998set_keyboard(char *device) 999{ 1000 keyboard_info_t info; 1001 int fd; 1002 1003 fd = open(device, O_RDONLY); 1004 if (fd < 0) { 1005 warn("cannot open %s", device); 1006 return; 1007 } 1008 if (ioctl(fd, KDGKBINFO, &info) == -1) { 1009 warn("unable to obtain keyboard information"); 1010 close(fd); 1011 return; 1012 } 1013 /* 1014 * The keyboard device driver won't release the keyboard by 1015 * the following ioctl, but it automatically will, when the device 1016 * is closed. So, we don't check error here. 1017 */ 1018 ioctl(fd, CONS_RELKBD, 0); 1019 close(fd); 1020#if 1 1021 printf("kbd%d\n", info.kb_index); 1022 printf(" %.*s%d, type:%s (%d)\n", 1023 sizeof(info.kb_name), info.kb_name, info.kb_unit, 1024 get_kbd_type_name(info.kb_type), info.kb_type); 1025#endif 1026 1027 if (ioctl(0, CONS_SETKBD, info.kb_index) == -1) 1028 warn("unable to set keyboard"); 1029} 1030 1031 1032void 1033release_keyboard(void) 1034{ 1035 keyboard_info_t info; 1036 1037 /* 1038 * If stdin is not associated with a keyboard, the following ioctl 1039 * will fail. 1040 */ 1041 if (ioctl(0, KDGKBINFO, &info) == -1) { 1042 warn("unable to obtain keyboard information"); 1043 return; 1044 } 1045#if 1 1046 printf("kbd%d\n", info.kb_index); 1047 printf(" %.*s%d, type:%s (%d)\n", 1048 sizeof(info.kb_name), info.kb_name, info.kb_unit, 1049 get_kbd_type_name(info.kb_type), info.kb_type); 1050#endif 1051 if (ioctl(0, CONS_RELKBD, 0) == -1) 1052 warn("unable to release the keyboard"); 1053} 1054 1055 1056static void 1057usage() 1058{ 1059 fprintf(stderr, "%s\n%s\n%s\n", 1060"usage: kbdcontrol [-dFKix] [-b duration.pitch | [quiet.]belltype]", 1061" [-r delay.repeat | speed] [-l mapfile] [-f # string]", 1062" [-h size] [-k device] [-L mapfile]"); 1063 exit(1); 1064} 1065 1066 1067int 1068main(int argc, char **argv) 1069{ 1070 int opt; 1071 1072 while((opt = getopt(argc, argv, "b:df:h:iKk:Fl:L:r:x")) != -1) 1073 switch(opt) { 1074 case 'b': 1075 set_bell_values(optarg); 1076 break; 1077 case 'd': 1078 print_keymap(); 1079 break; 1080 case 'l': 1081 load_keymap(optarg, 0); 1082 break; 1083 case 'L': 1084 load_keymap(optarg, 1); 1085 break; 1086 case 'f': 1087 set_functionkey(optarg, 1088 nextarg(argc, argv, &optind, 'f')); 1089 break; 1090 case 'F': 1091 load_default_functionkeys(); 1092 break; 1093 case 'h': 1094 set_history(optarg); 1095 break; 1096 case 'i': 1097 show_kbd_info(); 1098 break; 1099 case 'K': 1100 release_keyboard(); 1101 break; 1102 case 'k': 1103 set_keyboard(optarg); 1104 break; 1105 case 'r': 1106 set_keyrates(optarg); 1107 break; 1108 case 'x': 1109 hex = 1; 1110 break; 1111 default: 1112 usage(); 1113 } 1114 if ((optind != argc) || (argc == 1)) 1115 usage(); 1116 exit(0); 1117} 1118 1119 1120