kbdcontrol.c revision 266839
12088Ssos/*-
2228976Suqs * 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
1597748Sschweikh *    derived from this software without 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
29114601Sobrien#include <sys/cdefs.h>
30114601Sobrien__FBSDID("$FreeBSD: head/usr.sbin/kbdcontrol/kbdcontrol.c 266839 2014-05-29 14:39:25Z ray $");
3129603Scharnier
322088Ssos#include <ctype.h>
3329603Scharnier#include <err.h>
342088Ssos#include <stdio.h>
3529603Scharnier#include <stdlib.h>
363864Sswallace#include <string.h>
3729603Scharnier#include <unistd.h>
3842505Syokota#include <fcntl.h>
3966834Sphk#include <sys/kbio.h>
4066834Sphk#include <sys/consio.h>
41266839Sray#include <sys/sysctl.h>
422088Ssos#include "path.h"
432088Ssos#include "lex.h"
442088Ssos
4576643Simp/*
4690394Sru * HALT, PDWN, and PASTE aren't defined in 4.x, but we need them to bridge
4790394Sru * to 5.0-current so define them here as a stop gap transition measure.
4876643Simp */
4990394Sru#ifndef	HALT
5090394Sru#define	HALT		0xa1		/* halt machine */
5190394Sru#endif
5290394Sru#ifndef PDWN
5390394Sru#define	PDWN		0xa2		/* halt machine and power down */
5490394Sru#endif
5576643Simp#ifndef PASTE
5676643Simp#define PASTE		0xa3		/* paste from cut-paste buffer */
5776643Simp#endif
5876643Simp
59196500Sed#define	SPECIAL		0x80000000
60196500Sed
61228437Sedstatic const char ctrl_names[32][4] = {
628857Srgrimes	"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
632088Ssos	"bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ",
642088Ssos	"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
6538139Syokota	"can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us "
662088Ssos	};
672088Ssos
68228437Sedstatic const char acc_names[15][5] = {
6932316Syokota	"dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot",
7032316Syokota	"duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo",
7132316Syokota	"dcar",
7232316Syokota	};
7332316Syokota
74228437Sedstatic const char acc_names_u[15][5] = {
7532316Syokota	"DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT",
7632316Syokota	"DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO",
7732316Syokota	"DCAR",
7832316Syokota	};
7932316Syokota
80228437Sedstatic const char fkey_table[96][MAXFK] = {
815994Ssos/* 01-04 */	"\033[M", "\033[N", "\033[O", "\033[P",
825994Ssos/* 05-08 */	"\033[Q", "\033[R", "\033[S", "\033[T",
835994Ssos/* 09-12 */	"\033[U", "\033[V", "\033[W", "\033[X",
845994Ssos/* 13-16 */	"\033[Y", "\033[Z", "\033[a", "\033[b",
855994Ssos/* 17-20 */	"\033[c", "\033[d", "\033[e", "\033[f",
865994Ssos/* 21-24 */	"\033[g", "\033[h", "\033[i", "\033[j",
875994Ssos/* 25-28 */	"\033[k", "\033[l", "\033[m", "\033[n",
885994Ssos/* 29-32 */	"\033[o", "\033[p", "\033[q", "\033[r",
895994Ssos/* 33-36 */	"\033[s", "\033[t", "\033[u", "\033[v",
905994Ssos/* 37-40 */	"\033[w", "\033[x", "\033[y", "\033[z",
915994Ssos/* 41-44 */	"\033[@", "\033[[", "\033[\\","\033[]",
929202Srgrimes/* 45-48 */     "\033[^", "\033[_", "\033[`", "\033[{",
935994Ssos/* 49-52 */	"\033[H", "\033[A", "\033[I", "-"     ,
945994Ssos/* 53-56 */	"\033[D", "\033[E", "\033[C", "+"     ,
955994Ssos/* 57-60 */	"\033[F", "\033[B", "\033[G", "\033[L",
969202Srgrimes/* 61-64 */     "\177",   "\033[J", "\033[~", "\033[}",
975994Ssos/* 65-68 */	""      , ""      , ""      , ""      ,
985994Ssos/* 69-72 */	""      , ""      , ""      , ""      ,
995994Ssos/* 73-76 */	""      , ""      , ""      , ""      ,
1005994Ssos/* 77-80 */	""      , ""      , ""      , ""      ,
1015994Ssos/* 81-84 */	""      , ""      , ""      , ""      ,
1025994Ssos/* 85-88 */	""      , ""      , ""      , ""      ,
1035994Ssos/* 89-92 */	""      , ""      , ""      , ""      ,
1045994Ssos/* 93-96 */	""      , ""      , ""      , ""      ,
1052088Ssos	};
1062088Ssos
107228437Sedstatic const int delays[]  = {250, 500, 750, 1000};
108228437Sedstatic const int repeats[] = { 34,  38,  42,  46,  50,  55,  59,  63,
109228437Sed		      68,  76,  84,  92, 100, 110, 118, 126,
110228437Sed		     136, 152, 168, 184, 200, 220, 236, 252,
111228437Sed		     272, 304, 336, 368, 400, 440, 472, 504};
112228437Sedstatic const int ndelays = (sizeof(delays) / sizeof(int));
113228437Sedstatic const int nrepeats = (sizeof(repeats) / sizeof(int));
114228437Sedstatic int	hex = 0;
115228437Sedstatic int	token;
1162088Ssos
117228437Sedint		number;
118228437Sedchar		letter;
1192088Ssos
120228437Sedstatic void	dump_accent_definition(char *name, accentmap_t *accentmap);
121228437Sedstatic void	dump_entry(int value);
122228437Sedstatic void	dump_key_definition(char *name, keymap_t *keymap);
123228437Sedstatic int	get_accent_definition_line(accentmap_t *);
124228437Sedstatic int	get_entry(void);
125228437Sedstatic int	get_key_definition_line(keymap_t *);
126228437Sedstatic void	load_keymap(char *opt, int dumponly);
127228437Sedstatic void	load_default_functionkeys(void);
128228437Sedstatic char *	nextarg(int ac, char **av, int *indp, int oc);
129228437Sedstatic char *	mkfullname(const char *s1, const char *s2, const char *s3);
130228437Sedstatic void	print_accent_definition_line(FILE *fp, int accent,
131228437Sed		struct acc_t *key);
132228437Sedstatic void	print_entry(FILE *fp, int value);
133228437Sedstatic void	print_key_definition_line(FILE *fp, int scancode,
134228437Sed		struct keyent_t *key);
135228437Sedstatic void	print_keymap(void);
136228437Sedstatic void	release_keyboard(void);
137228437Sedstatic void	mux_keyboard(u_int op, char *kbd);
138228437Sedstatic void	set_bell_values(char *opt);
139228437Sedstatic void	set_functionkey(char *keynumstr, char *string);
140228437Sedstatic void	set_keyboard(char *device);
141228437Sedstatic void	set_keyrates(char *opt);
142228437Sedstatic void	show_kbd_info(void);
143228437Sedstatic void	usage(void) __dead2;
144228437Sed
145266839Sray/* Detect presence of vt(4). */
146266839Sraystatic int
147266839Srayis_vt4(void)
148266839Sray{
149266839Sray
150266839Sray	if (sysctlbyname("kern.vt.deadtimer", NULL, NULL, NULL, 0) == 0)
151266839Sray		return (1);
152266839Sray
153266839Sray	return (0);
154266839Sray}
155266839Sray
156228437Sedstatic char *
1572088Ssosnextarg(int ac, char **av, int *indp, int oc)
1582088Ssos{
1592088Ssos	if (*indp < ac)
1602088Ssos		return(av[(*indp)++]);
16129603Scharnier	warnx("option requires two arguments -- %c", oc);
1622088Ssos	usage();
1632088Ssos}
1642088Ssos
1652088Ssos
166228437Sedstatic char *
1672088Ssosmkfullname(const char *s1, const char *s2, const char *s3)
1682088Ssos{
1695536Ssos	static char	*buf = NULL;
1705536Ssos	static int	bufl = 0;
1715536Ssos	int		f;
1722088Ssos
1732088Ssos	f = strlen(s1) + strlen(s2) + strlen(s3) + 1;
17477394Ssobomax	if (f > bufl) {
1752088Ssos		if (buf)
1762088Ssos			buf = (char *)realloc(buf, f);
1772088Ssos		else
1782088Ssos			buf = (char *)malloc(f);
17977394Ssobomax	}
1802088Ssos	if (!buf) {
1812088Ssos		bufl = 0;
1822088Ssos		return(NULL);
1832088Ssos	}
1842088Ssos
1852088Ssos	bufl = f;
1862088Ssos	strcpy(buf, s1);
1872088Ssos	strcat(buf, s2);
1882088Ssos	strcat(buf, s3);
1892088Ssos	return(buf);
1902088Ssos}
1912088Ssos
1922088Ssos
193228437Sedstatic int
19499816Salfredget_entry(void)
1952088Ssos{
19632316Syokota	switch ((token = yylex())) {
1972088Ssos	case TNOP:
198196500Sed		return NOP | SPECIAL;
1992088Ssos	case TLSH:
200196500Sed		return LSH | SPECIAL;
2012088Ssos	case TRSH:
202196500Sed		return RSH | SPECIAL;
2032088Ssos	case TCLK:
204196500Sed		return CLK | SPECIAL;
2052088Ssos	case TNLK:
206196500Sed		return NLK | SPECIAL;
2072088Ssos	case TSLK:
208196500Sed		return SLK | SPECIAL;
2092088Ssos	case TBTAB:
210196500Sed		return BTAB | SPECIAL;
2112088Ssos	case TLALT:
212196500Sed		return LALT | SPECIAL;
2132088Ssos	case TLCTR:
214196500Sed		return LCTR | SPECIAL;
2152088Ssos	case TNEXT:
216196500Sed		return NEXT | SPECIAL;
21748105Syokota	case TPREV:
218196500Sed		return PREV | SPECIAL;
2192088Ssos	case TRCTR:
220196500Sed		return RCTR | SPECIAL;
2212088Ssos	case TRALT:
222196500Sed		return RALT | SPECIAL;
2232088Ssos	case TALK:
224196500Sed		return ALK | SPECIAL;
2252088Ssos	case TASH:
226196500Sed		return ASH | SPECIAL;
2272088Ssos	case TMETA:
228196500Sed		return META | SPECIAL;
2292088Ssos	case TRBT:
230196500Sed		return RBT | SPECIAL;
2312088Ssos	case TDBG:
232196500Sed		return DBG | SPECIAL;
2335994Ssos	case TSUSP:
234196500Sed		return SUSP | SPECIAL;
23538053Syokota	case TSPSC:
236196500Sed		return SPSC | SPECIAL;
23754380Syokota	case TPANIC:
238196500Sed		return PNC | SPECIAL;
23954380Syokota	case TLSHA:
240196500Sed		return LSHA | SPECIAL;
24154380Syokota	case TRSHA:
242196500Sed		return RSHA | SPECIAL;
24354380Syokota	case TLCTRA:
244196500Sed		return LCTRA | SPECIAL;
24554380Syokota	case TRCTRA:
246196500Sed		return RCTRA | SPECIAL;
24754380Syokota	case TLALTA:
248196500Sed		return LALTA | SPECIAL;
24954380Syokota	case TRALTA:
250196500Sed		return RALTA | SPECIAL;
25165759Sdwmalone	case THALT:
252196500Sed		return HALT | SPECIAL;
25365759Sdwmalone	case TPDWN:
254196500Sed		return PDWN | SPECIAL;
25574118Sache	case TPASTE:
256196500Sed		return PASTE | SPECIAL;
25732316Syokota	case TACC:
25832316Syokota		if (ACC(number) > L_ACC)
25932316Syokota			return -1;
260196500Sed		return ACC(number) | SPECIAL;
2612088Ssos	case TFUNC:
2622088Ssos		if (F(number) > L_FN)
2632088Ssos			return -1;
264196500Sed		return F(number) | SPECIAL;
2652088Ssos	case TSCRN:
2662088Ssos		if (S(number) > L_SCR)
2672088Ssos			return -1;
268196500Sed		return S(number) | SPECIAL;
2692088Ssos	case TLET:
2702088Ssos		return (unsigned char)letter;
2712088Ssos	case TNUM:
272197330Sed		if (number < 0x000000 || number > 0x10FFFF)
2732088Ssos			return -1;
2742088Ssos		return number;
2752088Ssos	default:
2762088Ssos		return -1;
2772088Ssos	}
2782088Ssos}
2792088Ssos
28077394Ssobomaxstatic int
28132316Syokotaget_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap)
2822088Ssos{
28332316Syokota	int c;
2842088Ssos
2852088Ssos	yyin = fd;
2862088Ssos
28732316Syokota	if (token < 0)
28832316Syokota		token = yylex();
28932316Syokota	switch (token) {
29032316Syokota	case TNUM:
29132316Syokota		c = get_key_definition_line(keymap);
29232316Syokota		if (c < 0)
29332316Syokota			errx(1, "invalid key definition");
29432316Syokota		if (c > keymap->n_keys)
29532316Syokota			keymap->n_keys = c;
29632316Syokota		break;
29732316Syokota	case TACC:
29832316Syokota		c = get_accent_definition_line(accentmap);
29932316Syokota		if (c < 0)
30032316Syokota			errx(1, "invalid accent key definition");
30132316Syokota		if (c > accentmap->n_accs)
30232316Syokota			accentmap->n_accs = c;
30332316Syokota		break;
30432316Syokota	case 0:
30532316Syokota		/* EOF */
3062088Ssos		return -1;
30732316Syokota	default:
30832316Syokota		errx(1, "illegal definition line");
30932316Syokota	}
31032316Syokota	return c;
31132316Syokota}
31232316Syokota
313228437Sedstatic int
31432316Syokotaget_key_definition_line(keymap_t *map)
31532316Syokota{
31632316Syokota	int i, def, scancode;
31732316Syokota
31832316Syokota	/* check scancode number */
3192088Ssos	if (number < 0 || number >= NUM_KEYS)
3202088Ssos		return -1;
3212088Ssos	scancode = number;
3222088Ssos
3232088Ssos	/* get key definitions */
3242088Ssos	map->key[scancode].spcl = 0;
3252088Ssos	for (i=0; i<NUM_STATES; i++) {
3262088Ssos		if ((def = get_entry()) == -1)
3272088Ssos			return -1;
328196500Sed		if (def & SPECIAL)
3292088Ssos			map->key[scancode].spcl |= (0x80 >> i);
330196500Sed		map->key[scancode].map[i] = def & ~SPECIAL;
3312088Ssos	}
3322088Ssos	/* get lock state key def */
33332316Syokota	if ((token = yylex()) != TFLAG)
3342088Ssos		return -1;
3352088Ssos	map->key[scancode].flgs = number;
33632316Syokota	token = yylex();
33732316Syokota	return (scancode + 1);
3382088Ssos}
3392088Ssos
340228437Sedstatic int
34132316Syokotaget_accent_definition_line(accentmap_t *map)
34232316Syokota{
34332316Syokota	int accent;
34432316Syokota	int c1, c2;
34532316Syokota	int i;
3462088Ssos
34732316Syokota	if (ACC(number) < F_ACC || ACC(number) > L_ACC)
34832316Syokota		/* number out of range */
34932316Syokota		return -1;
35032316Syokota	accent = number;
35132316Syokota	if (map->acc[accent].accchar != 0) {
35232316Syokota		/* this entry has already been defined before! */
35332316Syokota		errx(1, "duplicated accent key definition");
35432316Syokota	}
35532316Syokota
35632316Syokota	switch ((token = yylex())) {
35732316Syokota	case TLET:
35832316Syokota		map->acc[accent].accchar = letter;
35932316Syokota		break;
36032316Syokota	case TNUM:
36132316Syokota		map->acc[accent].accchar = number;
36232316Syokota		break;
36332316Syokota	default:
36432316Syokota		return -1;
36532316Syokota	}
36632316Syokota
36732316Syokota	for (i = 0; (token = yylex()) == '(';) {
36832316Syokota		switch ((token = yylex())) {
36932316Syokota		case TLET:
37032316Syokota			c1 = letter;
37132316Syokota			break;
37232316Syokota		case TNUM:
37332316Syokota			c1 = number;
37432316Syokota			break;
37532316Syokota		default:
37632316Syokota			return -1;
37732316Syokota		}
37832316Syokota		switch ((token = yylex())) {
37932316Syokota		case TLET:
38032316Syokota			c2 = letter;
38132316Syokota			break;
38232316Syokota		case TNUM:
38332316Syokota			c2 = number;
38432316Syokota			break;
38532316Syokota		default:
38632316Syokota			return -1;
38732316Syokota		}
38832316Syokota		if ((token = yylex()) != ')')
38932316Syokota			return -1;
39032316Syokota		if (i >= NUM_ACCENTCHARS) {
39132316Syokota			warnx("too many accented characters, ignored");
39232316Syokota			continue;
39332316Syokota		}
39432316Syokota		map->acc[accent].map[i][0] = c1;
39532316Syokota		map->acc[accent].map[i][1] = c2;
39632316Syokota		++i;
39732316Syokota	}
39832316Syokota	return (accent + 1);
39932316Syokota}
40032316Syokota
401228437Sedstatic void
4022088Ssosprint_entry(FILE *fp, int value)
4032088Ssos{
404196500Sed	int val = value & ~SPECIAL;
4052088Ssos
4062088Ssos	switch (value) {
407196500Sed	case NOP | SPECIAL:
4088857Srgrimes		fprintf(fp, " nop   ");
4092088Ssos		break;
410196500Sed	case LSH | SPECIAL:
4112088Ssos		fprintf(fp, " lshift");
4122088Ssos		break;
413196500Sed	case RSH | SPECIAL:
4142088Ssos		fprintf(fp, " rshift");
4152088Ssos		break;
416196500Sed	case CLK | SPECIAL:
4172088Ssos		fprintf(fp, " clock ");
4182088Ssos		break;
419196500Sed	case NLK | SPECIAL:
4202088Ssos		fprintf(fp, " nlock ");
4212088Ssos		break;
422196500Sed	case SLK | SPECIAL:
4232088Ssos		fprintf(fp, " slock ");
4242088Ssos		break;
425196500Sed	case BTAB | SPECIAL:
4262088Ssos		fprintf(fp, " btab  ");
4272088Ssos		break;
428196500Sed	case LALT | SPECIAL:
4292088Ssos		fprintf(fp, " lalt  ");
4302088Ssos		break;
431196500Sed	case LCTR | SPECIAL:
4322088Ssos		fprintf(fp, " lctrl ");
4332088Ssos		break;
434196500Sed	case NEXT | SPECIAL:
4352088Ssos		fprintf(fp, " nscr  ");
4362088Ssos		break;
437196500Sed	case PREV | SPECIAL:
43848105Syokota		fprintf(fp, " pscr  ");
43948105Syokota		break;
440196500Sed	case RCTR | SPECIAL:
4412088Ssos		fprintf(fp, " rctrl ");
4422088Ssos		break;
443196500Sed	case RALT | SPECIAL:
4442088Ssos		fprintf(fp, " ralt  ");
4452088Ssos		break;
446196500Sed	case ALK | SPECIAL:
4472088Ssos		fprintf(fp, " alock ");
4482088Ssos		break;
449196500Sed	case ASH | SPECIAL:
4502088Ssos		fprintf(fp, " ashift");
4512088Ssos		break;
452196500Sed	case META | SPECIAL:
4532088Ssos		fprintf(fp, " meta  ");
4542088Ssos		break;
455196500Sed	case RBT | SPECIAL:
4562088Ssos		fprintf(fp, " boot  ");
4572088Ssos		break;
458196500Sed	case DBG | SPECIAL:
4592088Ssos		fprintf(fp, " debug ");
4602088Ssos		break;
461196500Sed	case SUSP | SPECIAL:
46232316Syokota		fprintf(fp, " susp  ");
46332316Syokota		break;
464196500Sed	case SPSC | SPECIAL:
46538053Syokota		fprintf(fp, " saver ");
46638053Syokota		break;
467196500Sed	case PNC | SPECIAL:
46854380Syokota		fprintf(fp, " panic ");
46954380Syokota		break;
470196500Sed	case LSHA | SPECIAL:
47154380Syokota		fprintf(fp, " lshifta");
47254380Syokota		break;
473196500Sed	case RSHA | SPECIAL:
47454380Syokota		fprintf(fp, " rshifta");
47554380Syokota		break;
476196500Sed	case LCTRA | SPECIAL:
47754380Syokota		fprintf(fp, " lctrla");
47854380Syokota		break;
479196500Sed	case RCTRA | SPECIAL:
48054380Syokota		fprintf(fp, " rctrla");
48154380Syokota		break;
482196500Sed	case LALTA | SPECIAL:
48354380Syokota		fprintf(fp, " lalta ");
48454380Syokota		break;
485196500Sed	case RALTA | SPECIAL:
48654380Syokota		fprintf(fp, " ralta ");
48754380Syokota		break;
488196500Sed	case HALT | SPECIAL:
48965759Sdwmalone		fprintf(fp, " halt  ");
49065759Sdwmalone		break;
491196500Sed	case PDWN | SPECIAL:
49265759Sdwmalone		fprintf(fp, " pdwn  ");
49365759Sdwmalone		break;
494196500Sed	case PASTE | SPECIAL:
49574118Sache		fprintf(fp, " paste ");
49674118Sache		break;
4972088Ssos	default:
498196500Sed		if (value & SPECIAL) {
4998857Srgrimes		 	if (val >= F_FN && val <= L_FN)
5002088Ssos				fprintf(fp, " fkey%02d", val - F_FN + 1);
5018857Srgrimes		 	else if (val >= F_SCR && val <= L_SCR)
5022088Ssos				fprintf(fp, " scr%02d ", val - F_SCR + 1);
50332316Syokota		 	else if (val >= F_ACC && val <= L_ACC)
50432316Syokota				fprintf(fp, " %-6s", acc_names[val - F_ACC]);
5052088Ssos			else if (hex)
5068857Srgrimes				fprintf(fp, " 0x%02x  ", val);
5072088Ssos			else
50832316Syokota				fprintf(fp, " %3d   ", val);
5092088Ssos		}
5102088Ssos		else {
5112088Ssos			if (val < ' ')
5128857Srgrimes				fprintf(fp, " %s   ", ctrl_names[val]);
5132088Ssos			else if (val == 127)
5148857Srgrimes				fprintf(fp, " del   ");
5159202Srgrimes			else if (isascii(val) && isprint(val))
5168857Srgrimes				fprintf(fp, " '%c'   ", val);
5172088Ssos			else if (hex)
5188857Srgrimes				fprintf(fp, " 0x%02x  ", val);
5192088Ssos			else
5208857Srgrimes				fprintf(fp, " %3d   ", val);
5212088Ssos		}
5222088Ssos	}
5232088Ssos}
5242088Ssos
525228437Sedstatic void
52642505Syokotaprint_key_definition_line(FILE *fp, int scancode, struct keyent_t *key)
5272088Ssos{
52829603Scharnier	int i;
5292088Ssos
5302088Ssos	/* print scancode number */
5312088Ssos	if (hex)
5322088Ssos		fprintf(fp, " 0x%02x  ", scancode);
5332088Ssos	else
5342088Ssos		fprintf(fp, "  %03d  ", scancode);
5352088Ssos
5362088Ssos	/* print key definitions */
5372088Ssos	for (i=0; i<NUM_STATES; i++) {
5382088Ssos		if (key->spcl & (0x80 >> i))
539196500Sed			print_entry(fp, key->map[i] | SPECIAL);
5402088Ssos		else
5418857Srgrimes			print_entry(fp, key->map[i]);
5422088Ssos	}
5432088Ssos
5442088Ssos	/* print lock state key def */
5452088Ssos	switch (key->flgs) {
5462088Ssos	case 0:
5472088Ssos		fprintf(fp, "  O\n");
5482088Ssos		break;
5492088Ssos	case 1:
5502088Ssos		fprintf(fp, "  C\n");
5512088Ssos		break;
5522088Ssos	case 2:
5532088Ssos		fprintf(fp, "  N\n");
5542088Ssos		break;
5556046Ssos	case 3:
5566046Ssos		fprintf(fp, "  B\n");
5576046Ssos		break;
5588857Srgrimes	}
5592088Ssos}
5602088Ssos
561228437Sedstatic void
56232316Syokotaprint_accent_definition_line(FILE *fp, int accent, struct acc_t *key)
56332316Syokota{
56432316Syokota	int c;
56532316Syokota	int i;
5662088Ssos
56732316Syokota	if (key->accchar == 0)
56832316Syokota		return;
56932316Syokota
57032316Syokota	/* print accent number */
57132316Syokota	fprintf(fp, "  %-6s", acc_names[accent]);
57232316Syokota	if (isascii(key->accchar) && isprint(key->accchar))
57332316Syokota		fprintf(fp, "'%c'  ", key->accchar);
57432316Syokota	else if (hex)
57532316Syokota		fprintf(fp, "0x%02x ", key->accchar);
57632316Syokota	else
57732316Syokota		fprintf(fp, "%03d  ", key->accchar);
57832316Syokota
57932316Syokota	for (i = 0; i < NUM_ACCENTCHARS; ++i) {
58032316Syokota		c = key->map[i][0];
58132316Syokota		if (c == 0)
58232316Syokota			break;
58332316Syokota		if ((i > 0) && ((i % 4) == 0))
58432316Syokota			fprintf(fp, "\n             ");
58532316Syokota		if (isascii(c) && isprint(c))
58632316Syokota			fprintf(fp, "( '%c' ", c);
58732316Syokota		else if (hex)
58832316Syokota			fprintf(fp, "(0x%02x ", c);
58932316Syokota		else
59032316Syokota			fprintf(fp, "( %03d ", c);
59132316Syokota		c = key->map[i][1];
59232316Syokota		if (isascii(c) && isprint(c))
59332316Syokota			fprintf(fp, "'%c' ) ", c);
59432316Syokota		else if (hex)
59532316Syokota			fprintf(fp, "0x%02x) ", c);
59632316Syokota		else
59732316Syokota			fprintf(fp, "%03d ) ", c);
59832316Syokota	}
59932316Syokota	fprintf(fp, "\n");
60032316Syokota}
60132316Syokota
602228437Sedstatic void
60332316Syokotadump_entry(int value)
60432316Syokota{
605196500Sed	if (value & SPECIAL) {
606196500Sed		value &= ~SPECIAL;
60732316Syokota		switch (value) {
60832316Syokota		case NOP:
60932316Syokota			printf("  NOP, ");
61032316Syokota			break;
61132316Syokota		case LSH:
61232316Syokota			printf("  LSH, ");
61332316Syokota			break;
61432316Syokota		case RSH:
61532316Syokota			printf("  RSH, ");
61632316Syokota			break;
61732316Syokota		case CLK:
61832316Syokota			printf("  CLK, ");
61932316Syokota			break;
62032316Syokota		case NLK:
62132316Syokota			printf("  NLK, ");
62232316Syokota			break;
62332316Syokota		case SLK:
62432316Syokota			printf("  SLK, ");
62532316Syokota			break;
62632316Syokota		case BTAB:
62732316Syokota			printf(" BTAB, ");
62832316Syokota			break;
62932316Syokota		case LALT:
63032316Syokota			printf(" LALT, ");
63132316Syokota			break;
63232316Syokota		case LCTR:
63332316Syokota			printf(" LCTR, ");
63432316Syokota			break;
63532316Syokota		case NEXT:
63632316Syokota			printf(" NEXT, ");
63732316Syokota			break;
63848105Syokota		case PREV:
63948105Syokota			printf(" PREV, ");
64048105Syokota			break;
64132316Syokota		case RCTR:
64232316Syokota			printf(" RCTR, ");
64332316Syokota			break;
64432316Syokota		case RALT:
64532316Syokota			printf(" RALT, ");
64632316Syokota			break;
64732316Syokota		case ALK:
64832316Syokota			printf("  ALK, ");
64932316Syokota			break;
65032316Syokota		case ASH:
65132316Syokota			printf("  ASH, ");
65232316Syokota			break;
65332316Syokota		case META:
65432316Syokota			printf(" META, ");
65532316Syokota			break;
65632316Syokota		case RBT:
65732316Syokota			printf("  RBT, ");
65832316Syokota			break;
65932316Syokota		case DBG:
66032316Syokota			printf("  DBG, ");
66132316Syokota			break;
66232316Syokota		case SUSP:
66332316Syokota			printf(" SUSP, ");
66432316Syokota			break;
66538053Syokota		case SPSC:
66638053Syokota			printf(" SPSC, ");
66738053Syokota			break;
66854380Syokota		case PNC:
66954380Syokota			printf("  PNC, ");
67054380Syokota			break;
67154380Syokota		case LSHA:
67254380Syokota			printf(" LSHA, ");
67354380Syokota			break;
67454380Syokota		case RSHA:
67554380Syokota			printf(" RSHA, ");
67654380Syokota			break;
67754380Syokota		case LCTRA:
67854380Syokota			printf("LCTRA, ");
67954380Syokota			break;
68054380Syokota		case RCTRA:
68154380Syokota			printf("RCTRA, ");
68254380Syokota			break;
68354380Syokota		case LALTA:
68454380Syokota			printf("LALTA, ");
68554380Syokota			break;
68654380Syokota		case RALTA:
68754380Syokota			printf("RALTA, ");
68854380Syokota			break;
68965759Sdwmalone		case HALT:
69065759Sdwmalone			printf(" HALT, ");
69165759Sdwmalone			break;
69265759Sdwmalone		case PDWN:
69365759Sdwmalone			printf(" PDWN, ");
69465759Sdwmalone			break;
69574118Sache		case PASTE:
69674118Sache			printf("PASTE, ");
69774118Sache			break;
69832316Syokota		default:
69932316Syokota	 		if (value >= F_FN && value <= L_FN)
70032316Syokota				printf(" F(%2d),", value - F_FN + 1);
70132316Syokota	 		else if (value >= F_SCR && value <= L_SCR)
70232486Syokota				printf(" S(%2d),", value - F_SCR + 1);
70332316Syokota	 		else if (value >= F_ACC && value <= L_ACC)
70432316Syokota				printf(" %-4s, ", acc_names_u[value - F_ACC]);
70532316Syokota			else
70632316Syokota				printf(" 0x%02X, ", value);
70732316Syokota			break;
70832316Syokota		}
70932316Syokota	} else if (value == '\'') {
71032316Syokota		printf(" '\\'', ");
71132316Syokota	} else if (value == '\\') {
71232316Syokota		printf(" '\\\\', ");
71332316Syokota	} else if (isascii(value) && isprint(value)) {
71432316Syokota		printf("  '%c', ", value);
71532316Syokota	} else {
71632316Syokota		printf(" 0x%02X, ", value);
71732316Syokota	}
71832316Syokota}
71932316Syokota
720228437Sedstatic void
72132316Syokotadump_key_definition(char *name, keymap_t *keymap)
72232316Syokota{
72332316Syokota	int	i, j;
72432316Syokota
72532486Syokota	printf("static keymap_t keymap_%s = { 0x%02x, {\n",
72632316Syokota	       name, (unsigned)keymap->n_keys);
72732316Syokota	printf(
72832486Syokota"/*                                                         alt\n"
72932486Syokota" * scan                       cntrl          alt    alt   cntrl\n"
73032486Syokota" * code  base   shift  cntrl  shift   alt   shift  cntrl  shift    spcl flgs\n"
73132316Syokota" * ---------------------------------------------------------------------------\n"
73232316Syokota" */\n");
73332316Syokota	for (i = 0; i < keymap->n_keys; i++) {
73432486Syokota		printf("/*%02x*/{{", i);
73532316Syokota		for (j = 0; j < NUM_STATES; j++) {
73632316Syokota			if (keymap->key[i].spcl & (0x80 >> j))
737196500Sed				dump_entry(keymap->key[i].map[j] | SPECIAL);
73832316Syokota			else
73932316Syokota				dump_entry(keymap->key[i].map[j]);
74032316Syokota		}
74132486Syokota		printf("}, 0x%02X,0x%02X },\n",
74232316Syokota		       (unsigned)keymap->key[i].spcl,
74332316Syokota		       (unsigned)keymap->key[i].flgs);
74432316Syokota	}
74532486Syokota	printf("} };\n\n");
74632316Syokota}
74732316Syokota
748228437Sedstatic void
74932316Syokotadump_accent_definition(char *name, accentmap_t *accentmap)
75032316Syokota{
75132316Syokota	int i, j;
75232316Syokota	int c;
75332316Syokota
75432486Syokota	printf("static accentmap_t accentmap_%s = { %d",
75532316Syokota		name, accentmap->n_accs);
75632486Syokota	if (accentmap->n_accs <= 0) {
75732486Syokota		printf(" };\n\n");
75832486Syokota		return;
75932486Syokota	}
76032486Syokota	printf(", {\n");
76132316Syokota	for (i = 0; i < NUM_DEADKEYS; i++) {
76232316Syokota		printf("    /* %s=%d */\n    {", acc_names[i], i);
76332316Syokota		c = accentmap->acc[i].accchar;
76432316Syokota		if (c == '\'')
76532316Syokota			printf(" '\\'', {");
76632316Syokota		else if (c == '\\')
76732316Syokota			printf(" '\\\\', {");
76832316Syokota		else if (isascii(c) && isprint(c))
76932316Syokota			printf("  '%c', {", c);
77032316Syokota		else if (c == 0) {
77132316Syokota			printf(" 0x00 }, \n");
77232316Syokota			continue;
77332316Syokota		} else
77432316Syokota			printf(" 0x%02x, {", c);
77532316Syokota		for (j = 0; j < NUM_ACCENTCHARS; j++) {
77632316Syokota			c = accentmap->acc[i].map[j][0];
77732316Syokota			if (c == 0)
77832316Syokota				break;
77932316Syokota			if ((j > 0) && ((j % 4) == 0))
78032316Syokota				printf("\n\t     ");
78132316Syokota			if (isascii(c) && isprint(c))
78232316Syokota				printf(" {  '%c',", c);
78332316Syokota			else
78432316Syokota				printf(" { 0x%02x,", c);
78532316Syokota			printf("0x%02x },", accentmap->acc[i].map[j][1]);
78632316Syokota		}
78732316Syokota		printf(" }, },\n");
78832316Syokota	}
78932486Syokota	printf("} };\n\n");
79032316Syokota}
79132316Syokota
792228437Sedstatic void
79319569Sjoergload_keymap(char *opt, int dumponly)
7942088Ssos{
79532316Syokota	keymap_t keymap;
79632316Syokota	accentmap_t accentmap;
7972088Ssos	FILE	*fd;
79876502Ssobomax	int	i, j;
79919569Sjoerg	char	*name, *cp;
800266839Sray	char	blank[] = "", keymap_path[] = KEYMAP_PATH;
801266839Sray	char	vt_keymap_path[] = VT_KEYMAP_PATH, dotkbd[] = ".kbd";
80299816Salfred	char	*prefix[]  = {blank, blank, keymap_path, NULL};
80399816Salfred	char	*postfix[] = {blank, dotkbd, NULL};
8042088Ssos
805266839Sray	if (is_vt4())
806266839Sray		prefix[2] = vt_keymap_path;
80776569Ssobomax	cp = getenv("KEYMAP_PATH");
80876569Ssobomax	if (cp != NULL)
80976569Ssobomax		asprintf(&(prefix[0]), "%s/", cp);
81076502Ssobomax
81176643Simp	fd = NULL;
81276643Simp	for (i=0; prefix[i] && fd == NULL; i++) {
81376643Simp		for (j=0; postfix[j] && fd == NULL; j++) {
81476502Ssobomax			name = mkfullname(prefix[i], opt, postfix[j]);
81576643Simp			fd = fopen(name, "r");
81676502Ssobomax		}
81776643Simp	}
8182088Ssos	if (fd == NULL) {
81979677Sobrien		warn("keymap file \"%s\" not found", opt);
8202088Ssos		return;
8212088Ssos	}
82232316Syokota	memset(&keymap, 0, sizeof(keymap));
82332316Syokota	memset(&accentmap, 0, sizeof(accentmap));
82432316Syokota	token = -1;
8252088Ssos	while (1) {
82632316Syokota		if (get_definition_line(fd, &keymap, &accentmap) < 0)
8272088Ssos			break;
8282088Ssos    	}
82919569Sjoerg	if (dumponly) {
83019569Sjoerg		/* fix up the filename to make it a valid C identifier */
83119569Sjoerg		for (cp = opt; *cp; cp++)
83219569Sjoerg			if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_';
83332316Syokota		printf("/*\n"
83432316Syokota		       " * Automatically generated from %s.\n"
83532316Syokota	               " * DO NOT EDIT!\n"
83632316Syokota		       " */\n", name);
83732316Syokota		dump_key_definition(opt, &keymap);
83832316Syokota		dump_accent_definition(opt, &accentmap);
83919569Sjoerg		return;
84019569Sjoerg	}
84132316Syokota	if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) {
84229603Scharnier		warn("setting keymap");
8432088Ssos		fclose(fd);
8442088Ssos		return;
8452088Ssos	}
84632316Syokota	if ((accentmap.n_accs > 0)
84732316Syokota		&& (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) {
84832316Syokota		warn("setting accentmap");
84932316Syokota		fclose(fd);
85032316Syokota		return;
85132316Syokota	}
8522088Ssos}
8532088Ssos
854228437Sedstatic void
85599816Salfredprint_keymap(void)
8562088Ssos{
85732316Syokota	keymap_t keymap;
85832316Syokota	accentmap_t accentmap;
8592088Ssos	int i;
8602088Ssos
86132316Syokota	if (ioctl(0, GIO_KEYMAP, &keymap) < 0)
86229603Scharnier		err(1, "getting keymap");
86332316Syokota	if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0)
86432316Syokota		memset(&accentmap, 0, sizeof(accentmap));
8652088Ssos    	printf(
8662088Ssos"#                                                         alt\n"
8672088Ssos"# scan                       cntrl          alt    alt   cntrl lock\n"
8682088Ssos"# code  base   shift  cntrl  shift  alt    shift  cntrl  shift state\n"
8692088Ssos"# ------------------------------------------------------------------\n"
8702088Ssos    	);
87132316Syokota	for (i=0; i<keymap.n_keys; i++)
87232316Syokota		print_key_definition_line(stdout, i, &keymap.key[i]);
87332316Syokota
87432316Syokota	printf("\n");
87532316Syokota	for (i = 0; i < NUM_DEADKEYS; i++)
87632316Syokota		print_accent_definition_line(stdout, i, &accentmap.acc[i]);
87732316Syokota
8782088Ssos}
8792088Ssos
880228437Sedstatic void
88199816Salfredload_default_functionkeys(void)
8822088Ssos{
8832088Ssos	fkeyarg_t fkey;
8842088Ssos	int i;
8852088Ssos
8862088Ssos	for (i=0; i<NUM_FKEYS; i++) {
8872088Ssos		fkey.keynum = i;
8882088Ssos		strcpy(fkey.keydef, fkey_table[i]);
8892088Ssos		fkey.flen = strlen(fkey_table[i]);
8902088Ssos		if (ioctl(0, SETFKEY, &fkey) < 0)
89129603Scharnier			warn("setting function key");
8922088Ssos	}
8932088Ssos}
8942088Ssos
895228437Sedstatic void
8962088Ssosset_functionkey(char *keynumstr, char *string)
8972088Ssos{
8982088Ssos	fkeyarg_t fkey;
8992088Ssos
9002088Ssos	if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) {
9012088Ssos		load_default_functionkeys();
9022088Ssos		return;
9032088Ssos	}
9042088Ssos	fkey.keynum = atoi(keynumstr);
9052088Ssos	if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) {
90629603Scharnier		warnx("function key number must be between 1 and %d",
9072088Ssos			NUM_FKEYS);
9082088Ssos		return;
9092088Ssos	}
9102088Ssos	if ((fkey.flen = strlen(string)) > MAXFK) {
91129603Scharnier		warnx("function key string too long (%d > %d)",
9122088Ssos			fkey.flen, MAXFK);
9132088Ssos		return;
9142088Ssos	}
915133353Sjmg	strncpy(fkey.keydef, string, MAXFK);
9162088Ssos	fkey.keynum -= 1;
9172088Ssos	if (ioctl(0, SETFKEY, &fkey) < 0)
91829603Scharnier		warn("setting function key");
9192088Ssos}
9202088Ssos
921228437Sedstatic void
9222088Ssosset_bell_values(char *opt)
9232088Ssos{
9245536Ssos	int bell, duration, pitch;
9252088Ssos
92638044Syokota	bell = 0;
92738044Syokota	if (!strncmp(opt, "quiet.", 6)) {
928164333Sru		bell = CONS_QUIET_BELL;
92938044Syokota		opt += 6;
93038044Syokota	}
9318857Srgrimes	if (!strcmp(opt, "visual"))
932164333Sru		bell |= CONS_VISUAL_BELL;
9335536Ssos	else if (!strcmp(opt, "normal"))
93438044Syokota		duration = 5, pitch = 800;
93548982Syokota	else if (!strcmp(opt, "off"))
93648982Syokota		duration = 0, pitch = 0;
9372088Ssos	else {
9382088Ssos		char		*v1;
9398857Srgrimes
9405536Ssos		bell = 0;
9412088Ssos		duration = strtol(opt, &v1, 0);
9422088Ssos		if ((duration < 0) || (*v1 != '.'))
9432088Ssos			goto badopt;
9442088Ssos		opt = ++v1;
9452088Ssos		pitch = strtol(opt, &v1, 0);
9462088Ssos		if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) {
9472088Ssosbadopt:
94877394Ssobomax			warnx("argument to -b must be duration.pitch or [quiet.]visual|normal|off");
9492088Ssos			return;
9502088Ssos		}
95138044Syokota		if (pitch != 0)
95238044Syokota			pitch = 1193182 / pitch;	/* in Hz */
95338044Syokota		duration /= 10;	/* in 10 m sec */
9542088Ssos	}
9552088Ssos
9565536Ssos	ioctl(0, CONS_BELLTYPE, &bell);
957164333Sru	if (!(bell & CONS_VISUAL_BELL))
9585536Ssos		fprintf(stderr, "[=%d;%dB", pitch, duration);
9592088Ssos}
9602088Ssos
961228437Sedstatic void
9622088Ssosset_keyrates(char *opt)
9632088Ssos{
96444628Syokota	int arg[2];
96539047Syokota	int repeat;
96639047Syokota	int delay;
96746761Syokota	int r, d;
9682088Ssos
96946761Syokota	if (!strcmp(opt, "slow")) {
97044628Syokota		delay = 1000, repeat = 500;
97146761Syokota		d = 3, r = 31;
97246761Syokota	} else if (!strcmp(opt, "normal")) {
97344628Syokota		delay = 500, repeat = 125;
97446761Syokota		d = 1, r = 15;
97546761Syokota	} else if (!strcmp(opt, "fast")) {
97639047Syokota		delay = repeat = 0;
97746761Syokota		d = r = 0;
97846761Syokota	} else {
9792088Ssos		int		n;
9802088Ssos		char		*v1;
9812088Ssos
9822088Ssos		delay = strtol(opt, &v1, 0);
9832088Ssos		if ((delay < 0) || (*v1 != '.'))
9842088Ssos			goto badopt;
9852088Ssos		opt = ++v1;
9862088Ssos		repeat = strtol(opt, &v1, 0);
9872088Ssos		if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) {
9882088Ssosbadopt:
98977394Ssobomax			warnx("argument to -r must be delay.repeat or slow|normal|fast");
9902088Ssos			return;
9912088Ssos		}
99246761Syokota		for (n = 0; n < ndelays - 1; n++)
99346761Syokota			if (delay <= delays[n])
99446761Syokota				break;
99546761Syokota		d = n;
99646761Syokota		for (n = 0; n < nrepeats - 1; n++)
99746761Syokota			if (repeat <= repeats[n])
99846761Syokota				break;
99946761Syokota		r = n;
10002088Ssos	}
10012088Ssos
100244628Syokota	arg[0] = delay;
100344628Syokota	arg[1] = repeat;
100446761Syokota	if (ioctl(0, KDSETREPEAT, arg)) {
100546761Syokota		if (ioctl(0, KDSETRAD, (d << 5) | r))
100646761Syokota			warn("setting keyboard rate");
100746761Syokota	}
10082088Ssos}
10092088Ssos
101099816Salfredstatic const char *
101199816Salfredget_kbd_type_name(int type)
101242505Syokota{
101342505Syokota	static struct {
101442505Syokota		int type;
101599816Salfred		const char *name;
101642505Syokota	} name_table[] = {
101742505Syokota		{ KB_84,	"AT 84" },
101842505Syokota		{ KB_101,	"AT 101/102" },
101942505Syokota		{ KB_OTHER,	"generic" },
102042505Syokota	};
102199816Salfred	unsigned int i;
10226046Ssos
102342505Syokota	for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) {
102442505Syokota		if (type == name_table[i].type)
102542505Syokota			return name_table[i].name;
102642505Syokota	}
102742505Syokota	return "unknown";
102842505Syokota}
102942505Syokota
1030228437Sedstatic void
103142505Syokotashow_kbd_info(void)
103242505Syokota{
103342505Syokota	keyboard_info_t info;
103442505Syokota
103542505Syokota	if (ioctl(0, KDGKBINFO, &info) == -1) {
103642505Syokota		warn("unable to obtain keyboard information");
103742505Syokota		return;
103842505Syokota	}
103942505Syokota	printf("kbd%d:\n", info.kb_index);
104042505Syokota	printf("    %.*s%d, type:%s (%d)\n",
104177394Ssobomax		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
104242505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
104342505Syokota}
104442505Syokota
1045228437Sedstatic void
104642505Syokotaset_keyboard(char *device)
104742505Syokota{
104842505Syokota	keyboard_info_t info;
104942505Syokota	int fd;
105042505Syokota
105142505Syokota	fd = open(device, O_RDONLY);
105242505Syokota	if (fd < 0) {
105342505Syokota		warn("cannot open %s", device);
105442505Syokota		return;
105542505Syokota	}
105642505Syokota	if (ioctl(fd, KDGKBINFO, &info) == -1) {
105742505Syokota		warn("unable to obtain keyboard information");
105842505Syokota		close(fd);
105942505Syokota		return;
106042505Syokota	}
106142505Syokota	/*
106242505Syokota	 * The keyboard device driver won't release the keyboard by
106342505Syokota	 * the following ioctl, but it automatically will, when the device
106442505Syokota	 * is closed.  So, we don't check error here.
106542505Syokota	 */
106642505Syokota	ioctl(fd, CONS_RELKBD, 0);
106742505Syokota	close(fd);
106842505Syokota#if 1
106942505Syokota	printf("kbd%d\n", info.kb_index);
107042505Syokota	printf("    %.*s%d, type:%s (%d)\n",
107177394Ssobomax		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
107242505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
107342505Syokota#endif
107442505Syokota
107542505Syokota	if (ioctl(0, CONS_SETKBD, info.kb_index) == -1)
107642505Syokota		warn("unable to set keyboard");
107742505Syokota}
107842505Syokota
1079228437Sedstatic void
108042505Syokotarelease_keyboard(void)
108142505Syokota{
108242505Syokota	keyboard_info_t info;
108342505Syokota
108442505Syokota	/*
108542505Syokota	 * If stdin is not associated with a keyboard, the following ioctl
108642505Syokota	 * will fail.
108742505Syokota	 */
108842505Syokota	if (ioctl(0, KDGKBINFO, &info) == -1) {
108942505Syokota		warn("unable to obtain keyboard information");
109042505Syokota		return;
109142505Syokota	}
109242505Syokota#if 1
109342505Syokota	printf("kbd%d\n", info.kb_index);
109442505Syokota	printf("    %.*s%d, type:%s (%d)\n",
109577394Ssobomax		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
109642505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
109742505Syokota#endif
109842505Syokota	if (ioctl(0, CONS_RELKBD, 0) == -1)
109942505Syokota		warn("unable to release the keyboard");
110042505Syokota}
110142505Syokota
1102228437Sedstatic void
1103162327Semaxmux_keyboard(u_int op, char *kbd)
1104148017Semax{
1105148017Semax	keyboard_info_t	info;
1106148017Semax	char		*unit, *ep;
110742505Syokota
1108148017Semax	/*
1109148017Semax	 * If stdin is not associated with a keyboard, the following ioctl
1110148017Semax	 * will fail.
1111148017Semax	 */
1112148017Semax	if (ioctl(0, KDGKBINFO, &info) == -1) {
1113148017Semax		warn("unable to obtain keyboard information");
1114148017Semax		return;
1115148017Semax	}
1116148017Semax#if 1
1117148017Semax	printf("kbd%d\n", info.kb_index);
1118148017Semax	printf("    %.*s%d, type:%s (%d)\n",
1119148017Semax		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
1120148017Semax		get_kbd_type_name(info.kb_type), info.kb_type);
1121148017Semax#endif
1122148017Semax	/*
1123148017Semax	 * split kbd into name and unit. find the right most part of the
1124148017Semax	 * kbd string that consist of only digits.
1125148017Semax	 */
1126148017Semax
1127148017Semax	memset(&info, 0, sizeof(info));
1128148017Semax
1129148017Semax	info.kb_unit = -1;
1130148017Semax	ep = kbd - 1;
1131148017Semax
1132148017Semax	do {
1133148017Semax		unit = strpbrk(ep + 1, "0123456789");
1134148017Semax		if (unit != NULL) {
1135148017Semax			info.kb_unit = strtol(unit, &ep, 10);
1136148017Semax			if (*ep != '\0')
1137148017Semax				info.kb_unit = -1;
1138148017Semax		}
1139148017Semax	} while (unit != NULL && info.kb_unit == -1);
1140148017Semax
1141148017Semax	if (info.kb_unit == -1) {
1142148017Semax		warnx("unable to find keyboard driver unit in '%s'", kbd);
1143148017Semax		return;
1144148017Semax	}
1145148017Semax
1146148017Semax	if (unit == kbd) {
1147148017Semax		warnx("unable to find keyboard driver name in '%s'", kbd);
1148148017Semax		return;
1149148017Semax	}
1150148017Semax	if (unit - kbd >= (int) sizeof(info.kb_name)) {
1151148017Semax		warnx("keyboard name '%s' is too long", kbd);
1152148017Semax		return;
1153148017Semax	}
1154148017Semax
1155148017Semax	strncpy(info.kb_name, kbd, unit - kbd);
1156148017Semax
1157148017Semax	/*
1158148017Semax	 * If stdin is not associated with a kbdmux(4) keyboard, the following
1159148017Semax	 * ioctl will fail.
1160148017Semax	 */
1161148017Semax
1162148017Semax	if (ioctl(0, op, &info) == -1)
1163148017Semax		warn("unable to (un)mux the keyboard");
1164148017Semax}
1165148017Semax
1166228437Sedstatic void
1167201387Sedusage(void)
11682088Ssos{
116929603Scharnier	fprintf(stderr, "%s\n%s\n%s\n",
1170148017Semax"usage: kbdcontrol [-dFKix] [-A name] [-a name] [-b duration.pitch | [quiet.]belltype]",
117129603Scharnier"                  [-r delay.repeat | speed] [-l mapfile] [-f # string]",
117277329Sdes"                  [-k device] [-L mapfile]");
117329603Scharnier	exit(1);
11742088Ssos}
11752088Ssos
11762088Ssos
117751287Speterint
11782088Ssosmain(int argc, char **argv)
11792088Ssos{
11802088Ssos	int		opt;
11812088Ssos
1182148017Semax	while((opt = getopt(argc, argv, "A:a:b:df:iKk:Fl:L:r:x")) != -1)
11832088Ssos		switch(opt) {
1184148017Semax		case 'A':
1185148017Semax		case 'a':
1186148017Semax			mux_keyboard((opt == 'A')? KBRELKBD : KBADDKBD, optarg);
1187148017Semax			break;
118877329Sdes		case 'b':
118977329Sdes			set_bell_values(optarg);
119077329Sdes			break;
119177329Sdes		case 'd':
119277329Sdes			print_keymap();
119377329Sdes			break;
119477329Sdes		case 'l':
119577329Sdes			load_keymap(optarg, 0);
119677329Sdes			break;
119777329Sdes		case 'L':
119877329Sdes			load_keymap(optarg, 1);
119977329Sdes			break;
120077329Sdes		case 'f':
120177329Sdes			set_functionkey(optarg,
120277329Sdes			    nextarg(argc, argv, &optind, 'f'));
120377329Sdes			break;
120477329Sdes		case 'F':
120577329Sdes			load_default_functionkeys();
120677329Sdes			break;
120777329Sdes		case 'i':
120877329Sdes			show_kbd_info();
120977329Sdes			break;
121077329Sdes		case 'K':
121177329Sdes			release_keyboard();
121277329Sdes			break;
121377329Sdes		case 'k':
121477329Sdes			set_keyboard(optarg);
121577329Sdes			break;
121677329Sdes		case 'r':
121777329Sdes			set_keyrates(optarg);
121877329Sdes			break;
121977329Sdes		case 'x':
122077329Sdes			hex = 1;
122177329Sdes			break;
122277329Sdes		default:
122377329Sdes			usage();
12242088Ssos		}
122529603Scharnier	if ((optind != argc) || (argc == 1))
12262088Ssos		usage();
12272088Ssos	exit(0);
12282088Ssos}
1229