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$");
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>
412088Ssos#include "path.h"
422088Ssos#include "lex.h"
432088Ssos
4476643Simp/*
4590394Sru * HALT, PDWN, and PASTE aren't defined in 4.x, but we need them to bridge
4690394Sru * to 5.0-current so define them here as a stop gap transition measure.
4776643Simp */
4890394Sru#ifndef	HALT
4990394Sru#define	HALT		0xa1		/* halt machine */
5090394Sru#endif
5190394Sru#ifndef PDWN
5290394Sru#define	PDWN		0xa2		/* halt machine and power down */
5390394Sru#endif
5476643Simp#ifndef PASTE
5576643Simp#define PASTE		0xa3		/* paste from cut-paste buffer */
5676643Simp#endif
5776643Simp
58196500Sed#define	SPECIAL		0x80000000
59196500Sed
60228437Sedstatic const char ctrl_names[32][4] = {
618857Srgrimes	"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
622088Ssos	"bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ",
632088Ssos	"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
6438139Syokota	"can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us "
652088Ssos	};
662088Ssos
67228437Sedstatic const char acc_names[15][5] = {
6832316Syokota	"dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot",
6932316Syokota	"duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo",
7032316Syokota	"dcar",
7132316Syokota	};
7232316Syokota
73228437Sedstatic const char acc_names_u[15][5] = {
7432316Syokota	"DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT",
7532316Syokota	"DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO",
7632316Syokota	"DCAR",
7732316Syokota	};
7832316Syokota
79228437Sedstatic const char fkey_table[96][MAXFK] = {
805994Ssos/* 01-04 */	"\033[M", "\033[N", "\033[O", "\033[P",
815994Ssos/* 05-08 */	"\033[Q", "\033[R", "\033[S", "\033[T",
825994Ssos/* 09-12 */	"\033[U", "\033[V", "\033[W", "\033[X",
835994Ssos/* 13-16 */	"\033[Y", "\033[Z", "\033[a", "\033[b",
845994Ssos/* 17-20 */	"\033[c", "\033[d", "\033[e", "\033[f",
855994Ssos/* 21-24 */	"\033[g", "\033[h", "\033[i", "\033[j",
865994Ssos/* 25-28 */	"\033[k", "\033[l", "\033[m", "\033[n",
875994Ssos/* 29-32 */	"\033[o", "\033[p", "\033[q", "\033[r",
885994Ssos/* 33-36 */	"\033[s", "\033[t", "\033[u", "\033[v",
895994Ssos/* 37-40 */	"\033[w", "\033[x", "\033[y", "\033[z",
905994Ssos/* 41-44 */	"\033[@", "\033[[", "\033[\\","\033[]",
919202Srgrimes/* 45-48 */     "\033[^", "\033[_", "\033[`", "\033[{",
925994Ssos/* 49-52 */	"\033[H", "\033[A", "\033[I", "-"     ,
935994Ssos/* 53-56 */	"\033[D", "\033[E", "\033[C", "+"     ,
945994Ssos/* 57-60 */	"\033[F", "\033[B", "\033[G", "\033[L",
959202Srgrimes/* 61-64 */     "\177",   "\033[J", "\033[~", "\033[}",
965994Ssos/* 65-68 */	""      , ""      , ""      , ""      ,
975994Ssos/* 69-72 */	""      , ""      , ""      , ""      ,
985994Ssos/* 73-76 */	""      , ""      , ""      , ""      ,
995994Ssos/* 77-80 */	""      , ""      , ""      , ""      ,
1005994Ssos/* 81-84 */	""      , ""      , ""      , ""      ,
1015994Ssos/* 85-88 */	""      , ""      , ""      , ""      ,
1025994Ssos/* 89-92 */	""      , ""      , ""      , ""      ,
1035994Ssos/* 93-96 */	""      , ""      , ""      , ""      ,
1042088Ssos	};
1052088Ssos
106228437Sedstatic const int delays[]  = {250, 500, 750, 1000};
107228437Sedstatic const int repeats[] = { 34,  38,  42,  46,  50,  55,  59,  63,
108228437Sed		      68,  76,  84,  92, 100, 110, 118, 126,
109228437Sed		     136, 152, 168, 184, 200, 220, 236, 252,
110228437Sed		     272, 304, 336, 368, 400, 440, 472, 504};
111228437Sedstatic const int ndelays = (sizeof(delays) / sizeof(int));
112228437Sedstatic const int nrepeats = (sizeof(repeats) / sizeof(int));
113228437Sedstatic int	hex = 0;
114228437Sedstatic int	token;
1152088Ssos
116228437Sedint		number;
117228437Sedchar		letter;
1182088Ssos
119228437Sedstatic void	dump_accent_definition(char *name, accentmap_t *accentmap);
120228437Sedstatic void	dump_entry(int value);
121228437Sedstatic void	dump_key_definition(char *name, keymap_t *keymap);
122228437Sedstatic int	get_accent_definition_line(accentmap_t *);
123228437Sedstatic int	get_entry(void);
124228437Sedstatic int	get_key_definition_line(keymap_t *);
125228437Sedstatic void	load_keymap(char *opt, int dumponly);
126228437Sedstatic void	load_default_functionkeys(void);
127228437Sedstatic char *	nextarg(int ac, char **av, int *indp, int oc);
128228437Sedstatic char *	mkfullname(const char *s1, const char *s2, const char *s3);
129228437Sedstatic void	print_accent_definition_line(FILE *fp, int accent,
130228437Sed		struct acc_t *key);
131228437Sedstatic void	print_entry(FILE *fp, int value);
132228437Sedstatic void	print_key_definition_line(FILE *fp, int scancode,
133228437Sed		struct keyent_t *key);
134228437Sedstatic void	print_keymap(void);
135228437Sedstatic void	release_keyboard(void);
136228437Sedstatic void	mux_keyboard(u_int op, char *kbd);
137228437Sedstatic void	set_bell_values(char *opt);
138228437Sedstatic void	set_functionkey(char *keynumstr, char *string);
139228437Sedstatic void	set_keyboard(char *device);
140228437Sedstatic void	set_keyrates(char *opt);
141228437Sedstatic void	show_kbd_info(void);
142228437Sedstatic void	usage(void) __dead2;
143228437Sed
144228437Sedstatic char *
1452088Ssosnextarg(int ac, char **av, int *indp, int oc)
1462088Ssos{
1472088Ssos	if (*indp < ac)
1482088Ssos		return(av[(*indp)++]);
14929603Scharnier	warnx("option requires two arguments -- %c", oc);
1502088Ssos	usage();
1512088Ssos}
1522088Ssos
1532088Ssos
154228437Sedstatic char *
1552088Ssosmkfullname(const char *s1, const char *s2, const char *s3)
1562088Ssos{
1575536Ssos	static char	*buf = NULL;
1585536Ssos	static int	bufl = 0;
1595536Ssos	int		f;
1602088Ssos
1612088Ssos	f = strlen(s1) + strlen(s2) + strlen(s3) + 1;
16277394Ssobomax	if (f > bufl) {
1632088Ssos		if (buf)
1642088Ssos			buf = (char *)realloc(buf, f);
1652088Ssos		else
1662088Ssos			buf = (char *)malloc(f);
16777394Ssobomax	}
1682088Ssos	if (!buf) {
1692088Ssos		bufl = 0;
1702088Ssos		return(NULL);
1712088Ssos	}
1722088Ssos
1732088Ssos	bufl = f;
1742088Ssos	strcpy(buf, s1);
1752088Ssos	strcat(buf, s2);
1762088Ssos	strcat(buf, s3);
1772088Ssos	return(buf);
1782088Ssos}
1792088Ssos
1802088Ssos
181228437Sedstatic int
18299816Salfredget_entry(void)
1832088Ssos{
18432316Syokota	switch ((token = yylex())) {
1852088Ssos	case TNOP:
186196500Sed		return NOP | SPECIAL;
1872088Ssos	case TLSH:
188196500Sed		return LSH | SPECIAL;
1892088Ssos	case TRSH:
190196500Sed		return RSH | SPECIAL;
1912088Ssos	case TCLK:
192196500Sed		return CLK | SPECIAL;
1932088Ssos	case TNLK:
194196500Sed		return NLK | SPECIAL;
1952088Ssos	case TSLK:
196196500Sed		return SLK | SPECIAL;
1972088Ssos	case TBTAB:
198196500Sed		return BTAB | SPECIAL;
1992088Ssos	case TLALT:
200196500Sed		return LALT | SPECIAL;
2012088Ssos	case TLCTR:
202196500Sed		return LCTR | SPECIAL;
2032088Ssos	case TNEXT:
204196500Sed		return NEXT | SPECIAL;
20548105Syokota	case TPREV:
206196500Sed		return PREV | SPECIAL;
2072088Ssos	case TRCTR:
208196500Sed		return RCTR | SPECIAL;
2092088Ssos	case TRALT:
210196500Sed		return RALT | SPECIAL;
2112088Ssos	case TALK:
212196500Sed		return ALK | SPECIAL;
2132088Ssos	case TASH:
214196500Sed		return ASH | SPECIAL;
2152088Ssos	case TMETA:
216196500Sed		return META | SPECIAL;
2172088Ssos	case TRBT:
218196500Sed		return RBT | SPECIAL;
2192088Ssos	case TDBG:
220196500Sed		return DBG | SPECIAL;
2215994Ssos	case TSUSP:
222196500Sed		return SUSP | SPECIAL;
22338053Syokota	case TSPSC:
224196500Sed		return SPSC | SPECIAL;
22554380Syokota	case TPANIC:
226196500Sed		return PNC | SPECIAL;
22754380Syokota	case TLSHA:
228196500Sed		return LSHA | SPECIAL;
22954380Syokota	case TRSHA:
230196500Sed		return RSHA | SPECIAL;
23154380Syokota	case TLCTRA:
232196500Sed		return LCTRA | SPECIAL;
23354380Syokota	case TRCTRA:
234196500Sed		return RCTRA | SPECIAL;
23554380Syokota	case TLALTA:
236196500Sed		return LALTA | SPECIAL;
23754380Syokota	case TRALTA:
238196500Sed		return RALTA | SPECIAL;
23965759Sdwmalone	case THALT:
240196500Sed		return HALT | SPECIAL;
24165759Sdwmalone	case TPDWN:
242196500Sed		return PDWN | SPECIAL;
24374118Sache	case TPASTE:
244196500Sed		return PASTE | SPECIAL;
24532316Syokota	case TACC:
24632316Syokota		if (ACC(number) > L_ACC)
24732316Syokota			return -1;
248196500Sed		return ACC(number) | SPECIAL;
2492088Ssos	case TFUNC:
2502088Ssos		if (F(number) > L_FN)
2512088Ssos			return -1;
252196500Sed		return F(number) | SPECIAL;
2532088Ssos	case TSCRN:
2542088Ssos		if (S(number) > L_SCR)
2552088Ssos			return -1;
256196500Sed		return S(number) | SPECIAL;
2572088Ssos	case TLET:
2582088Ssos		return (unsigned char)letter;
2592088Ssos	case TNUM:
260197330Sed		if (number < 0x000000 || number > 0x10FFFF)
2612088Ssos			return -1;
2622088Ssos		return number;
2632088Ssos	default:
2642088Ssos		return -1;
2652088Ssos	}
2662088Ssos}
2672088Ssos
26877394Ssobomaxstatic int
26932316Syokotaget_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap)
2702088Ssos{
27132316Syokota	int c;
2722088Ssos
2732088Ssos	yyin = fd;
2742088Ssos
27532316Syokota	if (token < 0)
27632316Syokota		token = yylex();
27732316Syokota	switch (token) {
27832316Syokota	case TNUM:
27932316Syokota		c = get_key_definition_line(keymap);
28032316Syokota		if (c < 0)
28132316Syokota			errx(1, "invalid key definition");
28232316Syokota		if (c > keymap->n_keys)
28332316Syokota			keymap->n_keys = c;
28432316Syokota		break;
28532316Syokota	case TACC:
28632316Syokota		c = get_accent_definition_line(accentmap);
28732316Syokota		if (c < 0)
28832316Syokota			errx(1, "invalid accent key definition");
28932316Syokota		if (c > accentmap->n_accs)
29032316Syokota			accentmap->n_accs = c;
29132316Syokota		break;
29232316Syokota	case 0:
29332316Syokota		/* EOF */
2942088Ssos		return -1;
29532316Syokota	default:
29632316Syokota		errx(1, "illegal definition line");
29732316Syokota	}
29832316Syokota	return c;
29932316Syokota}
30032316Syokota
301228437Sedstatic int
30232316Syokotaget_key_definition_line(keymap_t *map)
30332316Syokota{
30432316Syokota	int i, def, scancode;
30532316Syokota
30632316Syokota	/* check scancode number */
3072088Ssos	if (number < 0 || number >= NUM_KEYS)
3082088Ssos		return -1;
3092088Ssos	scancode = number;
3102088Ssos
3112088Ssos	/* get key definitions */
3122088Ssos	map->key[scancode].spcl = 0;
3132088Ssos	for (i=0; i<NUM_STATES; i++) {
3142088Ssos		if ((def = get_entry()) == -1)
3152088Ssos			return -1;
316196500Sed		if (def & SPECIAL)
3172088Ssos			map->key[scancode].spcl |= (0x80 >> i);
318196500Sed		map->key[scancode].map[i] = def & ~SPECIAL;
3192088Ssos	}
3202088Ssos	/* get lock state key def */
32132316Syokota	if ((token = yylex()) != TFLAG)
3222088Ssos		return -1;
3232088Ssos	map->key[scancode].flgs = number;
32432316Syokota	token = yylex();
32532316Syokota	return (scancode + 1);
3262088Ssos}
3272088Ssos
328228437Sedstatic int
32932316Syokotaget_accent_definition_line(accentmap_t *map)
33032316Syokota{
33132316Syokota	int accent;
33232316Syokota	int c1, c2;
33332316Syokota	int i;
3342088Ssos
33532316Syokota	if (ACC(number) < F_ACC || ACC(number) > L_ACC)
33632316Syokota		/* number out of range */
33732316Syokota		return -1;
33832316Syokota	accent = number;
33932316Syokota	if (map->acc[accent].accchar != 0) {
34032316Syokota		/* this entry has already been defined before! */
34132316Syokota		errx(1, "duplicated accent key definition");
34232316Syokota	}
34332316Syokota
34432316Syokota	switch ((token = yylex())) {
34532316Syokota	case TLET:
34632316Syokota		map->acc[accent].accchar = letter;
34732316Syokota		break;
34832316Syokota	case TNUM:
34932316Syokota		map->acc[accent].accchar = number;
35032316Syokota		break;
35132316Syokota	default:
35232316Syokota		return -1;
35332316Syokota	}
35432316Syokota
35532316Syokota	for (i = 0; (token = yylex()) == '(';) {
35632316Syokota		switch ((token = yylex())) {
35732316Syokota		case TLET:
35832316Syokota			c1 = letter;
35932316Syokota			break;
36032316Syokota		case TNUM:
36132316Syokota			c1 = number;
36232316Syokota			break;
36332316Syokota		default:
36432316Syokota			return -1;
36532316Syokota		}
36632316Syokota		switch ((token = yylex())) {
36732316Syokota		case TLET:
36832316Syokota			c2 = letter;
36932316Syokota			break;
37032316Syokota		case TNUM:
37132316Syokota			c2 = number;
37232316Syokota			break;
37332316Syokota		default:
37432316Syokota			return -1;
37532316Syokota		}
37632316Syokota		if ((token = yylex()) != ')')
37732316Syokota			return -1;
37832316Syokota		if (i >= NUM_ACCENTCHARS) {
37932316Syokota			warnx("too many accented characters, ignored");
38032316Syokota			continue;
38132316Syokota		}
38232316Syokota		map->acc[accent].map[i][0] = c1;
38332316Syokota		map->acc[accent].map[i][1] = c2;
38432316Syokota		++i;
38532316Syokota	}
38632316Syokota	return (accent + 1);
38732316Syokota}
38832316Syokota
389228437Sedstatic void
3902088Ssosprint_entry(FILE *fp, int value)
3912088Ssos{
392196500Sed	int val = value & ~SPECIAL;
3932088Ssos
3942088Ssos	switch (value) {
395196500Sed	case NOP | SPECIAL:
3968857Srgrimes		fprintf(fp, " nop   ");
3972088Ssos		break;
398196500Sed	case LSH | SPECIAL:
3992088Ssos		fprintf(fp, " lshift");
4002088Ssos		break;
401196500Sed	case RSH | SPECIAL:
4022088Ssos		fprintf(fp, " rshift");
4032088Ssos		break;
404196500Sed	case CLK | SPECIAL:
4052088Ssos		fprintf(fp, " clock ");
4062088Ssos		break;
407196500Sed	case NLK | SPECIAL:
4082088Ssos		fprintf(fp, " nlock ");
4092088Ssos		break;
410196500Sed	case SLK | SPECIAL:
4112088Ssos		fprintf(fp, " slock ");
4122088Ssos		break;
413196500Sed	case BTAB | SPECIAL:
4142088Ssos		fprintf(fp, " btab  ");
4152088Ssos		break;
416196500Sed	case LALT | SPECIAL:
4172088Ssos		fprintf(fp, " lalt  ");
4182088Ssos		break;
419196500Sed	case LCTR | SPECIAL:
4202088Ssos		fprintf(fp, " lctrl ");
4212088Ssos		break;
422196500Sed	case NEXT | SPECIAL:
4232088Ssos		fprintf(fp, " nscr  ");
4242088Ssos		break;
425196500Sed	case PREV | SPECIAL:
42648105Syokota		fprintf(fp, " pscr  ");
42748105Syokota		break;
428196500Sed	case RCTR | SPECIAL:
4292088Ssos		fprintf(fp, " rctrl ");
4302088Ssos		break;
431196500Sed	case RALT | SPECIAL:
4322088Ssos		fprintf(fp, " ralt  ");
4332088Ssos		break;
434196500Sed	case ALK | SPECIAL:
4352088Ssos		fprintf(fp, " alock ");
4362088Ssos		break;
437196500Sed	case ASH | SPECIAL:
4382088Ssos		fprintf(fp, " ashift");
4392088Ssos		break;
440196500Sed	case META | SPECIAL:
4412088Ssos		fprintf(fp, " meta  ");
4422088Ssos		break;
443196500Sed	case RBT | SPECIAL:
4442088Ssos		fprintf(fp, " boot  ");
4452088Ssos		break;
446196500Sed	case DBG | SPECIAL:
4472088Ssos		fprintf(fp, " debug ");
4482088Ssos		break;
449196500Sed	case SUSP | SPECIAL:
45032316Syokota		fprintf(fp, " susp  ");
45132316Syokota		break;
452196500Sed	case SPSC | SPECIAL:
45338053Syokota		fprintf(fp, " saver ");
45438053Syokota		break;
455196500Sed	case PNC | SPECIAL:
45654380Syokota		fprintf(fp, " panic ");
45754380Syokota		break;
458196500Sed	case LSHA | SPECIAL:
45954380Syokota		fprintf(fp, " lshifta");
46054380Syokota		break;
461196500Sed	case RSHA | SPECIAL:
46254380Syokota		fprintf(fp, " rshifta");
46354380Syokota		break;
464196500Sed	case LCTRA | SPECIAL:
46554380Syokota		fprintf(fp, " lctrla");
46654380Syokota		break;
467196500Sed	case RCTRA | SPECIAL:
46854380Syokota		fprintf(fp, " rctrla");
46954380Syokota		break;
470196500Sed	case LALTA | SPECIAL:
47154380Syokota		fprintf(fp, " lalta ");
47254380Syokota		break;
473196500Sed	case RALTA | SPECIAL:
47454380Syokota		fprintf(fp, " ralta ");
47554380Syokota		break;
476196500Sed	case HALT | SPECIAL:
47765759Sdwmalone		fprintf(fp, " halt  ");
47865759Sdwmalone		break;
479196500Sed	case PDWN | SPECIAL:
48065759Sdwmalone		fprintf(fp, " pdwn  ");
48165759Sdwmalone		break;
482196500Sed	case PASTE | SPECIAL:
48374118Sache		fprintf(fp, " paste ");
48474118Sache		break;
4852088Ssos	default:
486196500Sed		if (value & SPECIAL) {
4878857Srgrimes		 	if (val >= F_FN && val <= L_FN)
4882088Ssos				fprintf(fp, " fkey%02d", val - F_FN + 1);
4898857Srgrimes		 	else if (val >= F_SCR && val <= L_SCR)
4902088Ssos				fprintf(fp, " scr%02d ", val - F_SCR + 1);
49132316Syokota		 	else if (val >= F_ACC && val <= L_ACC)
49232316Syokota				fprintf(fp, " %-6s", acc_names[val - F_ACC]);
4932088Ssos			else if (hex)
4948857Srgrimes				fprintf(fp, " 0x%02x  ", val);
4952088Ssos			else
49632316Syokota				fprintf(fp, " %3d   ", val);
4972088Ssos		}
4982088Ssos		else {
4992088Ssos			if (val < ' ')
5008857Srgrimes				fprintf(fp, " %s   ", ctrl_names[val]);
5012088Ssos			else if (val == 127)
5028857Srgrimes				fprintf(fp, " del   ");
5039202Srgrimes			else if (isascii(val) && isprint(val))
5048857Srgrimes				fprintf(fp, " '%c'   ", val);
5052088Ssos			else if (hex)
5068857Srgrimes				fprintf(fp, " 0x%02x  ", val);
5072088Ssos			else
5088857Srgrimes				fprintf(fp, " %3d   ", val);
5092088Ssos		}
5102088Ssos	}
5112088Ssos}
5122088Ssos
513228437Sedstatic void
51442505Syokotaprint_key_definition_line(FILE *fp, int scancode, struct keyent_t *key)
5152088Ssos{
51629603Scharnier	int i;
5172088Ssos
5182088Ssos	/* print scancode number */
5192088Ssos	if (hex)
5202088Ssos		fprintf(fp, " 0x%02x  ", scancode);
5212088Ssos	else
5222088Ssos		fprintf(fp, "  %03d  ", scancode);
5232088Ssos
5242088Ssos	/* print key definitions */
5252088Ssos	for (i=0; i<NUM_STATES; i++) {
5262088Ssos		if (key->spcl & (0x80 >> i))
527196500Sed			print_entry(fp, key->map[i] | SPECIAL);
5282088Ssos		else
5298857Srgrimes			print_entry(fp, key->map[i]);
5302088Ssos	}
5312088Ssos
5322088Ssos	/* print lock state key def */
5332088Ssos	switch (key->flgs) {
5342088Ssos	case 0:
5352088Ssos		fprintf(fp, "  O\n");
5362088Ssos		break;
5372088Ssos	case 1:
5382088Ssos		fprintf(fp, "  C\n");
5392088Ssos		break;
5402088Ssos	case 2:
5412088Ssos		fprintf(fp, "  N\n");
5422088Ssos		break;
5436046Ssos	case 3:
5446046Ssos		fprintf(fp, "  B\n");
5456046Ssos		break;
5468857Srgrimes	}
5472088Ssos}
5482088Ssos
549228437Sedstatic void
55032316Syokotaprint_accent_definition_line(FILE *fp, int accent, struct acc_t *key)
55132316Syokota{
55232316Syokota	int c;
55332316Syokota	int i;
5542088Ssos
55532316Syokota	if (key->accchar == 0)
55632316Syokota		return;
55732316Syokota
55832316Syokota	/* print accent number */
55932316Syokota	fprintf(fp, "  %-6s", acc_names[accent]);
56032316Syokota	if (isascii(key->accchar) && isprint(key->accchar))
56132316Syokota		fprintf(fp, "'%c'  ", key->accchar);
56232316Syokota	else if (hex)
56332316Syokota		fprintf(fp, "0x%02x ", key->accchar);
56432316Syokota	else
56532316Syokota		fprintf(fp, "%03d  ", key->accchar);
56632316Syokota
56732316Syokota	for (i = 0; i < NUM_ACCENTCHARS; ++i) {
56832316Syokota		c = key->map[i][0];
56932316Syokota		if (c == 0)
57032316Syokota			break;
57132316Syokota		if ((i > 0) && ((i % 4) == 0))
57232316Syokota			fprintf(fp, "\n             ");
57332316Syokota		if (isascii(c) && isprint(c))
57432316Syokota			fprintf(fp, "( '%c' ", c);
57532316Syokota		else if (hex)
57632316Syokota			fprintf(fp, "(0x%02x ", c);
57732316Syokota		else
57832316Syokota			fprintf(fp, "( %03d ", c);
57932316Syokota		c = key->map[i][1];
58032316Syokota		if (isascii(c) && isprint(c))
58132316Syokota			fprintf(fp, "'%c' ) ", c);
58232316Syokota		else if (hex)
58332316Syokota			fprintf(fp, "0x%02x) ", c);
58432316Syokota		else
58532316Syokota			fprintf(fp, "%03d ) ", c);
58632316Syokota	}
58732316Syokota	fprintf(fp, "\n");
58832316Syokota}
58932316Syokota
590228437Sedstatic void
59132316Syokotadump_entry(int value)
59232316Syokota{
593196500Sed	if (value & SPECIAL) {
594196500Sed		value &= ~SPECIAL;
59532316Syokota		switch (value) {
59632316Syokota		case NOP:
59732316Syokota			printf("  NOP, ");
59832316Syokota			break;
59932316Syokota		case LSH:
60032316Syokota			printf("  LSH, ");
60132316Syokota			break;
60232316Syokota		case RSH:
60332316Syokota			printf("  RSH, ");
60432316Syokota			break;
60532316Syokota		case CLK:
60632316Syokota			printf("  CLK, ");
60732316Syokota			break;
60832316Syokota		case NLK:
60932316Syokota			printf("  NLK, ");
61032316Syokota			break;
61132316Syokota		case SLK:
61232316Syokota			printf("  SLK, ");
61332316Syokota			break;
61432316Syokota		case BTAB:
61532316Syokota			printf(" BTAB, ");
61632316Syokota			break;
61732316Syokota		case LALT:
61832316Syokota			printf(" LALT, ");
61932316Syokota			break;
62032316Syokota		case LCTR:
62132316Syokota			printf(" LCTR, ");
62232316Syokota			break;
62332316Syokota		case NEXT:
62432316Syokota			printf(" NEXT, ");
62532316Syokota			break;
62648105Syokota		case PREV:
62748105Syokota			printf(" PREV, ");
62848105Syokota			break;
62932316Syokota		case RCTR:
63032316Syokota			printf(" RCTR, ");
63132316Syokota			break;
63232316Syokota		case RALT:
63332316Syokota			printf(" RALT, ");
63432316Syokota			break;
63532316Syokota		case ALK:
63632316Syokota			printf("  ALK, ");
63732316Syokota			break;
63832316Syokota		case ASH:
63932316Syokota			printf("  ASH, ");
64032316Syokota			break;
64132316Syokota		case META:
64232316Syokota			printf(" META, ");
64332316Syokota			break;
64432316Syokota		case RBT:
64532316Syokota			printf("  RBT, ");
64632316Syokota			break;
64732316Syokota		case DBG:
64832316Syokota			printf("  DBG, ");
64932316Syokota			break;
65032316Syokota		case SUSP:
65132316Syokota			printf(" SUSP, ");
65232316Syokota			break;
65338053Syokota		case SPSC:
65438053Syokota			printf(" SPSC, ");
65538053Syokota			break;
65654380Syokota		case PNC:
65754380Syokota			printf("  PNC, ");
65854380Syokota			break;
65954380Syokota		case LSHA:
66054380Syokota			printf(" LSHA, ");
66154380Syokota			break;
66254380Syokota		case RSHA:
66354380Syokota			printf(" RSHA, ");
66454380Syokota			break;
66554380Syokota		case LCTRA:
66654380Syokota			printf("LCTRA, ");
66754380Syokota			break;
66854380Syokota		case RCTRA:
66954380Syokota			printf("RCTRA, ");
67054380Syokota			break;
67154380Syokota		case LALTA:
67254380Syokota			printf("LALTA, ");
67354380Syokota			break;
67454380Syokota		case RALTA:
67554380Syokota			printf("RALTA, ");
67654380Syokota			break;
67765759Sdwmalone		case HALT:
67865759Sdwmalone			printf(" HALT, ");
67965759Sdwmalone			break;
68065759Sdwmalone		case PDWN:
68165759Sdwmalone			printf(" PDWN, ");
68265759Sdwmalone			break;
68374118Sache		case PASTE:
68474118Sache			printf("PASTE, ");
68574118Sache			break;
68632316Syokota		default:
68732316Syokota	 		if (value >= F_FN && value <= L_FN)
68832316Syokota				printf(" F(%2d),", value - F_FN + 1);
68932316Syokota	 		else if (value >= F_SCR && value <= L_SCR)
69032486Syokota				printf(" S(%2d),", value - F_SCR + 1);
69132316Syokota	 		else if (value >= F_ACC && value <= L_ACC)
69232316Syokota				printf(" %-4s, ", acc_names_u[value - F_ACC]);
69332316Syokota			else
69432316Syokota				printf(" 0x%02X, ", value);
69532316Syokota			break;
69632316Syokota		}
69732316Syokota	} else if (value == '\'') {
69832316Syokota		printf(" '\\'', ");
69932316Syokota	} else if (value == '\\') {
70032316Syokota		printf(" '\\\\', ");
70132316Syokota	} else if (isascii(value) && isprint(value)) {
70232316Syokota		printf("  '%c', ", value);
70332316Syokota	} else {
70432316Syokota		printf(" 0x%02X, ", value);
70532316Syokota	}
70632316Syokota}
70732316Syokota
708228437Sedstatic void
70932316Syokotadump_key_definition(char *name, keymap_t *keymap)
71032316Syokota{
71132316Syokota	int	i, j;
71232316Syokota
71332486Syokota	printf("static keymap_t keymap_%s = { 0x%02x, {\n",
71432316Syokota	       name, (unsigned)keymap->n_keys);
71532316Syokota	printf(
71632486Syokota"/*                                                         alt\n"
71732486Syokota" * scan                       cntrl          alt    alt   cntrl\n"
71832486Syokota" * code  base   shift  cntrl  shift   alt   shift  cntrl  shift    spcl flgs\n"
71932316Syokota" * ---------------------------------------------------------------------------\n"
72032316Syokota" */\n");
72132316Syokota	for (i = 0; i < keymap->n_keys; i++) {
72232486Syokota		printf("/*%02x*/{{", i);
72332316Syokota		for (j = 0; j < NUM_STATES; j++) {
72432316Syokota			if (keymap->key[i].spcl & (0x80 >> j))
725196500Sed				dump_entry(keymap->key[i].map[j] | SPECIAL);
72632316Syokota			else
72732316Syokota				dump_entry(keymap->key[i].map[j]);
72832316Syokota		}
72932486Syokota		printf("}, 0x%02X,0x%02X },\n",
73032316Syokota		       (unsigned)keymap->key[i].spcl,
73132316Syokota		       (unsigned)keymap->key[i].flgs);
73232316Syokota	}
73332486Syokota	printf("} };\n\n");
73432316Syokota}
73532316Syokota
736228437Sedstatic void
73732316Syokotadump_accent_definition(char *name, accentmap_t *accentmap)
73832316Syokota{
73932316Syokota	int i, j;
74032316Syokota	int c;
74132316Syokota
74232486Syokota	printf("static accentmap_t accentmap_%s = { %d",
74332316Syokota		name, accentmap->n_accs);
74432486Syokota	if (accentmap->n_accs <= 0) {
74532486Syokota		printf(" };\n\n");
74632486Syokota		return;
74732486Syokota	}
74832486Syokota	printf(", {\n");
74932316Syokota	for (i = 0; i < NUM_DEADKEYS; i++) {
75032316Syokota		printf("    /* %s=%d */\n    {", acc_names[i], i);
75132316Syokota		c = accentmap->acc[i].accchar;
75232316Syokota		if (c == '\'')
75332316Syokota			printf(" '\\'', {");
75432316Syokota		else if (c == '\\')
75532316Syokota			printf(" '\\\\', {");
75632316Syokota		else if (isascii(c) && isprint(c))
75732316Syokota			printf("  '%c', {", c);
75832316Syokota		else if (c == 0) {
75932316Syokota			printf(" 0x00 }, \n");
76032316Syokota			continue;
76132316Syokota		} else
76232316Syokota			printf(" 0x%02x, {", c);
76332316Syokota		for (j = 0; j < NUM_ACCENTCHARS; j++) {
76432316Syokota			c = accentmap->acc[i].map[j][0];
76532316Syokota			if (c == 0)
76632316Syokota				break;
76732316Syokota			if ((j > 0) && ((j % 4) == 0))
76832316Syokota				printf("\n\t     ");
76932316Syokota			if (isascii(c) && isprint(c))
77032316Syokota				printf(" {  '%c',", c);
77132316Syokota			else
77232316Syokota				printf(" { 0x%02x,", c);
77332316Syokota			printf("0x%02x },", accentmap->acc[i].map[j][1]);
77432316Syokota		}
77532316Syokota		printf(" }, },\n");
77632316Syokota	}
77732486Syokota	printf("} };\n\n");
77832316Syokota}
77932316Syokota
780228437Sedstatic void
78119569Sjoergload_keymap(char *opt, int dumponly)
7822088Ssos{
78332316Syokota	keymap_t keymap;
78432316Syokota	accentmap_t accentmap;
7852088Ssos	FILE	*fd;
78676502Ssobomax	int	i, j;
78719569Sjoerg	char	*name, *cp;
78899816Salfred	char	blank[] = "", keymap_path[] = KEYMAP_PATH, dotkbd[] = ".kbd";
78999816Salfred	char	*prefix[]  = {blank, blank, keymap_path, NULL};
79099816Salfred	char	*postfix[] = {blank, dotkbd, NULL};
7912088Ssos
79276569Ssobomax	cp = getenv("KEYMAP_PATH");
79376569Ssobomax	if (cp != NULL)
79476569Ssobomax		asprintf(&(prefix[0]), "%s/", cp);
79576502Ssobomax
79676643Simp	fd = NULL;
79776643Simp	for (i=0; prefix[i] && fd == NULL; i++) {
79876643Simp		for (j=0; postfix[j] && fd == NULL; j++) {
79976502Ssobomax			name = mkfullname(prefix[i], opt, postfix[j]);
80076643Simp			fd = fopen(name, "r");
80176502Ssobomax		}
80276643Simp	}
8032088Ssos	if (fd == NULL) {
80479677Sobrien		warn("keymap file \"%s\" not found", opt);
8052088Ssos		return;
8062088Ssos	}
80732316Syokota	memset(&keymap, 0, sizeof(keymap));
80832316Syokota	memset(&accentmap, 0, sizeof(accentmap));
80932316Syokota	token = -1;
8102088Ssos	while (1) {
81132316Syokota		if (get_definition_line(fd, &keymap, &accentmap) < 0)
8122088Ssos			break;
8132088Ssos    	}
81419569Sjoerg	if (dumponly) {
81519569Sjoerg		/* fix up the filename to make it a valid C identifier */
81619569Sjoerg		for (cp = opt; *cp; cp++)
81719569Sjoerg			if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_';
81832316Syokota		printf("/*\n"
81932316Syokota		       " * Automatically generated from %s.\n"
82032316Syokota	               " * DO NOT EDIT!\n"
82132316Syokota		       " */\n", name);
82232316Syokota		dump_key_definition(opt, &keymap);
82332316Syokota		dump_accent_definition(opt, &accentmap);
82419569Sjoerg		return;
82519569Sjoerg	}
82632316Syokota	if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) {
82729603Scharnier		warn("setting keymap");
8282088Ssos		fclose(fd);
8292088Ssos		return;
8302088Ssos	}
83132316Syokota	if ((accentmap.n_accs > 0)
83232316Syokota		&& (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) {
83332316Syokota		warn("setting accentmap");
83432316Syokota		fclose(fd);
83532316Syokota		return;
83632316Syokota	}
8372088Ssos}
8382088Ssos
839228437Sedstatic void
84099816Salfredprint_keymap(void)
8412088Ssos{
84232316Syokota	keymap_t keymap;
84332316Syokota	accentmap_t accentmap;
8442088Ssos	int i;
8452088Ssos
84632316Syokota	if (ioctl(0, GIO_KEYMAP, &keymap) < 0)
84729603Scharnier		err(1, "getting keymap");
84832316Syokota	if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0)
84932316Syokota		memset(&accentmap, 0, sizeof(accentmap));
8502088Ssos    	printf(
8512088Ssos"#                                                         alt\n"
8522088Ssos"# scan                       cntrl          alt    alt   cntrl lock\n"
8532088Ssos"# code  base   shift  cntrl  shift  alt    shift  cntrl  shift state\n"
8542088Ssos"# ------------------------------------------------------------------\n"
8552088Ssos    	);
85632316Syokota	for (i=0; i<keymap.n_keys; i++)
85732316Syokota		print_key_definition_line(stdout, i, &keymap.key[i]);
85832316Syokota
85932316Syokota	printf("\n");
86032316Syokota	for (i = 0; i < NUM_DEADKEYS; i++)
86132316Syokota		print_accent_definition_line(stdout, i, &accentmap.acc[i]);
86232316Syokota
8632088Ssos}
8642088Ssos
865228437Sedstatic void
86699816Salfredload_default_functionkeys(void)
8672088Ssos{
8682088Ssos	fkeyarg_t fkey;
8692088Ssos	int i;
8702088Ssos
8712088Ssos	for (i=0; i<NUM_FKEYS; i++) {
8722088Ssos		fkey.keynum = i;
8732088Ssos		strcpy(fkey.keydef, fkey_table[i]);
8742088Ssos		fkey.flen = strlen(fkey_table[i]);
8752088Ssos		if (ioctl(0, SETFKEY, &fkey) < 0)
87629603Scharnier			warn("setting function key");
8772088Ssos	}
8782088Ssos}
8792088Ssos
880228437Sedstatic void
8812088Ssosset_functionkey(char *keynumstr, char *string)
8822088Ssos{
8832088Ssos	fkeyarg_t fkey;
8842088Ssos
8852088Ssos	if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) {
8862088Ssos		load_default_functionkeys();
8872088Ssos		return;
8882088Ssos	}
8892088Ssos	fkey.keynum = atoi(keynumstr);
8902088Ssos	if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) {
89129603Scharnier		warnx("function key number must be between 1 and %d",
8922088Ssos			NUM_FKEYS);
8932088Ssos		return;
8942088Ssos	}
8952088Ssos	if ((fkey.flen = strlen(string)) > MAXFK) {
89629603Scharnier		warnx("function key string too long (%d > %d)",
8972088Ssos			fkey.flen, MAXFK);
8982088Ssos		return;
8992088Ssos	}
900133353Sjmg	strncpy(fkey.keydef, string, MAXFK);
9012088Ssos	fkey.keynum -= 1;
9022088Ssos	if (ioctl(0, SETFKEY, &fkey) < 0)
90329603Scharnier		warn("setting function key");
9042088Ssos}
9052088Ssos
906228437Sedstatic void
9072088Ssosset_bell_values(char *opt)
9082088Ssos{
9095536Ssos	int bell, duration, pitch;
9102088Ssos
91138044Syokota	bell = 0;
91238044Syokota	if (!strncmp(opt, "quiet.", 6)) {
913164333Sru		bell = CONS_QUIET_BELL;
91438044Syokota		opt += 6;
91538044Syokota	}
9168857Srgrimes	if (!strcmp(opt, "visual"))
917164333Sru		bell |= CONS_VISUAL_BELL;
9185536Ssos	else if (!strcmp(opt, "normal"))
91938044Syokota		duration = 5, pitch = 800;
92048982Syokota	else if (!strcmp(opt, "off"))
92148982Syokota		duration = 0, pitch = 0;
9222088Ssos	else {
9232088Ssos		char		*v1;
9248857Srgrimes
9255536Ssos		bell = 0;
9262088Ssos		duration = strtol(opt, &v1, 0);
9272088Ssos		if ((duration < 0) || (*v1 != '.'))
9282088Ssos			goto badopt;
9292088Ssos		opt = ++v1;
9302088Ssos		pitch = strtol(opt, &v1, 0);
9312088Ssos		if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) {
9322088Ssosbadopt:
93377394Ssobomax			warnx("argument to -b must be duration.pitch or [quiet.]visual|normal|off");
9342088Ssos			return;
9352088Ssos		}
93638044Syokota		if (pitch != 0)
93738044Syokota			pitch = 1193182 / pitch;	/* in Hz */
93838044Syokota		duration /= 10;	/* in 10 m sec */
9392088Ssos	}
9402088Ssos
9415536Ssos	ioctl(0, CONS_BELLTYPE, &bell);
942164333Sru	if (!(bell & CONS_VISUAL_BELL))
9435536Ssos		fprintf(stderr, "[=%d;%dB", pitch, duration);
9442088Ssos}
9452088Ssos
946228437Sedstatic void
9472088Ssosset_keyrates(char *opt)
9482088Ssos{
94944628Syokota	int arg[2];
95039047Syokota	int repeat;
95139047Syokota	int delay;
95246761Syokota	int r, d;
9532088Ssos
95446761Syokota	if (!strcmp(opt, "slow")) {
95544628Syokota		delay = 1000, repeat = 500;
95646761Syokota		d = 3, r = 31;
95746761Syokota	} else if (!strcmp(opt, "normal")) {
95844628Syokota		delay = 500, repeat = 125;
95946761Syokota		d = 1, r = 15;
96046761Syokota	} else if (!strcmp(opt, "fast")) {
96139047Syokota		delay = repeat = 0;
96246761Syokota		d = r = 0;
96346761Syokota	} else {
9642088Ssos		int		n;
9652088Ssos		char		*v1;
9662088Ssos
9672088Ssos		delay = strtol(opt, &v1, 0);
9682088Ssos		if ((delay < 0) || (*v1 != '.'))
9692088Ssos			goto badopt;
9702088Ssos		opt = ++v1;
9712088Ssos		repeat = strtol(opt, &v1, 0);
9722088Ssos		if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) {
9732088Ssosbadopt:
97477394Ssobomax			warnx("argument to -r must be delay.repeat or slow|normal|fast");
9752088Ssos			return;
9762088Ssos		}
97746761Syokota		for (n = 0; n < ndelays - 1; n++)
97846761Syokota			if (delay <= delays[n])
97946761Syokota				break;
98046761Syokota		d = n;
98146761Syokota		for (n = 0; n < nrepeats - 1; n++)
98246761Syokota			if (repeat <= repeats[n])
98346761Syokota				break;
98446761Syokota		r = n;
9852088Ssos	}
9862088Ssos
98744628Syokota	arg[0] = delay;
98844628Syokota	arg[1] = repeat;
98946761Syokota	if (ioctl(0, KDSETREPEAT, arg)) {
99046761Syokota		if (ioctl(0, KDSETRAD, (d << 5) | r))
99146761Syokota			warn("setting keyboard rate");
99246761Syokota	}
9932088Ssos}
9942088Ssos
99599816Salfredstatic const char *
99699816Salfredget_kbd_type_name(int type)
99742505Syokota{
99842505Syokota	static struct {
99942505Syokota		int type;
100099816Salfred		const char *name;
100142505Syokota	} name_table[] = {
100242505Syokota		{ KB_84,	"AT 84" },
100342505Syokota		{ KB_101,	"AT 101/102" },
100442505Syokota		{ KB_OTHER,	"generic" },
100542505Syokota	};
100699816Salfred	unsigned int i;
10076046Ssos
100842505Syokota	for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) {
100942505Syokota		if (type == name_table[i].type)
101042505Syokota			return name_table[i].name;
101142505Syokota	}
101242505Syokota	return "unknown";
101342505Syokota}
101442505Syokota
1015228437Sedstatic void
101642505Syokotashow_kbd_info(void)
101742505Syokota{
101842505Syokota	keyboard_info_t info;
101942505Syokota
102042505Syokota	if (ioctl(0, KDGKBINFO, &info) == -1) {
102142505Syokota		warn("unable to obtain keyboard information");
102242505Syokota		return;
102342505Syokota	}
102442505Syokota	printf("kbd%d:\n", info.kb_index);
102542505Syokota	printf("    %.*s%d, type:%s (%d)\n",
102677394Ssobomax		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
102742505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
102842505Syokota}
102942505Syokota
1030228437Sedstatic void
103142505Syokotaset_keyboard(char *device)
103242505Syokota{
103342505Syokota	keyboard_info_t info;
103442505Syokota	int fd;
103542505Syokota
103642505Syokota	fd = open(device, O_RDONLY);
103742505Syokota	if (fd < 0) {
103842505Syokota		warn("cannot open %s", device);
103942505Syokota		return;
104042505Syokota	}
104142505Syokota	if (ioctl(fd, KDGKBINFO, &info) == -1) {
104242505Syokota		warn("unable to obtain keyboard information");
104342505Syokota		close(fd);
104442505Syokota		return;
104542505Syokota	}
104642505Syokota	/*
104742505Syokota	 * The keyboard device driver won't release the keyboard by
104842505Syokota	 * the following ioctl, but it automatically will, when the device
104942505Syokota	 * is closed.  So, we don't check error here.
105042505Syokota	 */
105142505Syokota	ioctl(fd, CONS_RELKBD, 0);
105242505Syokota	close(fd);
105342505Syokota#if 1
105442505Syokota	printf("kbd%d\n", info.kb_index);
105542505Syokota	printf("    %.*s%d, type:%s (%d)\n",
105677394Ssobomax		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
105742505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
105842505Syokota#endif
105942505Syokota
106042505Syokota	if (ioctl(0, CONS_SETKBD, info.kb_index) == -1)
106142505Syokota		warn("unable to set keyboard");
106242505Syokota}
106342505Syokota
1064228437Sedstatic void
106542505Syokotarelease_keyboard(void)
106642505Syokota{
106742505Syokota	keyboard_info_t info;
106842505Syokota
106942505Syokota	/*
107042505Syokota	 * If stdin is not associated with a keyboard, the following ioctl
107142505Syokota	 * will fail.
107242505Syokota	 */
107342505Syokota	if (ioctl(0, KDGKBINFO, &info) == -1) {
107442505Syokota		warn("unable to obtain keyboard information");
107542505Syokota		return;
107642505Syokota	}
107742505Syokota#if 1
107842505Syokota	printf("kbd%d\n", info.kb_index);
107942505Syokota	printf("    %.*s%d, type:%s (%d)\n",
108077394Ssobomax		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
108142505Syokota		get_kbd_type_name(info.kb_type), info.kb_type);
108242505Syokota#endif
108342505Syokota	if (ioctl(0, CONS_RELKBD, 0) == -1)
108442505Syokota		warn("unable to release the keyboard");
108542505Syokota}
108642505Syokota
1087228437Sedstatic void
1088162327Semaxmux_keyboard(u_int op, char *kbd)
1089148017Semax{
1090148017Semax	keyboard_info_t	info;
1091148017Semax	char		*unit, *ep;
109242505Syokota
1093148017Semax	/*
1094148017Semax	 * If stdin is not associated with a keyboard, the following ioctl
1095148017Semax	 * will fail.
1096148017Semax	 */
1097148017Semax	if (ioctl(0, KDGKBINFO, &info) == -1) {
1098148017Semax		warn("unable to obtain keyboard information");
1099148017Semax		return;
1100148017Semax	}
1101148017Semax#if 1
1102148017Semax	printf("kbd%d\n", info.kb_index);
1103148017Semax	printf("    %.*s%d, type:%s (%d)\n",
1104148017Semax		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
1105148017Semax		get_kbd_type_name(info.kb_type), info.kb_type);
1106148017Semax#endif
1107148017Semax	/*
1108148017Semax	 * split kbd into name and unit. find the right most part of the
1109148017Semax	 * kbd string that consist of only digits.
1110148017Semax	 */
1111148017Semax
1112148017Semax	memset(&info, 0, sizeof(info));
1113148017Semax
1114148017Semax	info.kb_unit = -1;
1115148017Semax	ep = kbd - 1;
1116148017Semax
1117148017Semax	do {
1118148017Semax		unit = strpbrk(ep + 1, "0123456789");
1119148017Semax		if (unit != NULL) {
1120148017Semax			info.kb_unit = strtol(unit, &ep, 10);
1121148017Semax			if (*ep != '\0')
1122148017Semax				info.kb_unit = -1;
1123148017Semax		}
1124148017Semax	} while (unit != NULL && info.kb_unit == -1);
1125148017Semax
1126148017Semax	if (info.kb_unit == -1) {
1127148017Semax		warnx("unable to find keyboard driver unit in '%s'", kbd);
1128148017Semax		return;
1129148017Semax	}
1130148017Semax
1131148017Semax	if (unit == kbd) {
1132148017Semax		warnx("unable to find keyboard driver name in '%s'", kbd);
1133148017Semax		return;
1134148017Semax	}
1135148017Semax	if (unit - kbd >= (int) sizeof(info.kb_name)) {
1136148017Semax		warnx("keyboard name '%s' is too long", kbd);
1137148017Semax		return;
1138148017Semax	}
1139148017Semax
1140148017Semax	strncpy(info.kb_name, kbd, unit - kbd);
1141148017Semax
1142148017Semax	/*
1143148017Semax	 * If stdin is not associated with a kbdmux(4) keyboard, the following
1144148017Semax	 * ioctl will fail.
1145148017Semax	 */
1146148017Semax
1147148017Semax	if (ioctl(0, op, &info) == -1)
1148148017Semax		warn("unable to (un)mux the keyboard");
1149148017Semax}
1150148017Semax
1151228437Sedstatic void
1152201387Sedusage(void)
11532088Ssos{
115429603Scharnier	fprintf(stderr, "%s\n%s\n%s\n",
1155148017Semax"usage: kbdcontrol [-dFKix] [-A name] [-a name] [-b duration.pitch | [quiet.]belltype]",
115629603Scharnier"                  [-r delay.repeat | speed] [-l mapfile] [-f # string]",
115777329Sdes"                  [-k device] [-L mapfile]");
115829603Scharnier	exit(1);
11592088Ssos}
11602088Ssos
11612088Ssos
116251287Speterint
11632088Ssosmain(int argc, char **argv)
11642088Ssos{
11652088Ssos	int		opt;
11662088Ssos
1167148017Semax	while((opt = getopt(argc, argv, "A:a:b:df:iKk:Fl:L:r:x")) != -1)
11682088Ssos		switch(opt) {
1169148017Semax		case 'A':
1170148017Semax		case 'a':
1171148017Semax			mux_keyboard((opt == 'A')? KBRELKBD : KBADDKBD, optarg);
1172148017Semax			break;
117377329Sdes		case 'b':
117477329Sdes			set_bell_values(optarg);
117577329Sdes			break;
117677329Sdes		case 'd':
117777329Sdes			print_keymap();
117877329Sdes			break;
117977329Sdes		case 'l':
118077329Sdes			load_keymap(optarg, 0);
118177329Sdes			break;
118277329Sdes		case 'L':
118377329Sdes			load_keymap(optarg, 1);
118477329Sdes			break;
118577329Sdes		case 'f':
118677329Sdes			set_functionkey(optarg,
118777329Sdes			    nextarg(argc, argv, &optind, 'f'));
118877329Sdes			break;
118977329Sdes		case 'F':
119077329Sdes			load_default_functionkeys();
119177329Sdes			break;
119277329Sdes		case 'i':
119377329Sdes			show_kbd_info();
119477329Sdes			break;
119577329Sdes		case 'K':
119677329Sdes			release_keyboard();
119777329Sdes			break;
119877329Sdes		case 'k':
119977329Sdes			set_keyboard(optarg);
120077329Sdes			break;
120177329Sdes		case 'r':
120277329Sdes			set_keyrates(optarg);
120377329Sdes			break;
120477329Sdes		case 'x':
120577329Sdes			hex = 1;
120677329Sdes			break;
120777329Sdes		default:
120877329Sdes			usage();
12092088Ssos		}
121029603Scharnier	if ((optind != argc) || (argc == 1))
12112088Ssos		usage();
12122088Ssos	exit(0);
12132088Ssos}
1214