kbdcontrol.c revision 54380
12088Ssos/*- 25536Ssos * Copyright (c) 1994-1995 S�ren Schmidt 32088Ssos * All rights reserved. 42088Ssos * 52088Ssos * Redistribution and use in source and binary forms, with or without 62088Ssos * modification, are permitted provided that the following conditions 72088Ssos * are met: 82088Ssos * 1. Redistributions of source code must retain the above copyright 95994Ssos * notice, this list of conditions and the following disclaimer, 105994Ssos * in this position and unchanged. 112088Ssos * 2. Redistributions in binary form must reproduce the above copyright 122088Ssos * notice, this list of conditions and the following disclaimer in the 132088Ssos * documentation and/or other materials provided with the distribution. 142088Ssos * 3. The name of the author may not be used to endorse or promote products 152088Ssos * derived from this software withough specific prior written permission 162088Ssos * 172088Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 182088Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 192088Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 202088Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 212088Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 222088Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232088Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242088Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252088Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 262088Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272088Ssos */ 282088Ssos 2929603Scharnier#ifndef lint 3029603Scharnierstatic const char rcsid[] = 3150479Speter "$FreeBSD: head/usr.sbin/kbdcontrol/kbdcontrol.c 54380 1999-12-10 04:24:27Z yokota $"; 3229603Scharnier#endif /* not lint */ 3329603Scharnier 342088Ssos#include <ctype.h> 3529603Scharnier#include <err.h> 362088Ssos#include <stdio.h> 3729603Scharnier#include <stdlib.h> 383864Sswallace#include <string.h> 3929603Scharnier#include <unistd.h> 4042505Syokota#include <fcntl.h> 412088Ssos#include <machine/console.h> 422088Ssos#include "path.h" 432088Ssos#include "lex.h" 442088Ssos 452088Ssoschar ctrl_names[32][4] = { 468857Srgrimes "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 472088Ssos "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 482088Ssos "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 4938139Syokota "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us " 502088Ssos }; 512088Ssos 5232316Syokotachar acc_names[15][5] = { 5332316Syokota "dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot", 5432316Syokota "duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo", 5532316Syokota "dcar", 5632316Syokota }; 5732316Syokota 5832316Syokotachar acc_names_u[15][5] = { 5932316Syokota "DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT", 6032316Syokota "DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO", 6132316Syokota "DCAR", 6232316Syokota }; 6332316Syokota 645994Ssoschar fkey_table[96][MAXFK] = { 655994Ssos/* 01-04 */ "\033[M", "\033[N", "\033[O", "\033[P", 665994Ssos/* 05-08 */ "\033[Q", "\033[R", "\033[S", "\033[T", 675994Ssos/* 09-12 */ "\033[U", "\033[V", "\033[W", "\033[X", 685994Ssos/* 13-16 */ "\033[Y", "\033[Z", "\033[a", "\033[b", 695994Ssos/* 17-20 */ "\033[c", "\033[d", "\033[e", "\033[f", 705994Ssos/* 21-24 */ "\033[g", "\033[h", "\033[i", "\033[j", 715994Ssos/* 25-28 */ "\033[k", "\033[l", "\033[m", "\033[n", 725994Ssos/* 29-32 */ "\033[o", "\033[p", "\033[q", "\033[r", 735994Ssos/* 33-36 */ "\033[s", "\033[t", "\033[u", "\033[v", 745994Ssos/* 37-40 */ "\033[w", "\033[x", "\033[y", "\033[z", 755994Ssos/* 41-44 */ "\033[@", "\033[[", "\033[\\","\033[]", 769202Srgrimes/* 45-48 */ "\033[^", "\033[_", "\033[`", "\033[{", 775994Ssos/* 49-52 */ "\033[H", "\033[A", "\033[I", "-" , 785994Ssos/* 53-56 */ "\033[D", "\033[E", "\033[C", "+" , 795994Ssos/* 57-60 */ "\033[F", "\033[B", "\033[G", "\033[L", 809202Srgrimes/* 61-64 */ "\177", "\033[J", "\033[~", "\033[}", 815994Ssos/* 65-68 */ "" , "" , "" , "" , 825994Ssos/* 69-72 */ "" , "" , "" , "" , 835994Ssos/* 73-76 */ "" , "" , "" , "" , 845994Ssos/* 77-80 */ "" , "" , "" , "" , 855994Ssos/* 81-84 */ "" , "" , "" , "" , 865994Ssos/* 85-88 */ "" , "" , "" , "" , 875994Ssos/* 89-92 */ "" , "" , "" , "" , 885994Ssos/* 93-96 */ "" , "" , "" , "" , 892088Ssos }; 902088Ssos 9146761Syokotaconst int delays[] = {250, 500, 750, 1000}; 9246761Syokotaconst int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 9346761Syokota 68, 76, 84, 92, 100, 110, 118, 126, 9446761Syokota 136, 152, 168, 184, 200, 220, 236, 252, 9546761Syokota 272, 304, 336, 368, 400, 440, 472, 504}; 9646761Syokotaconst int ndelays = (sizeof(delays) / sizeof(int)); 9746761Syokotaconst int nrepeats = (sizeof(repeats) / sizeof(int)); 982088Ssosint hex = 0; 996046Ssosint number; 1002088Ssoschar letter; 10132316Syokotaint token; 1022088Ssos 10329603Scharnierstatic void usage __P((void)); 1042088Ssos 1052088Ssoschar * 1062088Ssosnextarg(int ac, char **av, int *indp, int oc) 1072088Ssos{ 1082088Ssos if (*indp < ac) 1092088Ssos return(av[(*indp)++]); 11029603Scharnier warnx("option requires two arguments -- %c", oc); 1112088Ssos usage(); 1122088Ssos return(""); 1132088Ssos} 1142088Ssos 1152088Ssos 1162088Ssoschar * 1172088Ssosmkfullname(const char *s1, const char *s2, const char *s3) 1182088Ssos{ 1195536Ssos static char *buf = NULL; 1205536Ssos static int bufl = 0; 1215536Ssos int f; 1222088Ssos 1232088Ssos f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 1242088Ssos if (f > bufl) 1252088Ssos if (buf) 1262088Ssos buf = (char *)realloc(buf, f); 1272088Ssos else 1282088Ssos buf = (char *)malloc(f); 1292088Ssos if (!buf) { 1302088Ssos bufl = 0; 1312088Ssos return(NULL); 1322088Ssos } 1332088Ssos 1342088Ssos bufl = f; 1352088Ssos strcpy(buf, s1); 1362088Ssos strcat(buf, s2); 1372088Ssos strcat(buf, s3); 1382088Ssos return(buf); 1392088Ssos} 1402088Ssos 1412088Ssos 1422088Ssosint 1432088Ssosget_entry() 1442088Ssos{ 14532316Syokota switch ((token = yylex())) { 1462088Ssos case TNOP: 1472088Ssos return NOP | 0x100; 1482088Ssos case TLSH: 1492088Ssos return LSH | 0x100; 1502088Ssos case TRSH: 1512088Ssos return RSH | 0x100; 1522088Ssos case TCLK: 1532088Ssos return CLK | 0x100; 1542088Ssos case TNLK: 1552088Ssos return NLK | 0x100; 1562088Ssos case TSLK: 1572088Ssos return SLK | 0x100; 1582088Ssos case TBTAB: 1592088Ssos return BTAB | 0x100; 1602088Ssos case TLALT: 1612088Ssos return LALT | 0x100; 1622088Ssos case TLCTR: 1632088Ssos return LCTR | 0x100; 1642088Ssos case TNEXT: 1652088Ssos return NEXT | 0x100; 16648105Syokota case TPREV: 16748105Syokota return PREV | 0x100; 1682088Ssos case TRCTR: 1692088Ssos return RCTR | 0x100; 1702088Ssos case TRALT: 1712088Ssos return RALT | 0x100; 1722088Ssos case TALK: 1732088Ssos return ALK | 0x100; 1742088Ssos case TASH: 1752088Ssos return ASH | 0x100; 1762088Ssos case TMETA: 1772088Ssos return META | 0x100; 1782088Ssos case TRBT: 1792088Ssos return RBT | 0x100; 1802088Ssos case TDBG: 1812088Ssos return DBG | 0x100; 1825994Ssos case TSUSP: 1835994Ssos return SUSP | 0x100; 18438053Syokota case TSPSC: 18538053Syokota return SPSC | 0x100; 18654380Syokota case TPANIC: 18754380Syokota return PNC | 0x100; 18854380Syokota case TLSHA: 18954380Syokota return LSHA | 0x100; 19054380Syokota case TRSHA: 19154380Syokota return RSHA | 0x100; 19254380Syokota case TLCTRA: 19354380Syokota return LCTRA | 0x100; 19454380Syokota case TRCTRA: 19554380Syokota return RCTRA | 0x100; 19654380Syokota case TLALTA: 19754380Syokota return LALTA | 0x100; 19854380Syokota case TRALTA: 19954380Syokota return RALTA | 0x100; 20032316Syokota case TACC: 20132316Syokota if (ACC(number) > L_ACC) 20232316Syokota return -1; 20332316Syokota return ACC(number) | 0x100; 2042088Ssos case TFUNC: 2052088Ssos if (F(number) > L_FN) 2062088Ssos return -1; 2072088Ssos return F(number) | 0x100; 2082088Ssos case TSCRN: 2092088Ssos if (S(number) > L_SCR) 2102088Ssos return -1; 2112088Ssos return S(number) | 0x100; 2122088Ssos case TLET: 2132088Ssos return (unsigned char)letter; 2142088Ssos case TNUM: 2152088Ssos if (number < 0 || number > 255) 2162088Ssos return -1; 2172088Ssos return number; 2182088Ssos default: 2192088Ssos return -1; 2202088Ssos } 2212088Ssos} 2222088Ssos 2232088Ssosint 22432316Syokotaget_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap) 2252088Ssos{ 22632316Syokota int c; 2272088Ssos 2282088Ssos yyin = fd; 2292088Ssos 23032316Syokota if (token < 0) 23132316Syokota token = yylex(); 23232316Syokota switch (token) { 23332316Syokota case TNUM: 23432316Syokota c = get_key_definition_line(keymap); 23532316Syokota if (c < 0) 23632316Syokota errx(1, "invalid key definition"); 23732316Syokota if (c > keymap->n_keys) 23832316Syokota keymap->n_keys = c; 23932316Syokota break; 24032316Syokota case TACC: 24132316Syokota c = get_accent_definition_line(accentmap); 24232316Syokota if (c < 0) 24332316Syokota errx(1, "invalid accent key definition"); 24432316Syokota if (c > accentmap->n_accs) 24532316Syokota accentmap->n_accs = c; 24632316Syokota break; 24732316Syokota case 0: 24832316Syokota /* EOF */ 2492088Ssos return -1; 25032316Syokota default: 25132316Syokota errx(1, "illegal definition line"); 25232316Syokota } 25332316Syokota return c; 25432316Syokota} 25532316Syokota 25632316Syokotaint 25732316Syokotaget_key_definition_line(keymap_t *map) 25832316Syokota{ 25932316Syokota int i, def, scancode; 26032316Syokota 26132316Syokota /* check scancode number */ 2622088Ssos if (number < 0 || number >= NUM_KEYS) 2632088Ssos return -1; 2642088Ssos scancode = number; 2652088Ssos 2662088Ssos /* get key definitions */ 2672088Ssos map->key[scancode].spcl = 0; 2682088Ssos for (i=0; i<NUM_STATES; i++) { 2692088Ssos if ((def = get_entry()) == -1) 2702088Ssos return -1; 2712088Ssos if (def & 0x100) 2722088Ssos map->key[scancode].spcl |= (0x80 >> i); 2732088Ssos map->key[scancode].map[i] = def & 0xFF; 2742088Ssos } 2752088Ssos /* get lock state key def */ 27632316Syokota if ((token = yylex()) != TFLAG) 2772088Ssos return -1; 2782088Ssos map->key[scancode].flgs = number; 27932316Syokota token = yylex(); 28032316Syokota return (scancode + 1); 2812088Ssos} 2822088Ssos 28332316Syokotaint 28432316Syokotaget_accent_definition_line(accentmap_t *map) 28532316Syokota{ 28632316Syokota int accent; 28732316Syokota int c1, c2; 28832316Syokota int i; 2892088Ssos 29032316Syokota if (ACC(number) < F_ACC || ACC(number) > L_ACC) 29132316Syokota /* number out of range */ 29232316Syokota return -1; 29332316Syokota accent = number; 29432316Syokota if (map->acc[accent].accchar != 0) { 29532316Syokota /* this entry has already been defined before! */ 29632316Syokota errx(1, "duplicated accent key definition"); 29732316Syokota } 29832316Syokota 29932316Syokota switch ((token = yylex())) { 30032316Syokota case TLET: 30132316Syokota map->acc[accent].accchar = letter; 30232316Syokota break; 30332316Syokota case TNUM: 30432316Syokota map->acc[accent].accchar = number; 30532316Syokota break; 30632316Syokota default: 30732316Syokota return -1; 30832316Syokota } 30932316Syokota 31032316Syokota for (i = 0; (token = yylex()) == '(';) { 31132316Syokota switch ((token = yylex())) { 31232316Syokota case TLET: 31332316Syokota c1 = letter; 31432316Syokota break; 31532316Syokota case TNUM: 31632316Syokota c1 = number; 31732316Syokota break; 31832316Syokota default: 31932316Syokota return -1; 32032316Syokota } 32132316Syokota switch ((token = yylex())) { 32232316Syokota case TLET: 32332316Syokota c2 = letter; 32432316Syokota break; 32532316Syokota case TNUM: 32632316Syokota c2 = number; 32732316Syokota break; 32832316Syokota default: 32932316Syokota return -1; 33032316Syokota } 33132316Syokota if ((token = yylex()) != ')') 33232316Syokota return -1; 33332316Syokota if (i >= NUM_ACCENTCHARS) { 33432316Syokota warnx("too many accented characters, ignored"); 33532316Syokota continue; 33632316Syokota } 33732316Syokota map->acc[accent].map[i][0] = c1; 33832316Syokota map->acc[accent].map[i][1] = c2; 33932316Syokota ++i; 34032316Syokota } 34132316Syokota return (accent + 1); 34232316Syokota} 34332316Syokota 34429603Scharniervoid 3452088Ssosprint_entry(FILE *fp, int value) 3462088Ssos{ 3472088Ssos int val = value & 0xFF; 3482088Ssos 3492088Ssos switch (value) { 3502088Ssos case NOP | 0x100: 3518857Srgrimes fprintf(fp, " nop "); 3522088Ssos break; 3532088Ssos case LSH | 0x100: 3542088Ssos fprintf(fp, " lshift"); 3552088Ssos break; 3562088Ssos case RSH | 0x100: 3572088Ssos fprintf(fp, " rshift"); 3582088Ssos break; 3592088Ssos case CLK | 0x100: 3602088Ssos fprintf(fp, " clock "); 3612088Ssos break; 3622088Ssos case NLK | 0x100: 3632088Ssos fprintf(fp, " nlock "); 3642088Ssos break; 3652088Ssos case SLK | 0x100: 3662088Ssos fprintf(fp, " slock "); 3672088Ssos break; 3682088Ssos case BTAB | 0x100: 3692088Ssos fprintf(fp, " btab "); 3702088Ssos break; 3712088Ssos case LALT | 0x100: 3722088Ssos fprintf(fp, " lalt "); 3732088Ssos break; 3742088Ssos case LCTR | 0x100: 3752088Ssos fprintf(fp, " lctrl "); 3762088Ssos break; 3772088Ssos case NEXT | 0x100: 3782088Ssos fprintf(fp, " nscr "); 3792088Ssos break; 38048105Syokota case PREV | 0x100: 38148105Syokota fprintf(fp, " pscr "); 38248105Syokota break; 3832088Ssos case RCTR | 0x100: 3842088Ssos fprintf(fp, " rctrl "); 3852088Ssos break; 3862088Ssos case RALT | 0x100: 3872088Ssos fprintf(fp, " ralt "); 3882088Ssos break; 3892088Ssos case ALK | 0x100: 3902088Ssos fprintf(fp, " alock "); 3912088Ssos break; 3922088Ssos case ASH | 0x100: 3932088Ssos fprintf(fp, " ashift"); 3942088Ssos break; 3952088Ssos case META | 0x100: 3962088Ssos fprintf(fp, " meta "); 3972088Ssos break; 3982088Ssos case RBT | 0x100: 3992088Ssos fprintf(fp, " boot "); 4002088Ssos break; 4012088Ssos case DBG | 0x100: 4022088Ssos fprintf(fp, " debug "); 4032088Ssos break; 40432316Syokota case SUSP | 0x100: 40532316Syokota fprintf(fp, " susp "); 40632316Syokota break; 40738053Syokota case SPSC | 0x100: 40838053Syokota fprintf(fp, " saver "); 40938053Syokota break; 41054380Syokota case PNC | 0x100: 41154380Syokota fprintf(fp, " panic "); 41254380Syokota break; 41354380Syokota case LSHA | 0x100: 41454380Syokota fprintf(fp, " lshifta"); 41554380Syokota break; 41654380Syokota case RSHA | 0x100: 41754380Syokota fprintf(fp, " rshifta"); 41854380Syokota break; 41954380Syokota case LCTRA | 0x100: 42054380Syokota fprintf(fp, " lctrla"); 42154380Syokota break; 42254380Syokota case RCTRA | 0x100: 42354380Syokota fprintf(fp, " rctrla"); 42454380Syokota break; 42554380Syokota case LALTA | 0x100: 42654380Syokota fprintf(fp, " lalta "); 42754380Syokota break; 42854380Syokota case RALTA | 0x100: 42954380Syokota fprintf(fp, " ralta "); 43054380Syokota break; 4312088Ssos default: 4322088Ssos if (value & 0x100) { 4338857Srgrimes if (val >= F_FN && val <= L_FN) 4342088Ssos fprintf(fp, " fkey%02d", val - F_FN + 1); 4358857Srgrimes else if (val >= F_SCR && val <= L_SCR) 4362088Ssos fprintf(fp, " scr%02d ", val - F_SCR + 1); 43732316Syokota else if (val >= F_ACC && val <= L_ACC) 43832316Syokota fprintf(fp, " %-6s", acc_names[val - F_ACC]); 4392088Ssos else if (hex) 4408857Srgrimes fprintf(fp, " 0x%02x ", val); 4412088Ssos else 44232316Syokota fprintf(fp, " %3d ", val); 4432088Ssos } 4442088Ssos else { 4452088Ssos if (val < ' ') 4468857Srgrimes fprintf(fp, " %s ", ctrl_names[val]); 4472088Ssos else if (val == 127) 4488857Srgrimes fprintf(fp, " del "); 4499202Srgrimes else if (isascii(val) && isprint(val)) 4508857Srgrimes fprintf(fp, " '%c' ", val); 4512088Ssos else if (hex) 4528857Srgrimes fprintf(fp, " 0x%02x ", val); 4532088Ssos else 4548857Srgrimes fprintf(fp, " %3d ", val); 4552088Ssos } 4562088Ssos } 4572088Ssos} 4582088Ssos 4592088Ssos 4602088Ssosvoid 46142505Syokotaprint_key_definition_line(FILE *fp, int scancode, struct keyent_t *key) 4622088Ssos{ 46329603Scharnier int i; 4642088Ssos 4652088Ssos /* print scancode number */ 4662088Ssos if (hex) 4672088Ssos fprintf(fp, " 0x%02x ", scancode); 4682088Ssos else 4692088Ssos fprintf(fp, " %03d ", scancode); 4702088Ssos 4712088Ssos /* print key definitions */ 4722088Ssos for (i=0; i<NUM_STATES; i++) { 4732088Ssos if (key->spcl & (0x80 >> i)) 4742088Ssos print_entry(fp, key->map[i] | 0x100); 4752088Ssos else 4768857Srgrimes print_entry(fp, key->map[i]); 4772088Ssos } 4782088Ssos 4792088Ssos /* print lock state key def */ 4802088Ssos switch (key->flgs) { 4812088Ssos case 0: 4822088Ssos fprintf(fp, " O\n"); 4832088Ssos break; 4842088Ssos case 1: 4852088Ssos fprintf(fp, " C\n"); 4862088Ssos break; 4872088Ssos case 2: 4882088Ssos fprintf(fp, " N\n"); 4892088Ssos break; 4906046Ssos case 3: 4916046Ssos fprintf(fp, " B\n"); 4926046Ssos break; 4938857Srgrimes } 4942088Ssos} 4952088Ssos 49632316Syokotavoid 49732316Syokotaprint_accent_definition_line(FILE *fp, int accent, struct acc_t *key) 49832316Syokota{ 49932316Syokota int c; 50032316Syokota int i; 5012088Ssos 50232316Syokota if (key->accchar == 0) 50332316Syokota return; 50432316Syokota 50532316Syokota /* print accent number */ 50632316Syokota fprintf(fp, " %-6s", acc_names[accent]); 50732316Syokota if (isascii(key->accchar) && isprint(key->accchar)) 50832316Syokota fprintf(fp, "'%c' ", key->accchar); 50932316Syokota else if (hex) 51032316Syokota fprintf(fp, "0x%02x ", key->accchar); 51132316Syokota else 51232316Syokota fprintf(fp, "%03d ", key->accchar); 51332316Syokota 51432316Syokota for (i = 0; i < NUM_ACCENTCHARS; ++i) { 51532316Syokota c = key->map[i][0]; 51632316Syokota if (c == 0) 51732316Syokota break; 51832316Syokota if ((i > 0) && ((i % 4) == 0)) 51932316Syokota fprintf(fp, "\n "); 52032316Syokota if (isascii(c) && isprint(c)) 52132316Syokota fprintf(fp, "( '%c' ", c); 52232316Syokota else if (hex) 52332316Syokota fprintf(fp, "(0x%02x ", c); 52432316Syokota else 52532316Syokota fprintf(fp, "( %03d ", c); 52632316Syokota c = key->map[i][1]; 52732316Syokota if (isascii(c) && isprint(c)) 52832316Syokota fprintf(fp, "'%c' ) ", c); 52932316Syokota else if (hex) 53032316Syokota fprintf(fp, "0x%02x) ", c); 53132316Syokota else 53232316Syokota fprintf(fp, "%03d ) ", c); 53332316Syokota } 53432316Syokota fprintf(fp, "\n"); 53532316Syokota} 53632316Syokota 5372088Ssosvoid 53832316Syokotadump_entry(int value) 53932316Syokota{ 54032316Syokota if (value & 0x100) { 54132316Syokota value &= 0x00ff; 54232316Syokota switch (value) { 54332316Syokota case NOP: 54432316Syokota printf(" NOP, "); 54532316Syokota break; 54632316Syokota case LSH: 54732316Syokota printf(" LSH, "); 54832316Syokota break; 54932316Syokota case RSH: 55032316Syokota printf(" RSH, "); 55132316Syokota break; 55232316Syokota case CLK: 55332316Syokota printf(" CLK, "); 55432316Syokota break; 55532316Syokota case NLK: 55632316Syokota printf(" NLK, "); 55732316Syokota break; 55832316Syokota case SLK: 55932316Syokota printf(" SLK, "); 56032316Syokota break; 56132316Syokota case BTAB: 56232316Syokota printf(" BTAB, "); 56332316Syokota break; 56432316Syokota case LALT: 56532316Syokota printf(" LALT, "); 56632316Syokota break; 56732316Syokota case LCTR: 56832316Syokota printf(" LCTR, "); 56932316Syokota break; 57032316Syokota case NEXT: 57132316Syokota printf(" NEXT, "); 57232316Syokota break; 57348105Syokota case PREV: 57448105Syokota printf(" PREV, "); 57548105Syokota break; 57632316Syokota case RCTR: 57732316Syokota printf(" RCTR, "); 57832316Syokota break; 57932316Syokota case RALT: 58032316Syokota printf(" RALT, "); 58132316Syokota break; 58232316Syokota case ALK: 58332316Syokota printf(" ALK, "); 58432316Syokota break; 58532316Syokota case ASH: 58632316Syokota printf(" ASH, "); 58732316Syokota break; 58832316Syokota case META: 58932316Syokota printf(" META, "); 59032316Syokota break; 59132316Syokota case RBT: 59232316Syokota printf(" RBT, "); 59332316Syokota break; 59432316Syokota case DBG: 59532316Syokota printf(" DBG, "); 59632316Syokota break; 59732316Syokota case SUSP: 59832316Syokota printf(" SUSP, "); 59932316Syokota break; 60038053Syokota case SPSC: 60138053Syokota printf(" SPSC, "); 60238053Syokota break; 60354380Syokota case PNC: 60454380Syokota printf(" PNC, "); 60554380Syokota break; 60654380Syokota case LSHA: 60754380Syokota printf(" LSHA, "); 60854380Syokota break; 60954380Syokota case RSHA: 61054380Syokota printf(" RSHA, "); 61154380Syokota break; 61254380Syokota case LCTRA: 61354380Syokota printf("LCTRA, "); 61454380Syokota break; 61554380Syokota case RCTRA: 61654380Syokota printf("RCTRA, "); 61754380Syokota break; 61854380Syokota case LALTA: 61954380Syokota printf("LALTA, "); 62054380Syokota break; 62154380Syokota case RALTA: 62254380Syokota printf("RALTA, "); 62354380Syokota break; 62432316Syokota default: 62532316Syokota if (value >= F_FN && value <= L_FN) 62632316Syokota printf(" F(%2d),", value - F_FN + 1); 62732316Syokota else if (value >= F_SCR && value <= L_SCR) 62832486Syokota printf(" S(%2d),", value - F_SCR + 1); 62932316Syokota else if (value >= F_ACC && value <= L_ACC) 63032316Syokota printf(" %-4s, ", acc_names_u[value - F_ACC]); 63132316Syokota else 63232316Syokota printf(" 0x%02X, ", value); 63332316Syokota break; 63432316Syokota } 63532316Syokota } else if (value == '\'') { 63632316Syokota printf(" '\\'', "); 63732316Syokota } else if (value == '\\') { 63832316Syokota printf(" '\\\\', "); 63932316Syokota } else if (isascii(value) && isprint(value)) { 64032316Syokota printf(" '%c', ", value); 64132316Syokota } else { 64232316Syokota printf(" 0x%02X, ", value); 64332316Syokota } 64432316Syokota} 64532316Syokota 64632316Syokotavoid 64732316Syokotadump_key_definition(char *name, keymap_t *keymap) 64832316Syokota{ 64932316Syokota int i, j; 65032316Syokota 65132486Syokota printf("static keymap_t keymap_%s = { 0x%02x, {\n", 65232316Syokota name, (unsigned)keymap->n_keys); 65332316Syokota printf( 65432486Syokota"/* alt\n" 65532486Syokota" * scan cntrl alt alt cntrl\n" 65632486Syokota" * code base shift cntrl shift alt shift cntrl shift spcl flgs\n" 65732316Syokota" * ---------------------------------------------------------------------------\n" 65832316Syokota" */\n"); 65932316Syokota for (i = 0; i < keymap->n_keys; i++) { 66032486Syokota printf("/*%02x*/{{", i); 66132316Syokota for (j = 0; j < NUM_STATES; j++) { 66232316Syokota if (keymap->key[i].spcl & (0x80 >> j)) 66332316Syokota dump_entry(keymap->key[i].map[j] | 0x100); 66432316Syokota else 66532316Syokota dump_entry(keymap->key[i].map[j]); 66632316Syokota } 66732486Syokota printf("}, 0x%02X,0x%02X },\n", 66832316Syokota (unsigned)keymap->key[i].spcl, 66932316Syokota (unsigned)keymap->key[i].flgs); 67032316Syokota } 67132486Syokota printf("} };\n\n"); 67232316Syokota} 67332316Syokota 67432316Syokotavoid 67532316Syokotadump_accent_definition(char *name, accentmap_t *accentmap) 67632316Syokota{ 67732316Syokota int i, j; 67832316Syokota int c; 67932316Syokota 68032486Syokota printf("static accentmap_t accentmap_%s = { %d", 68132316Syokota name, accentmap->n_accs); 68232486Syokota if (accentmap->n_accs <= 0) { 68332486Syokota printf(" };\n\n"); 68432486Syokota return; 68532486Syokota } 68632486Syokota printf(", {\n"); 68732316Syokota for (i = 0; i < NUM_DEADKEYS; i++) { 68832316Syokota printf(" /* %s=%d */\n {", acc_names[i], i); 68932316Syokota c = accentmap->acc[i].accchar; 69032316Syokota if (c == '\'') 69132316Syokota printf(" '\\'', {"); 69232316Syokota else if (c == '\\') 69332316Syokota printf(" '\\\\', {"); 69432316Syokota else if (isascii(c) && isprint(c)) 69532316Syokota printf(" '%c', {", c); 69632316Syokota else if (c == 0) { 69732316Syokota printf(" 0x00 }, \n"); 69832316Syokota continue; 69932316Syokota } else 70032316Syokota printf(" 0x%02x, {", c); 70132316Syokota for (j = 0; j < NUM_ACCENTCHARS; j++) { 70232316Syokota c = accentmap->acc[i].map[j][0]; 70332316Syokota if (c == 0) 70432316Syokota break; 70532316Syokota if ((j > 0) && ((j % 4) == 0)) 70632316Syokota printf("\n\t "); 70732316Syokota if (isascii(c) && isprint(c)) 70832316Syokota printf(" { '%c',", c); 70932316Syokota else 71032316Syokota printf(" { 0x%02x,", c); 71132316Syokota printf("0x%02x },", accentmap->acc[i].map[j][1]); 71232316Syokota } 71332316Syokota printf(" }, },\n"); 71432316Syokota } 71532486Syokota printf("} };\n\n"); 71632316Syokota} 71732316Syokota 71832316Syokotavoid 71919569Sjoergload_keymap(char *opt, int dumponly) 7202088Ssos{ 72132316Syokota keymap_t keymap; 72232316Syokota accentmap_t accentmap; 7232088Ssos FILE *fd; 72432316Syokota int i; 72519569Sjoerg char *name, *cp; 72635750Sdes char *prefix[] = {"", "", KEYMAP_PATH, KEYMAP_PATH, NULL}; 72735750Sdes char *postfix[] = {"", ".kbd", "", ".kbd"}; 7282088Ssos 7292088Ssos for (i=0; prefix[i]; i++) { 7302088Ssos name = mkfullname(prefix[i], opt, postfix[i]); 73129603Scharnier if ((fd = fopen(name, "r"))) 7322088Ssos break; 7332088Ssos } 7342088Ssos if (fd == NULL) { 73529603Scharnier warn("keymap file not found"); 7362088Ssos return; 7372088Ssos } 73832316Syokota memset(&keymap, 0, sizeof(keymap)); 73932316Syokota memset(&accentmap, 0, sizeof(accentmap)); 74032316Syokota token = -1; 7412088Ssos while (1) { 74232316Syokota if (get_definition_line(fd, &keymap, &accentmap) < 0) 7432088Ssos break; 7442088Ssos } 74519569Sjoerg if (dumponly) { 74619569Sjoerg /* fix up the filename to make it a valid C identifier */ 74719569Sjoerg for (cp = opt; *cp; cp++) 74819569Sjoerg if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_'; 74932316Syokota printf("/*\n" 75032316Syokota " * Automatically generated from %s.\n" 75132316Syokota " * DO NOT EDIT!\n" 75232316Syokota " */\n", name); 75332316Syokota dump_key_definition(opt, &keymap); 75432316Syokota dump_accent_definition(opt, &accentmap); 75519569Sjoerg return; 75619569Sjoerg } 75732316Syokota if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) { 75829603Scharnier warn("setting keymap"); 7592088Ssos fclose(fd); 7602088Ssos return; 7612088Ssos } 76232316Syokota if ((accentmap.n_accs > 0) 76332316Syokota && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) { 76432316Syokota warn("setting accentmap"); 76532316Syokota fclose(fd); 76632316Syokota return; 76732316Syokota } 7682088Ssos} 7692088Ssos 7702088Ssosvoid 7712088Ssosprint_keymap() 7722088Ssos{ 77332316Syokota keymap_t keymap; 77432316Syokota accentmap_t accentmap; 7752088Ssos int i; 7762088Ssos 77732316Syokota if (ioctl(0, GIO_KEYMAP, &keymap) < 0) 77829603Scharnier err(1, "getting keymap"); 77932316Syokota if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) 78032316Syokota memset(&accentmap, 0, sizeof(accentmap)); 7812088Ssos printf( 7822088Ssos"# alt\n" 7832088Ssos"# scan cntrl alt alt cntrl lock\n" 7842088Ssos"# code base shift cntrl shift alt shift cntrl shift state\n" 7852088Ssos"# ------------------------------------------------------------------\n" 7862088Ssos ); 78732316Syokota for (i=0; i<keymap.n_keys; i++) 78832316Syokota print_key_definition_line(stdout, i, &keymap.key[i]); 78932316Syokota 79032316Syokota printf("\n"); 79132316Syokota for (i = 0; i < NUM_DEADKEYS; i++) 79232316Syokota print_accent_definition_line(stdout, i, &accentmap.acc[i]); 79332316Syokota 7942088Ssos} 7952088Ssos 7962088Ssos 7972088Ssosvoid 7982088Ssosload_default_functionkeys() 7992088Ssos{ 8002088Ssos fkeyarg_t fkey; 8012088Ssos int i; 8022088Ssos 8032088Ssos for (i=0; i<NUM_FKEYS; i++) { 8042088Ssos fkey.keynum = i; 8052088Ssos strcpy(fkey.keydef, fkey_table[i]); 8062088Ssos fkey.flen = strlen(fkey_table[i]); 8072088Ssos if (ioctl(0, SETFKEY, &fkey) < 0) 80829603Scharnier warn("setting function key"); 8092088Ssos } 8102088Ssos} 8112088Ssos 8122088Ssosvoid 8132088Ssosset_functionkey(char *keynumstr, char *string) 8142088Ssos{ 8152088Ssos fkeyarg_t fkey; 8162088Ssos 8172088Ssos if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 8182088Ssos load_default_functionkeys(); 8192088Ssos return; 8202088Ssos } 8212088Ssos fkey.keynum = atoi(keynumstr); 8222088Ssos if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 82329603Scharnier warnx("function key number must be between 1 and %d", 8242088Ssos NUM_FKEYS); 8252088Ssos return; 8262088Ssos } 8272088Ssos if ((fkey.flen = strlen(string)) > MAXFK) { 82829603Scharnier warnx("function key string too long (%d > %d)", 8292088Ssos fkey.flen, MAXFK); 8302088Ssos return; 8312088Ssos } 8322088Ssos strcpy(fkey.keydef, string); 8332088Ssos fkey.keynum -= 1; 8342088Ssos if (ioctl(0, SETFKEY, &fkey) < 0) 83529603Scharnier warn("setting function key"); 8362088Ssos} 8372088Ssos 8382088Ssos 8392088Ssosvoid 8402088Ssosset_bell_values(char *opt) 8412088Ssos{ 8425536Ssos int bell, duration, pitch; 8432088Ssos 84438044Syokota bell = 0; 84538044Syokota if (!strncmp(opt, "quiet.", 6)) { 84638044Syokota bell = 2; 84738044Syokota opt += 6; 84838044Syokota } 8498857Srgrimes if (!strcmp(opt, "visual")) 85038044Syokota bell |= 1; 8515536Ssos else if (!strcmp(opt, "normal")) 85238044Syokota duration = 5, pitch = 800; 85348982Syokota else if (!strcmp(opt, "off")) 85448982Syokota duration = 0, pitch = 0; 8552088Ssos else { 8562088Ssos char *v1; 8578857Srgrimes 8585536Ssos bell = 0; 8592088Ssos duration = strtol(opt, &v1, 0); 8602088Ssos if ((duration < 0) || (*v1 != '.')) 8612088Ssos goto badopt; 8622088Ssos opt = ++v1; 8632088Ssos pitch = strtol(opt, &v1, 0); 8642088Ssos if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 8652088Ssosbadopt: 86629603Scharnier warnx("argument to -b must be DURATION.PITCH"); 8672088Ssos return; 8682088Ssos } 86938044Syokota if (pitch != 0) 87038044Syokota pitch = 1193182 / pitch; /* in Hz */ 87138044Syokota duration /= 10; /* in 10 m sec */ 8722088Ssos } 8732088Ssos 8745536Ssos ioctl(0, CONS_BELLTYPE, &bell); 87538044Syokota if ((bell & ~2) == 0) 8765536Ssos fprintf(stderr, "[=%d;%dB", pitch, duration); 8772088Ssos} 8782088Ssos 8792088Ssos 8802088Ssosvoid 8812088Ssosset_keyrates(char *opt) 8822088Ssos{ 88344628Syokota int arg[2]; 88439047Syokota int repeat; 88539047Syokota int delay; 88646761Syokota int r, d; 8872088Ssos 88846761Syokota if (!strcmp(opt, "slow")) { 88944628Syokota delay = 1000, repeat = 500; 89046761Syokota d = 3, r = 31; 89146761Syokota } else if (!strcmp(opt, "normal")) { 89244628Syokota delay = 500, repeat = 125; 89346761Syokota d = 1, r = 15; 89446761Syokota } else if (!strcmp(opt, "fast")) { 89539047Syokota delay = repeat = 0; 89646761Syokota d = r = 0; 89746761Syokota } else { 8982088Ssos int n; 8992088Ssos char *v1; 9002088Ssos 9012088Ssos delay = strtol(opt, &v1, 0); 9022088Ssos if ((delay < 0) || (*v1 != '.')) 9032088Ssos goto badopt; 9042088Ssos opt = ++v1; 9052088Ssos repeat = strtol(opt, &v1, 0); 9062088Ssos if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 9072088Ssosbadopt: 90829603Scharnier warnx("argument to -r must be delay.repeat"); 9092088Ssos return; 9102088Ssos } 91146761Syokota for (n = 0; n < ndelays - 1; n++) 91246761Syokota if (delay <= delays[n]) 91346761Syokota break; 91446761Syokota d = n; 91546761Syokota for (n = 0; n < nrepeats - 1; n++) 91646761Syokota if (repeat <= repeats[n]) 91746761Syokota break; 91846761Syokota r = n; 9192088Ssos } 9202088Ssos 92144628Syokota arg[0] = delay; 92244628Syokota arg[1] = repeat; 92346761Syokota if (ioctl(0, KDSETREPEAT, arg)) { 92446761Syokota if (ioctl(0, KDSETRAD, (d << 5) | r)) 92546761Syokota warn("setting keyboard rate"); 92646761Syokota } 9272088Ssos} 9282088Ssos 9292088Ssos 9306046Ssosvoid 9316046Ssosset_history(char *opt) 9326046Ssos{ 9336046Ssos int size; 9346046Ssos 9356046Ssos size = atoi(opt); 9366046Ssos if ((*opt == '\0') || size < 0) { 93729603Scharnier warnx("argument must be a positive number"); 9386046Ssos return; 9396046Ssos } 9406046Ssos if (ioctl(0, CONS_HISTORY, &size) == -1) 94129603Scharnier warn("setting history buffer size"); 9426046Ssos} 9436046Ssos 94442505Syokotastatic char 94542505Syokota*get_kbd_type_name(int type) 94642505Syokota{ 94742505Syokota static struct { 94842505Syokota int type; 94942505Syokota char *name; 95042505Syokota } name_table[] = { 95142505Syokota { KB_84, "AT 84" }, 95242505Syokota { KB_101, "AT 101/102" }, 95342505Syokota { KB_OTHER, "generic" }, 95442505Syokota }; 95542505Syokota int i; 9566046Ssos 95742505Syokota for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 95842505Syokota if (type == name_table[i].type) 95942505Syokota return name_table[i].name; 96042505Syokota } 96142505Syokota return "unknown"; 96242505Syokota} 96342505Syokota 96442505Syokotavoid 96542505Syokotashow_kbd_info(void) 96642505Syokota{ 96742505Syokota keyboard_info_t info; 96842505Syokota 96942505Syokota if (ioctl(0, KDGKBINFO, &info) == -1) { 97042505Syokota warn("unable to obtain keyboard information"); 97142505Syokota return; 97242505Syokota } 97342505Syokota printf("kbd%d:\n", info.kb_index); 97442505Syokota printf(" %.*s%d, type:%s (%d)\n", 97542505Syokota sizeof(info.kb_name), info.kb_name, info.kb_unit, 97642505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 97742505Syokota} 97842505Syokota 97942505Syokota 98042505Syokotavoid 98142505Syokotaset_keyboard(char *device) 98242505Syokota{ 98342505Syokota keyboard_info_t info; 98442505Syokota int fd; 98542505Syokota 98642505Syokota fd = open(device, O_RDONLY); 98742505Syokota if (fd < 0) { 98842505Syokota warn("cannot open %s", device); 98942505Syokota return; 99042505Syokota } 99142505Syokota if (ioctl(fd, KDGKBINFO, &info) == -1) { 99242505Syokota warn("unable to obtain keyboard information"); 99342505Syokota close(fd); 99442505Syokota return; 99542505Syokota } 99642505Syokota /* 99742505Syokota * The keyboard device driver won't release the keyboard by 99842505Syokota * the following ioctl, but it automatically will, when the device 99942505Syokota * is closed. So, we don't check error here. 100042505Syokota */ 100142505Syokota ioctl(fd, CONS_RELKBD, 0); 100242505Syokota close(fd); 100342505Syokota#if 1 100442505Syokota printf("kbd%d\n", info.kb_index); 100542505Syokota printf(" %.*s%d, type:%s (%d)\n", 100642505Syokota sizeof(info.kb_name), info.kb_name, info.kb_unit, 100742505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 100842505Syokota#endif 100942505Syokota 101042505Syokota if (ioctl(0, CONS_SETKBD, info.kb_index) == -1) 101142505Syokota warn("unable to set keyboard"); 101242505Syokota} 101342505Syokota 101442505Syokota 101542505Syokotavoid 101642505Syokotarelease_keyboard(void) 101742505Syokota{ 101842505Syokota keyboard_info_t info; 101942505Syokota 102042505Syokota /* 102142505Syokota * If stdin is not associated with a keyboard, the following ioctl 102242505Syokota * will fail. 102342505Syokota */ 102442505Syokota if (ioctl(0, KDGKBINFO, &info) == -1) { 102542505Syokota warn("unable to obtain keyboard information"); 102642505Syokota return; 102742505Syokota } 102842505Syokota#if 1 102942505Syokota printf("kbd%d\n", info.kb_index); 103042505Syokota printf(" %.*s%d, type:%s (%d)\n", 103142505Syokota sizeof(info.kb_name), info.kb_name, info.kb_unit, 103242505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 103342505Syokota#endif 103442505Syokota if (ioctl(0, CONS_RELKBD, 0) == -1) 103542505Syokota warn("unable to release the keyboard"); 103642505Syokota} 103742505Syokota 103842505Syokota 103929603Scharnierstatic void 10402088Ssosusage() 10412088Ssos{ 104229603Scharnier fprintf(stderr, "%s\n%s\n%s\n", 104342505Syokota"usage: kbdcontrol [-dFKix] [-b duration.pitch | [quiet.]belltype]", 104429603Scharnier" [-r delay.repeat | speed] [-l mapfile] [-f # string]", 104542505Syokota" [-h size] [-k device] [-L mapfile]"); 104629603Scharnier exit(1); 10472088Ssos} 10482088Ssos 10492088Ssos 105051287Speterint 10512088Ssosmain(int argc, char **argv) 10522088Ssos{ 10532088Ssos int opt; 10542088Ssos 105542505Syokota while((opt = getopt(argc, argv, "b:df:h:iKk:Fl:L:r:x")) != -1) 10562088Ssos switch(opt) { 10572088Ssos case 'b': 10582088Ssos set_bell_values(optarg); 10592088Ssos break; 10602088Ssos case 'd': 10612088Ssos print_keymap(); 10622088Ssos break; 10632088Ssos case 'l': 106419569Sjoerg load_keymap(optarg, 0); 10652088Ssos break; 106619569Sjoerg case 'L': 106719569Sjoerg load_keymap(optarg, 1); 106819569Sjoerg break; 10692088Ssos case 'f': 10708857Srgrimes set_functionkey(optarg, 10712088Ssos nextarg(argc, argv, &optind, 'f')); 10722088Ssos break; 10732088Ssos case 'F': 10742088Ssos load_default_functionkeys(); 10752088Ssos break; 10766046Ssos case 'h': 10776046Ssos set_history(optarg); 10786046Ssos break; 107942505Syokota case 'i': 108042505Syokota show_kbd_info(); 108142505Syokota break; 108242505Syokota case 'K': 108342505Syokota release_keyboard(); 108442505Syokota break; 108542505Syokota case 'k': 108642505Syokota set_keyboard(optarg); 108742505Syokota break; 10882088Ssos case 'r': 10892088Ssos set_keyrates(optarg); 10902088Ssos break; 10912088Ssos case 'x': 10922088Ssos hex = 1; 10932088Ssos break; 10942088Ssos default: 10952088Ssos usage(); 10962088Ssos } 109729603Scharnier if ((optind != argc) || (argc == 1)) 10982088Ssos usage(); 10992088Ssos exit(0); 11002088Ssos} 11012088Ssos 11022088Ssos 1103