kbdcontrol.c revision 42505
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[] =
3142505Syokota	"$Id: kbdcontrol.c,v 1.19 1998/09/10 12:20:09 yokota Exp $";
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
912088Ssosconst int	delays[]  = {250, 500, 750, 1000};
922088Ssosconst int	repeats[] = { 34,  38,  42,  46,  50,  55,  59,  63,
932088Ssos			      68,  76,  84,  92, 100, 110, 118, 126,
942088Ssos			     136, 152, 168, 184, 200, 220, 236, 252,
952088Ssos			     272, 304, 336, 368, 400, 440, 472, 504};
962088Ssosconst int	ndelays = (sizeof(delays) / sizeof(int));
972088Ssosconst 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;
1662088Ssos	case TRCTR:
1672088Ssos		return RCTR | 0x100;
1682088Ssos	case TRALT:
1692088Ssos		return RALT | 0x100;
1702088Ssos	case TALK:
1712088Ssos		return ALK | 0x100;
1722088Ssos	case TASH:
1732088Ssos		return ASH | 0x100;
1742088Ssos	case TMETA:
1752088Ssos		return META | 0x100;
1762088Ssos	case TRBT:
1772088Ssos		return RBT | 0x100;
1782088Ssos	case TDBG:
1792088Ssos		return DBG | 0x100;
1805994Ssos	case TSUSP:
1815994Ssos		return SUSP | 0x100;
18238053Syokota	case TSPSC:
18338053Syokota		return SPSC | 0x100;
18432316Syokota	case TACC:
18532316Syokota		if (ACC(number) > L_ACC)
18632316Syokota			return -1;
18732316Syokota		return ACC(number) | 0x100;
1882088Ssos	case TFUNC:
1892088Ssos		if (F(number) > L_FN)
1902088Ssos			return -1;
1912088Ssos		return F(number) | 0x100;
1922088Ssos	case TSCRN:
1932088Ssos		if (S(number) > L_SCR)
1942088Ssos			return -1;
1952088Ssos		return S(number) | 0x100;
1962088Ssos	case TLET:
1972088Ssos		return (unsigned char)letter;
1982088Ssos	case TNUM:
1992088Ssos		if (number < 0 || number > 255)
2002088Ssos			return -1;
2012088Ssos		return number;
2022088Ssos	default:
2032088Ssos		return -1;
2042088Ssos	}
2052088Ssos}
2062088Ssos
2072088Ssosint
20832316Syokotaget_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap)
2092088Ssos{
21032316Syokota	int c;
2112088Ssos
2122088Ssos	yyin = fd;
2132088Ssos
21432316Syokota	if (token < 0)
21532316Syokota		token = yylex();
21632316Syokota	switch (token) {
21732316Syokota	case TNUM:
21832316Syokota		c = get_key_definition_line(keymap);
21932316Syokota		if (c < 0)
22032316Syokota			errx(1, "invalid key definition");
22132316Syokota		if (c > keymap->n_keys)
22232316Syokota			keymap->n_keys = c;
22332316Syokota		break;
22432316Syokota	case TACC:
22532316Syokota		c = get_accent_definition_line(accentmap);
22632316Syokota		if (c < 0)
22732316Syokota			errx(1, "invalid accent key definition");
22832316Syokota		if (c > accentmap->n_accs)
22932316Syokota			accentmap->n_accs = c;
23032316Syokota		break;
23132316Syokota	case 0:
23232316Syokota		/* EOF */
2332088Ssos		return -1;
23432316Syokota	default:
23532316Syokota		errx(1, "illegal definition line");
23632316Syokota	}
23732316Syokota	return c;
23832316Syokota}
23932316Syokota
24032316Syokotaint
24132316Syokotaget_key_definition_line(keymap_t *map)
24232316Syokota{
24332316Syokota	int i, def, scancode;
24432316Syokota
24532316Syokota	/* check scancode number */
2462088Ssos	if (number < 0 || number >= NUM_KEYS)
2472088Ssos		return -1;
2482088Ssos	scancode = number;
2492088Ssos
2502088Ssos	/* get key definitions */
2512088Ssos	map->key[scancode].spcl = 0;
2522088Ssos	for (i=0; i<NUM_STATES; i++) {
2532088Ssos		if ((def = get_entry()) == -1)
2542088Ssos			return -1;
2552088Ssos		if (def & 0x100)
2562088Ssos			map->key[scancode].spcl |= (0x80 >> i);
2572088Ssos		map->key[scancode].map[i] = def & 0xFF;
2582088Ssos	}
2592088Ssos	/* get lock state key def */
26032316Syokota	if ((token = yylex()) != TFLAG)
2612088Ssos		return -1;
2622088Ssos	map->key[scancode].flgs = number;
26332316Syokota	token = yylex();
26432316Syokota	return (scancode + 1);
2652088Ssos}
2662088Ssos
26732316Syokotaint
26832316Syokotaget_accent_definition_line(accentmap_t *map)
26932316Syokota{
27032316Syokota	int accent;
27132316Syokota	int c1, c2;
27232316Syokota	int i;
2732088Ssos
27432316Syokota	if (ACC(number) < F_ACC || ACC(number) > L_ACC)
27532316Syokota		/* number out of range */
27632316Syokota		return -1;
27732316Syokota	accent = number;
27832316Syokota	if (map->acc[accent].accchar != 0) {
27932316Syokota		/* this entry has already been defined before! */
28032316Syokota		errx(1, "duplicated accent key definition");
28132316Syokota	}
28232316Syokota
28332316Syokota	switch ((token = yylex())) {
28432316Syokota	case TLET:
28532316Syokota		map->acc[accent].accchar = letter;
28632316Syokota		break;
28732316Syokota	case TNUM:
28832316Syokota		map->acc[accent].accchar = number;
28932316Syokota		break;
29032316Syokota	default:
29132316Syokota		return -1;
29232316Syokota	}
29332316Syokota
29432316Syokota	for (i = 0; (token = yylex()) == '(';) {
29532316Syokota		switch ((token = yylex())) {
29632316Syokota		case TLET:
29732316Syokota			c1 = letter;
29832316Syokota			break;
29932316Syokota		case TNUM:
30032316Syokota			c1 = number;
30132316Syokota			break;
30232316Syokota		default:
30332316Syokota			return -1;
30432316Syokota		}
30532316Syokota		switch ((token = yylex())) {
30632316Syokota		case TLET:
30732316Syokota			c2 = letter;
30832316Syokota			break;
30932316Syokota		case TNUM:
31032316Syokota			c2 = number;
31132316Syokota			break;
31232316Syokota		default:
31332316Syokota			return -1;
31432316Syokota		}
31532316Syokota		if ((token = yylex()) != ')')
31632316Syokota			return -1;
31732316Syokota		if (i >= NUM_ACCENTCHARS) {
31832316Syokota			warnx("too many accented characters, ignored");
31932316Syokota			continue;
32032316Syokota		}
32132316Syokota		map->acc[accent].map[i][0] = c1;
32232316Syokota		map->acc[accent].map[i][1] = c2;
32332316Syokota		++i;
32432316Syokota	}
32532316Syokota	return (accent + 1);
32632316Syokota}
32732316Syokota
32829603Scharniervoid
3292088Ssosprint_entry(FILE *fp, int value)
3302088Ssos{
3312088Ssos	int val = value & 0xFF;
3322088Ssos
3332088Ssos	switch (value) {
3342088Ssos	case NOP | 0x100:
3358857Srgrimes		fprintf(fp, " nop   ");
3362088Ssos		break;
3372088Ssos	case LSH | 0x100:
3382088Ssos		fprintf(fp, " lshift");
3392088Ssos		break;
3402088Ssos	case RSH | 0x100:
3412088Ssos		fprintf(fp, " rshift");
3422088Ssos		break;
3432088Ssos	case CLK | 0x100:
3442088Ssos		fprintf(fp, " clock ");
3452088Ssos		break;
3462088Ssos	case NLK | 0x100:
3472088Ssos		fprintf(fp, " nlock ");
3482088Ssos		break;
3492088Ssos	case SLK | 0x100:
3502088Ssos		fprintf(fp, " slock ");
3512088Ssos		break;
3522088Ssos	case BTAB | 0x100:
3532088Ssos		fprintf(fp, " btab  ");
3542088Ssos		break;
3552088Ssos	case LALT | 0x100:
3562088Ssos		fprintf(fp, " lalt  ");
3572088Ssos		break;
3582088Ssos	case LCTR | 0x100:
3592088Ssos		fprintf(fp, " lctrl ");
3602088Ssos		break;
3612088Ssos	case NEXT | 0x100:
3622088Ssos		fprintf(fp, " nscr  ");
3632088Ssos		break;
3642088Ssos	case RCTR | 0x100:
3652088Ssos		fprintf(fp, " rctrl ");
3662088Ssos		break;
3672088Ssos	case RALT | 0x100:
3682088Ssos		fprintf(fp, " ralt  ");
3692088Ssos		break;
3702088Ssos	case ALK | 0x100:
3712088Ssos		fprintf(fp, " alock ");
3722088Ssos		break;
3732088Ssos	case ASH | 0x100:
3742088Ssos		fprintf(fp, " ashift");
3752088Ssos		break;
3762088Ssos	case META | 0x100:
3772088Ssos		fprintf(fp, " meta  ");
3782088Ssos		break;
3792088Ssos	case RBT | 0x100:
3802088Ssos		fprintf(fp, " boot  ");
3812088Ssos		break;
3822088Ssos	case DBG | 0x100:
3832088Ssos		fprintf(fp, " debug ");
3842088Ssos		break;
38532316Syokota	case SUSP | 0x100:
38632316Syokota		fprintf(fp, " susp  ");
38732316Syokota		break;
38838053Syokota	case SPSC | 0x100:
38938053Syokota		fprintf(fp, " saver ");
39038053Syokota		break;
3912088Ssos	default:
3922088Ssos		if (value & 0x100) {
3938857Srgrimes		 	if (val >= F_FN && val <= L_FN)
3942088Ssos				fprintf(fp, " fkey%02d", val - F_FN + 1);
3958857Srgrimes		 	else if (val >= F_SCR && val <= L_SCR)
3962088Ssos				fprintf(fp, " scr%02d ", val - F_SCR + 1);
39732316Syokota		 	else if (val >= F_ACC && val <= L_ACC)
39832316Syokota				fprintf(fp, " %-6s", acc_names[val - F_ACC]);
3992088Ssos			else if (hex)
4008857Srgrimes				fprintf(fp, " 0x%02x  ", val);
4012088Ssos			else
40232316Syokota				fprintf(fp, " %3d   ", val);
4032088Ssos		}
4042088Ssos		else {
4052088Ssos			if (val < ' ')
4068857Srgrimes				fprintf(fp, " %s   ", ctrl_names[val]);
4072088Ssos			else if (val == 127)
4088857Srgrimes				fprintf(fp, " del   ");
4099202Srgrimes			else if (isascii(val) && isprint(val))
4108857Srgrimes				fprintf(fp, " '%c'   ", val);
4112088Ssos			else if (hex)
4128857Srgrimes				fprintf(fp, " 0x%02x  ", val);
4132088Ssos			else
4148857Srgrimes				fprintf(fp, " %3d   ", val);
4152088Ssos		}
4162088Ssos	}
4172088Ssos}
4182088Ssos
4192088Ssos
4202088Ssosvoid
42142505Syokotaprint_key_definition_line(FILE *fp, int scancode, struct keyent_t *key)
4222088Ssos{
42329603Scharnier	int i;
4242088Ssos
4252088Ssos	/* print scancode number */
4262088Ssos	if (hex)
4272088Ssos		fprintf(fp, " 0x%02x  ", scancode);
4282088Ssos	else
4292088Ssos		fprintf(fp, "  %03d  ", scancode);
4302088Ssos
4312088Ssos	/* print key definitions */
4322088Ssos	for (i=0; i<NUM_STATES; i++) {
4332088Ssos		if (key->spcl & (0x80 >> i))
4342088Ssos			print_entry(fp, key->map[i] | 0x100);
4352088Ssos		else
4368857Srgrimes			print_entry(fp, key->map[i]);
4372088Ssos	}
4382088Ssos
4392088Ssos	/* print lock state key def */
4402088Ssos	switch (key->flgs) {
4412088Ssos	case 0:
4422088Ssos		fprintf(fp, "  O\n");
4432088Ssos		break;
4442088Ssos	case 1:
4452088Ssos		fprintf(fp, "  C\n");
4462088Ssos		break;
4472088Ssos	case 2:
4482088Ssos		fprintf(fp, "  N\n");
4492088Ssos		break;
4506046Ssos	case 3:
4516046Ssos		fprintf(fp, "  B\n");
4526046Ssos		break;
4538857Srgrimes	}
4542088Ssos}
4552088Ssos
45632316Syokotavoid
45732316Syokotaprint_accent_definition_line(FILE *fp, int accent, struct acc_t *key)
45832316Syokota{
45932316Syokota	int c;
46032316Syokota	int i;
4612088Ssos
46232316Syokota	if (key->accchar == 0)
46332316Syokota		return;
46432316Syokota
46532316Syokota	/* print accent number */
46632316Syokota	fprintf(fp, "  %-6s", acc_names[accent]);
46732316Syokota	if (isascii(key->accchar) && isprint(key->accchar))
46832316Syokota		fprintf(fp, "'%c'  ", key->accchar);
46932316Syokota	else if (hex)
47032316Syokota		fprintf(fp, "0x%02x ", key->accchar);
47132316Syokota	else
47232316Syokota		fprintf(fp, "%03d  ", key->accchar);
47332316Syokota
47432316Syokota	for (i = 0; i < NUM_ACCENTCHARS; ++i) {
47532316Syokota		c = key->map[i][0];
47632316Syokota		if (c == 0)
47732316Syokota			break;
47832316Syokota		if ((i > 0) && ((i % 4) == 0))
47932316Syokota			fprintf(fp, "\n             ");
48032316Syokota		if (isascii(c) && isprint(c))
48132316Syokota			fprintf(fp, "( '%c' ", c);
48232316Syokota		else if (hex)
48332316Syokota			fprintf(fp, "(0x%02x ", c);
48432316Syokota		else
48532316Syokota			fprintf(fp, "( %03d ", c);
48632316Syokota		c = key->map[i][1];
48732316Syokota		if (isascii(c) && isprint(c))
48832316Syokota			fprintf(fp, "'%c' ) ", c);
48932316Syokota		else if (hex)
49032316Syokota			fprintf(fp, "0x%02x) ", c);
49132316Syokota		else
49232316Syokota			fprintf(fp, "%03d ) ", c);
49332316Syokota	}
49432316Syokota	fprintf(fp, "\n");
49532316Syokota}
49632316Syokota
4972088Ssosvoid
49832316Syokotadump_entry(int value)
49932316Syokota{
50032316Syokota	if (value & 0x100) {
50132316Syokota		value &= 0x00ff;
50232316Syokota		switch (value) {
50332316Syokota		case NOP:
50432316Syokota			printf("  NOP, ");
50532316Syokota			break;
50632316Syokota		case LSH:
50732316Syokota			printf("  LSH, ");
50832316Syokota			break;
50932316Syokota		case RSH:
51032316Syokota			printf("  RSH, ");
51132316Syokota			break;
51232316Syokota		case CLK:
51332316Syokota			printf("  CLK, ");
51432316Syokota			break;
51532316Syokota		case NLK:
51632316Syokota			printf("  NLK, ");
51732316Syokota			break;
51832316Syokota		case SLK:
51932316Syokota			printf("  SLK, ");
52032316Syokota			break;
52132316Syokota		case BTAB:
52232316Syokota			printf(" BTAB, ");
52332316Syokota			break;
52432316Syokota		case LALT:
52532316Syokota			printf(" LALT, ");
52632316Syokota			break;
52732316Syokota		case LCTR:
52832316Syokota			printf(" LCTR, ");
52932316Syokota			break;
53032316Syokota		case NEXT:
53132316Syokota			printf(" NEXT, ");
53232316Syokota			break;
53332316Syokota		case RCTR:
53432316Syokota			printf(" RCTR, ");
53532316Syokota			break;
53632316Syokota		case RALT:
53732316Syokota			printf(" RALT, ");
53832316Syokota			break;
53932316Syokota		case ALK:
54032316Syokota			printf("  ALK, ");
54132316Syokota			break;
54232316Syokota		case ASH:
54332316Syokota			printf("  ASH, ");
54432316Syokota			break;
54532316Syokota		case META:
54632316Syokota			printf(" META, ");
54732316Syokota			break;
54832316Syokota		case RBT:
54932316Syokota			printf("  RBT, ");
55032316Syokota			break;
55132316Syokota		case DBG:
55232316Syokota			printf("  DBG, ");
55332316Syokota			break;
55432316Syokota		case SUSP:
55532316Syokota			printf(" SUSP, ");
55632316Syokota			break;
55738053Syokota		case SPSC:
55838053Syokota			printf(" SPSC, ");
55938053Syokota			break;
56032316Syokota		default:
56132316Syokota	 		if (value >= F_FN && value <= L_FN)
56232316Syokota				printf(" F(%2d),", value - F_FN + 1);
56332316Syokota	 		else if (value >= F_SCR && value <= L_SCR)
56432486Syokota				printf(" S(%2d),", value - F_SCR + 1);
56532316Syokota	 		else if (value >= F_ACC && value <= L_ACC)
56632316Syokota				printf(" %-4s, ", acc_names_u[value - F_ACC]);
56732316Syokota			else
56832316Syokota				printf(" 0x%02X, ", value);
56932316Syokota			break;
57032316Syokota		}
57132316Syokota	} else if (value == '\'') {
57232316Syokota		printf(" '\\'', ");
57332316Syokota	} else if (value == '\\') {
57432316Syokota		printf(" '\\\\', ");
57532316Syokota	} else if (isascii(value) && isprint(value)) {
57632316Syokota		printf("  '%c', ", value);
57732316Syokota	} else {
57832316Syokota		printf(" 0x%02X, ", value);
57932316Syokota	}
58032316Syokota}
58132316Syokota
58232316Syokotavoid
58332316Syokotadump_key_definition(char *name, keymap_t *keymap)
58432316Syokota{
58532316Syokota	int	i, j;
58632316Syokota
58732486Syokota	printf("static keymap_t keymap_%s = { 0x%02x, {\n",
58832316Syokota	       name, (unsigned)keymap->n_keys);
58932316Syokota	printf(
59032486Syokota"/*                                                         alt\n"
59132486Syokota" * scan                       cntrl          alt    alt   cntrl\n"
59232486Syokota" * code  base   shift  cntrl  shift   alt   shift  cntrl  shift    spcl flgs\n"
59332316Syokota" * ---------------------------------------------------------------------------\n"
59432316Syokota" */\n");
59532316Syokota	for (i = 0; i < keymap->n_keys; i++) {
59632486Syokota		printf("/*%02x*/{{", i);
59732316Syokota		for (j = 0; j < NUM_STATES; j++) {
59832316Syokota			if (keymap->key[i].spcl & (0x80 >> j))
59932316Syokota				dump_entry(keymap->key[i].map[j] | 0x100);
60032316Syokota			else
60132316Syokota				dump_entry(keymap->key[i].map[j]);
60232316Syokota		}
60332486Syokota		printf("}, 0x%02X,0x%02X },\n",
60432316Syokota		       (unsigned)keymap->key[i].spcl,
60532316Syokota		       (unsigned)keymap->key[i].flgs);
60632316Syokota	}
60732486Syokota	printf("} };\n\n");
60832316Syokota}
60932316Syokota
61032316Syokotavoid
61132316Syokotadump_accent_definition(char *name, accentmap_t *accentmap)
61232316Syokota{
61332316Syokota	int i, j;
61432316Syokota	int c;
61532316Syokota
61632486Syokota	printf("static accentmap_t accentmap_%s = { %d",
61732316Syokota		name, accentmap->n_accs);
61832486Syokota	if (accentmap->n_accs <= 0) {
61932486Syokota		printf(" };\n\n");
62032486Syokota		return;
62132486Syokota	}
62232486Syokota	printf(", {\n");
62332316Syokota	for (i = 0; i < NUM_DEADKEYS; i++) {
62432316Syokota		printf("    /* %s=%d */\n    {", acc_names[i], i);
62532316Syokota		c = accentmap->acc[i].accchar;
62632316Syokota		if (c == '\'')
62732316Syokota			printf(" '\\'', {");
62832316Syokota		else if (c == '\\')
62932316Syokota			printf(" '\\\\', {");
63032316Syokota		else if (isascii(c) && isprint(c))
63132316Syokota			printf("  '%c', {", c);
63232316Syokota		else if (c == 0) {
63332316Syokota			printf(" 0x00 }, \n");
63432316Syokota			continue;
63532316Syokota		} else
63632316Syokota			printf(" 0x%02x, {", c);
63732316Syokota		for (j = 0; j < NUM_ACCENTCHARS; j++) {
63832316Syokota			c = accentmap->acc[i].map[j][0];
63932316Syokota			if (c == 0)
64032316Syokota				break;
64132316Syokota			if ((j > 0) && ((j % 4) == 0))
64232316Syokota				printf("\n\t     ");
64332316Syokota			if (isascii(c) && isprint(c))
64432316Syokota				printf(" {  '%c',", c);
64532316Syokota			else
64632316Syokota				printf(" { 0x%02x,", c);
64732316Syokota			printf("0x%02x },", accentmap->acc[i].map[j][1]);
64832316Syokota		}
64932316Syokota		printf(" }, },\n");
65032316Syokota	}
65132486Syokota	printf("} };\n\n");
65232316Syokota}
65332316Syokota
65432316Syokotavoid
65519569Sjoergload_keymap(char *opt, int dumponly)
6562088Ssos{
65732316Syokota	keymap_t keymap;
65832316Syokota	accentmap_t accentmap;
6592088Ssos	FILE	*fd;
66032316Syokota	int	i;
66119569Sjoerg	char	*name, *cp;
66235750Sdes	char	*prefix[]  = {"", "", KEYMAP_PATH, KEYMAP_PATH, NULL};
66335750Sdes	char	*postfix[] = {"", ".kbd", "", ".kbd"};
6642088Ssos
6652088Ssos	for (i=0; prefix[i]; i++) {
6662088Ssos		name = mkfullname(prefix[i], opt, postfix[i]);
66729603Scharnier		if ((fd = fopen(name, "r")))
6682088Ssos			break;
6692088Ssos	}
6702088Ssos	if (fd == NULL) {
67129603Scharnier		warn("keymap file not found");
6722088Ssos		return;
6732088Ssos	}
67432316Syokota	memset(&keymap, 0, sizeof(keymap));
67532316Syokota	memset(&accentmap, 0, sizeof(accentmap));
67632316Syokota	token = -1;
6772088Ssos	while (1) {
67832316Syokota		if (get_definition_line(fd, &keymap, &accentmap) < 0)
6792088Ssos			break;
6802088Ssos    	}
68119569Sjoerg	if (dumponly) {
68219569Sjoerg		/* fix up the filename to make it a valid C identifier */
68319569Sjoerg		for (cp = opt; *cp; cp++)
68419569Sjoerg			if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_';
68532316Syokota		printf("/*\n"
68632316Syokota		       " * Automatically generated from %s.\n"
68732316Syokota	               " * DO NOT EDIT!\n"
68832316Syokota		       " */\n", name);
68932316Syokota		dump_key_definition(opt, &keymap);
69032316Syokota		dump_accent_definition(opt, &accentmap);
69119569Sjoerg		return;
69219569Sjoerg	}
69332316Syokota	if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) {
69429603Scharnier		warn("setting keymap");
6952088Ssos		fclose(fd);
6962088Ssos		return;
6972088Ssos	}
69832316Syokota	if ((accentmap.n_accs > 0)
69932316Syokota		&& (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) {
70032316Syokota		warn("setting accentmap");
70132316Syokota		fclose(fd);
70232316Syokota		return;
70332316Syokota	}
7042088Ssos}
7052088Ssos
7062088Ssosvoid
7072088Ssosprint_keymap()
7082088Ssos{
70932316Syokota	keymap_t keymap;
71032316Syokota	accentmap_t accentmap;
7112088Ssos	int i;
7122088Ssos
71332316Syokota	if (ioctl(0, GIO_KEYMAP, &keymap) < 0)
71429603Scharnier		err(1, "getting keymap");
71532316Syokota	if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0)
71632316Syokota		memset(&accentmap, 0, sizeof(accentmap));
7172088Ssos    	printf(
7182088Ssos"#                                                         alt\n"
7192088Ssos"# scan                       cntrl          alt    alt   cntrl lock\n"
7202088Ssos"# code  base   shift  cntrl  shift  alt    shift  cntrl  shift state\n"
7212088Ssos"# ------------------------------------------------------------------\n"
7222088Ssos    	);
72332316Syokota	for (i=0; i<keymap.n_keys; i++)
72432316Syokota		print_key_definition_line(stdout, i, &keymap.key[i]);
72532316Syokota
72632316Syokota	printf("\n");
72732316Syokota	for (i = 0; i < NUM_DEADKEYS; i++)
72832316Syokota		print_accent_definition_line(stdout, i, &accentmap.acc[i]);
72932316Syokota
7302088Ssos}
7312088Ssos
7322088Ssos
7332088Ssosvoid
7342088Ssosload_default_functionkeys()
7352088Ssos{
7362088Ssos	fkeyarg_t fkey;
7372088Ssos	int i;
7382088Ssos
7392088Ssos	for (i=0; i<NUM_FKEYS; i++) {
7402088Ssos		fkey.keynum = i;
7412088Ssos		strcpy(fkey.keydef, fkey_table[i]);
7422088Ssos		fkey.flen = strlen(fkey_table[i]);
7432088Ssos		if (ioctl(0, SETFKEY, &fkey) < 0)
74429603Scharnier			warn("setting function key");
7452088Ssos	}
7462088Ssos}
7472088Ssos
7482088Ssosvoid
7492088Ssosset_functionkey(char *keynumstr, char *string)
7502088Ssos{
7512088Ssos	fkeyarg_t fkey;
7522088Ssos
7532088Ssos	if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) {
7542088Ssos		load_default_functionkeys();
7552088Ssos		return;
7562088Ssos	}
7572088Ssos	fkey.keynum = atoi(keynumstr);
7582088Ssos	if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) {
75929603Scharnier		warnx("function key number must be between 1 and %d",
7602088Ssos			NUM_FKEYS);
7612088Ssos		return;
7622088Ssos	}
7632088Ssos	if ((fkey.flen = strlen(string)) > MAXFK) {
76429603Scharnier		warnx("function key string too long (%d > %d)",
7652088Ssos			fkey.flen, MAXFK);
7662088Ssos		return;
7672088Ssos	}
7682088Ssos	strcpy(fkey.keydef, string);
7692088Ssos	fkey.keynum -= 1;
7702088Ssos	if (ioctl(0, SETFKEY, &fkey) < 0)
77129603Scharnier		warn("setting function key");
7722088Ssos}
7732088Ssos
7742088Ssos
7752088Ssosvoid
7762088Ssosset_bell_values(char *opt)
7772088Ssos{
7785536Ssos	int bell, duration, pitch;
7792088Ssos
78038044Syokota	bell = 0;
78138044Syokota	if (!strncmp(opt, "quiet.", 6)) {
78238044Syokota		bell = 2;
78338044Syokota		opt += 6;
78438044Syokota	}
7858857Srgrimes	if (!strcmp(opt, "visual"))
78638044Syokota		bell |= 1;
7875536Ssos	else if (!strcmp(opt, "normal"))
78838044Syokota		duration = 5, pitch = 800;
7892088Ssos	else {
7902088Ssos		char		*v1;
7918857Srgrimes
7925536Ssos		bell = 0;
7932088Ssos		duration = strtol(opt, &v1, 0);
7942088Ssos		if ((duration < 0) || (*v1 != '.'))
7952088Ssos			goto badopt;
7962088Ssos		opt = ++v1;
7972088Ssos		pitch = strtol(opt, &v1, 0);
7982088Ssos		if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) {
7992088Ssosbadopt:
80029603Scharnier			warnx("argument to -b must be DURATION.PITCH");
8012088Ssos			return;
8022088Ssos		}
80338044Syokota		if (pitch != 0)
80438044Syokota			pitch = 1193182 / pitch;	/* in Hz */
80538044Syokota		duration /= 10;	/* in 10 m sec */
8062088Ssos	}
8072088Ssos
8085536Ssos	ioctl(0, CONS_BELLTYPE, &bell);
80938044Syokota	if ((bell & ~2) == 0)
8105536Ssos		fprintf(stderr, "[=%d;%dB", pitch, duration);
8112088Ssos}
8122088Ssos
8132088Ssos
8142088Ssosvoid
8152088Ssosset_keyrates(char *opt)
8162088Ssos{
81739047Syokota	int repeat;
81839047Syokota	int delay;
8192088Ssos
8202088Ssos	if (!strcmp(opt, "slow"))
82139047Syokota		delay = 3, repeat = 31;
8222088Ssos	else if (!strcmp(opt, "normal"))
82339047Syokota		delay = 1, repeat = 15;
8242088Ssos	else if (!strcmp(opt, "fast"))
82539047Syokota		delay = repeat = 0;
8262088Ssos	else {
8272088Ssos		int		n;
8282088Ssos		char		*v1;
8292088Ssos
8302088Ssos		delay = strtol(opt, &v1, 0);
8312088Ssos		if ((delay < 0) || (*v1 != '.'))
8322088Ssos			goto badopt;
8332088Ssos		opt = ++v1;
8342088Ssos		repeat = strtol(opt, &v1, 0);
8352088Ssos		if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) {
8362088Ssosbadopt:
83729603Scharnier			warnx("argument to -r must be delay.repeat");
8382088Ssos			return;
8392088Ssos		}
8402088Ssos		for (n = 0; n < ndelays - 1; n++)
8412088Ssos			if (delay <= delays[n])
8422088Ssos				break;
84339047Syokota		delay = n;
8442088Ssos		for (n = 0; n < nrepeats - 1; n++)
8452088Ssos			if (repeat <= repeats[n])
8462088Ssos				break;
84739047Syokota		repeat = n;
8482088Ssos	}
8492088Ssos
85039047Syokota	if (ioctl(0, KDSETRAD, (delay << 5) | repeat) < 0)
85129603Scharnier		warn("setting keyboard rate");
8522088Ssos}
8532088Ssos
8542088Ssos
8556046Ssosvoid
8566046Ssosset_history(char *opt)
8576046Ssos{
8586046Ssos	int size;
8596046Ssos
8606046Ssos	size = atoi(opt);
8616046Ssos	if ((*opt == '\0') || size < 0) {
86229603Scharnier		warnx("argument must be a positive number");
8636046Ssos		return;
8646046Ssos	}
8656046Ssos	if (ioctl(0, CONS_HISTORY, &size) == -1)
86629603Scharnier		warn("setting history buffer size");
8676046Ssos}
8686046Ssos
86942505Syokotastatic char
87042505Syokota*get_kbd_type_name(int type)
87142505Syokota{
87242505Syokota	static struct {
87342505Syokota		int type;
87442505Syokota		char *name;
87542505Syokota	} name_table[] = {
87642505Syokota		{ KB_84,	"AT 84" },
87742505Syokota		{ KB_101,	"AT 101/102" },
87842505Syokota		{ KB_OTHER,	"generic" },
87942505Syokota	};
88042505Syokota	int i;
8816046Ssos
88242505Syokota	for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) {
88342505Syokota		if (type == name_table[i].type)
88442505Syokota			return name_table[i].name;
88542505Syokota	}
88642505Syokota	return "unknown";
88742505Syokota}
88842505Syokota
88942505Syokotavoid
89042505Syokotashow_kbd_info(void)
89142505Syokota{
89242505Syokota	keyboard_info_t info;
89342505Syokota
89442505Syokota	if (ioctl(0, KDGKBINFO, &info) == -1) {
89542505Syokota		warn("unable to obtain keyboard information");
89642505Syokota		return;
89742505Syokota	}
89842505Syokota	printf("kbd%d:\n", info.kb_index);
89942505Syokota	printf("    %.*s%d, type:%s (%d)\n",
90042505Syokota		sizeof(info.kb_name), info.kb_name, info.kb_unit,
90142505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
90242505Syokota}
90342505Syokota
90442505Syokota
90542505Syokotavoid
90642505Syokotaset_keyboard(char *device)
90742505Syokota{
90842505Syokota	keyboard_info_t info;
90942505Syokota	int fd;
91042505Syokota
91142505Syokota	fd = open(device, O_RDONLY);
91242505Syokota	if (fd < 0) {
91342505Syokota		warn("cannot open %s", device);
91442505Syokota		return;
91542505Syokota	}
91642505Syokota	if (ioctl(fd, KDGKBINFO, &info) == -1) {
91742505Syokota		warn("unable to obtain keyboard information");
91842505Syokota		close(fd);
91942505Syokota		return;
92042505Syokota	}
92142505Syokota	/*
92242505Syokota	 * The keyboard device driver won't release the keyboard by
92342505Syokota	 * the following ioctl, but it automatically will, when the device
92442505Syokota	 * is closed.  So, we don't check error here.
92542505Syokota	 */
92642505Syokota	ioctl(fd, CONS_RELKBD, 0);
92742505Syokota	close(fd);
92842505Syokota#if 1
92942505Syokota	printf("kbd%d\n", info.kb_index);
93042505Syokota	printf("    %.*s%d, type:%s (%d)\n",
93142505Syokota		sizeof(info.kb_name), info.kb_name, info.kb_unit,
93242505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
93342505Syokota#endif
93442505Syokota
93542505Syokota	if (ioctl(0, CONS_SETKBD, info.kb_index) == -1)
93642505Syokota		warn("unable to set keyboard");
93742505Syokota}
93842505Syokota
93942505Syokota
94042505Syokotavoid
94142505Syokotarelease_keyboard(void)
94242505Syokota{
94342505Syokota	keyboard_info_t info;
94442505Syokota
94542505Syokota	/*
94642505Syokota	 * If stdin is not associated with a keyboard, the following ioctl
94742505Syokota	 * will fail.
94842505Syokota	 */
94942505Syokota	if (ioctl(0, KDGKBINFO, &info) == -1) {
95042505Syokota		warn("unable to obtain keyboard information");
95142505Syokota		return;
95242505Syokota	}
95342505Syokota#if 1
95442505Syokota	printf("kbd%d\n", info.kb_index);
95542505Syokota	printf("    %.*s%d, type:%s (%d)\n",
95642505Syokota		sizeof(info.kb_name), info.kb_name, info.kb_unit,
95742505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
95842505Syokota#endif
95942505Syokota	if (ioctl(0, CONS_RELKBD, 0) == -1)
96042505Syokota		warn("unable to release the keyboard");
96142505Syokota}
96242505Syokota
96342505Syokota
96429603Scharnierstatic void
9652088Ssosusage()
9662088Ssos{
96729603Scharnier	fprintf(stderr, "%s\n%s\n%s\n",
96842505Syokota"usage: kbdcontrol [-dFKix] [-b  duration.pitch | [quiet.]belltype]",
96929603Scharnier"                  [-r delay.repeat | speed] [-l mapfile] [-f # string]",
97042505Syokota"                  [-h size] [-k device] [-L mapfile]");
97129603Scharnier	exit(1);
9722088Ssos}
9732088Ssos
9742088Ssos
9752088Ssosvoid
9762088Ssosmain(int argc, char **argv)
9772088Ssos{
9782088Ssos	int		opt;
9792088Ssos
98042505Syokota	while((opt = getopt(argc, argv, "b:df:h:iKk:Fl:L:r:x")) != -1)
9812088Ssos		switch(opt) {
9822088Ssos			case 'b':
9832088Ssos				set_bell_values(optarg);
9842088Ssos				break;
9852088Ssos			case 'd':
9862088Ssos				print_keymap();
9872088Ssos				break;
9882088Ssos			case 'l':
98919569Sjoerg				load_keymap(optarg, 0);
9902088Ssos				break;
99119569Sjoerg			case 'L':
99219569Sjoerg				load_keymap(optarg, 1);
99319569Sjoerg				break;
9942088Ssos			case 'f':
9958857Srgrimes				set_functionkey(optarg,
9962088Ssos					nextarg(argc, argv, &optind, 'f'));
9972088Ssos				break;
9982088Ssos			case 'F':
9992088Ssos				load_default_functionkeys();
10002088Ssos				break;
10016046Ssos			case 'h':
10026046Ssos				set_history(optarg);
10036046Ssos				break;
100442505Syokota			case 'i':
100542505Syokota				show_kbd_info();
100642505Syokota				break;
100742505Syokota			case 'K':
100842505Syokota				release_keyboard();
100942505Syokota				break;
101042505Syokota			case 'k':
101142505Syokota				set_keyboard(optarg);
101242505Syokota				break;
10132088Ssos			case 'r':
10142088Ssos				set_keyrates(optarg);
10152088Ssos				break;
10162088Ssos			case 'x':
10172088Ssos				hex = 1;
10182088Ssos				break;
10192088Ssos			default:
10202088Ssos				usage();
10212088Ssos		}
102229603Scharnier	if ((optind != argc) || (argc == 1))
10232088Ssos		usage();
10242088Ssos	exit(0);
10252088Ssos}
10262088Ssos
10272088Ssos
1028