kbdcontrol.c revision 114601
1139825Simp/*-
2139740Sphk * Copyright (c) 1994-1995 S�ren Schmidt
350974Swpaul * All rights reserved.
450974Swpaul *
550974Swpaul * Redistribution and use in source and binary forms, with or without
650974Swpaul * modification, are permitted provided that the following conditions
750974Swpaul * are met:
850974Swpaul * 1. Redistributions of source code must retain the above copyright
950974Swpaul *    notice, this list of conditions and the following disclaimer,
1050974Swpaul *    in this position and unchanged.
1150974Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1250974Swpaul *    notice, this list of conditions and the following disclaimer in the
1350974Swpaul *    documentation and/or other materials provided with the distribution.
1450974Swpaul * 3. The name of the author may not be used to endorse or promote products
1550974Swpaul *    derived from this software without specific prior written permission
1650974Swpaul *
1750974Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1850974Swpaul * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1950974Swpaul * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2050974Swpaul * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2150974Swpaul * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2250974Swpaul * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2350974Swpaul * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2450974Swpaul * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2550974Swpaul * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2650974Swpaul * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2750974Swpaul */
2850974Swpaul
2950974Swpaul#include <sys/cdefs.h>
3050974Swpaul__FBSDID("$FreeBSD: head/usr.sbin/kbdcontrol/kbdcontrol.c 114601 2003-05-03 21:06:42Z obrien $");
3150974Swpaul
3250974Swpaul#include <ctype.h>
3350974Swpaul#include <err.h>
34122678Sobrien#include <stdio.h>
35122678Sobrien#include <stdlib.h>
36122678Sobrien#include <string.h>
3750974Swpaul#include <unistd.h>
3850974Swpaul#include <fcntl.h>
3950974Swpaul#include <sys/kbio.h>
4050974Swpaul#include <sys/consio.h>
4164963Swpaul#include "path.h"
4264963Swpaul#include "lex.h"
4364963Swpaul
4450974Swpaul/*
4550974Swpaul * HALT, PDWN, and PASTE aren't defined in 4.x, but we need them to bridge
4650974Swpaul * to 5.0-current so define them here as a stop gap transition measure.
4750974Swpaul */
4850974Swpaul#ifndef	HALT
4950974Swpaul#define	HALT		0xa1		/* halt machine */
5050974Swpaul#endif
5150974Swpaul#ifndef PDWN
5250974Swpaul#define	PDWN		0xa2		/* halt machine and power down */
5350974Swpaul#endif
5450974Swpaul#ifndef PASTE
5550974Swpaul#define PASTE		0xa3		/* paste from cut-paste buffer */
5650974Swpaul#endif
5750974Swpaul
5850974Swpaulchar ctrl_names[32][4] = {
5950974Swpaul	"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
6050974Swpaul	"bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ",
61150968Sglebius	"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
62150968Sglebius	"can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us "
63150968Sglebius	};
64150968Sglebius
6550974Swpaulchar acc_names[15][5] = {
6650974Swpaul	"dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot",
67212109Syongari	"duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo",
68212109Syongari	"dcar",
69212109Syongari	};
70212109Syongari
71212109Syongarichar acc_names_u[15][5] = {
7250974Swpaul	"DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT",
73129876Sphk	"DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO",
7450974Swpaul	"DCAR",
75212109Syongari	};
76212157Syongari
7750974Swpaulchar fkey_table[96][MAXFK] = {
7850974Swpaul/* 01-04 */	"\033[M", "\033[N", "\033[O", "\033[P",
7950974Swpaul/* 05-08 */	"\033[Q", "\033[R", "\033[S", "\033[T",
8050974Swpaul/* 09-12 */	"\033[U", "\033[V", "\033[W", "\033[X",
8150974Swpaul/* 13-16 */	"\033[Y", "\033[Z", "\033[a", "\033[b",
8250974Swpaul/* 17-20 */	"\033[c", "\033[d", "\033[e", "\033[f",
8387390Sjhay/* 21-24 */	"\033[g", "\033[h", "\033[i", "\033[j",
8487390Sjhay/* 25-28 */	"\033[k", "\033[l", "\033[m", "\033[n",
8550974Swpaul/* 29-32 */	"\033[o", "\033[p", "\033[q", "\033[r",
8650974Swpaul/* 33-36 */	"\033[s", "\033[t", "\033[u", "\033[v",
8750974Swpaul/* 37-40 */	"\033[w", "\033[x", "\033[y", "\033[z",
8850974Swpaul/* 41-44 */	"\033[@", "\033[[", "\033[\\","\033[]",
8950974Swpaul/* 45-48 */     "\033[^", "\033[_", "\033[`", "\033[{",
9050974Swpaul/* 49-52 */	"\033[H", "\033[A", "\033[I", "-"     ,
9150974Swpaul/* 53-56 */	"\033[D", "\033[E", "\033[C", "+"     ,
9250974Swpaul/* 57-60 */	"\033[F", "\033[B", "\033[G", "\033[L",
9350974Swpaul/* 61-64 */     "\177",   "\033[J", "\033[~", "\033[}",
9450974Swpaul/* 65-68 */	""      , ""      , ""      , ""      ,
9550974Swpaul/* 69-72 */	""      , ""      , ""      , ""      ,
96119288Simp/* 73-76 */	""      , ""      , ""      , ""      ,
97119288Simp/* 77-80 */	""      , ""      , ""      , ""      ,
9850974Swpaul/* 81-84 */	""      , ""      , ""      , ""      ,
9950974Swpaul/* 85-88 */	""      , ""      , ""      , ""      ,
10050974Swpaul/* 89-92 */	""      , ""      , ""      , ""      ,
101181524Simp/* 93-96 */	""      , ""      , ""      , ""      ,
10250974Swpaul	};
103113506Smdodd
104113506Smdoddconst int	delays[]  = {250, 500, 750, 1000};
10559758Speterconst int	repeats[] = { 34,  38,  42,  46,  50,  55,  59,  63,
10659758Speter			      68,  76,  84,  92, 100, 110, 118, 126,
107151545Simp			     136, 152, 168, 184, 200, 220, 236, 252,
10850974Swpaul			     272, 304, 336, 368, 400, 440, 472, 504};
10950974Swpaulconst int	ndelays = (sizeof(delays) / sizeof(int));
110150369Sphkconst int	nrepeats = (sizeof(repeats) / sizeof(int));
111150369Sphkint 		hex = 0;
112150369Sphkint 		number;
113150369Sphkchar 		letter;
11450974Swpaulint		token;
115150369Sphk
116150369Sphkvoid		dump_accent_definition(char *name, accentmap_t *accentmap);
117150526Sphkvoid		dump_entry(int value);
118150369Sphkvoid		dump_key_definition(char *name, keymap_t *keymap);
119150526Sphkint		get_accent_definition_line(accentmap_t *);
120150369Sphkint		get_entry(void);
121150526Sphkint		get_key_definition_line(keymap_t *);
122150369Sphkvoid		load_keymap(char *opt, int dumponly);
123150369Sphkvoid		load_default_functionkeys(void);
12450974Swpaulchar *		nextarg(int ac, char **av, int *indp, int oc);
12550974Swpaulchar *		mkfullname(const char *s1, const char *s2, const char *s3);
12650974Swpaulvoid		print_accent_definition_line(FILE *fp, int accent,
12750974Swpaul			struct acc_t *key);
12850974Swpaulvoid		print_entry(FILE *fp, int value);
129119712Sphkvoid		print_key_definition_line(FILE *fp, int scancode,
13050974Swpaul			struct keyent_t *key);
13150974Swpaulvoid		print_keymap(void);
13250974Swpaulvoid		release_keyboard(void);
133139801Sphkvoid		set_bell_values(char *opt);
134212109Syongarivoid		set_functionkey(char *keynumstr, char *string);
135212109Syongarivoid		set_keyboard(char *device);
136212109Syongarivoid		set_keyrates(char *opt);
137212109Syongarivoid		show_kbd_info(void);
138212109Syongarivoid		usage(void) __dead2;
139212109Syongari
140212109Syongarichar *
141212109Syongarinextarg(int ac, char **av, int *indp, int oc)
142212109Syongari{
143139801Sphk	if (*indp < ac)
144139801Sphk		return(av[(*indp)++]);
145139801Sphk	warnx("option requires two arguments -- %c", oc);
146139801Sphk	usage();
147139801Sphk}
148139801Sphk
149212109Syongari
150212167Syongarichar *
151212109Syongarimkfullname(const char *s1, const char *s2, const char *s3)
152139801Sphk{
153139801Sphk	static char	*buf = NULL;
154139801Sphk	static int	bufl = 0;
155212167Syongari	int		f;
156212157Syongari
157166940Sdelphij	f = strlen(s1) + strlen(s2) + strlen(s3) + 1;
158212167Syongari	if (f > bufl) {
15950974Swpaul		if (buf)
160150526Sphk			buf = (char *)realloc(buf, f);
161150526Sphk		else
16250974Swpaul			buf = (char *)malloc(f);
163150526Sphk	}
16450974Swpaul	if (!buf) {
165150526Sphk		bufl = 0;
16650974Swpaul		return(NULL);
167150526Sphk	}
168150526Sphk
169150526Sphk	bufl = f;
17050974Swpaul	strcpy(buf, s1);
17150974Swpaul	strcat(buf, s2);
17250974Swpaul	strcat(buf, s3);
17350974Swpaul	return(buf);
17450974Swpaul}
17550974Swpaul
17650974Swpaul
17750974Swpaulint
17850974Swpaulget_entry(void)
17950974Swpaul{
18050974Swpaul	switch ((token = yylex())) {
18150974Swpaul	case TNOP:
18250974Swpaul		return NOP | 0x100;
18350974Swpaul	case TLSH:
18450974Swpaul		return LSH | 0x100;
18562672Swpaul	case TRSH:
18662672Swpaul		return RSH | 0x100;
18762672Swpaul	case TCLK:
18862672Swpaul		return CLK | 0x100;
189139740Sphk	case TNLK:
190139740Sphk		return NLK | 0x100;
19162672Swpaul	case TSLK:
19262672Swpaul		return SLK | 0x100;
19362672Swpaul	case TBTAB:
19462672Swpaul		return BTAB | 0x100;
19562672Swpaul	case TLALT:
19662672Swpaul		return LALT | 0x100;
197212104Syongari	case TLCTR:
19862672Swpaul		return LCTR | 0x100;
19962672Swpaul	case TNEXT:
200102334Salfred		return NEXT | 0x100;
201139740Sphk	case TPREV:
20250974Swpaul		return PREV | 0x100;
20350974Swpaul	case TRCTR:
20450974Swpaul		return RCTR | 0x100;
20550974Swpaul	case TRALT:
20650974Swpaul		return RALT | 0x100;
20750974Swpaul	case TALK:
20850974Swpaul		return ALK | 0x100;
209102334Salfred	case TASH:
210139740Sphk		return ASH | 0x100;
21150974Swpaul	case TMETA:
212139708Sphk		return META | 0x100;
21350974Swpaul	case TRBT:
21450974Swpaul		return RBT | 0x100;
21550974Swpaul	case TDBG:
21650974Swpaul		return DBG | 0x100;
21750974Swpaul	case TSUSP:
21850974Swpaul		return SUSP | 0x100;
21950974Swpaul	case TSPSC:
22050974Swpaul		return SPSC | 0x100;
22150974Swpaul	case TPANIC:
22250974Swpaul		return PNC | 0x100;
22350974Swpaul	case TLSHA:
22450974Swpaul		return LSHA | 0x100;
22550974Swpaul	case TRSHA:
22650974Swpaul		return RSHA | 0x100;
22750974Swpaul	case TLCTRA:
22850974Swpaul		return LCTRA | 0x100;
22950974Swpaul	case TRCTRA:
23050974Swpaul		return RCTRA | 0x100;
23150974Swpaul	case TLALTA:
23250974Swpaul		return LALTA | 0x100;
23350974Swpaul	case TRALTA:
23450974Swpaul		return RALTA | 0x100;
23550974Swpaul	case THALT:
236102334Salfred		return HALT | 0x100;
237139740Sphk	case TPDWN:
23850974Swpaul		return PDWN | 0x100;
239139708Sphk	case TPASTE:
24050974Swpaul		return PASTE | 0x100;
24150974Swpaul	case TACC:
24250974Swpaul		if (ACC(number) > L_ACC)
24350974Swpaul			return -1;
24450974Swpaul		return ACC(number) | 0x100;
24550974Swpaul	case TFUNC:
24650974Swpaul		if (F(number) > L_FN)
24750974Swpaul			return -1;
24850974Swpaul		return F(number) | 0x100;
24950974Swpaul	case TSCRN:
25050974Swpaul		if (S(number) > L_SCR)
25150974Swpaul			return -1;
25250974Swpaul		return S(number) | 0x100;
25350974Swpaul	case TLET:
25450974Swpaul		return (unsigned char)letter;
25550974Swpaul	case TNUM:
25650974Swpaul		if (number < 0 || number > 255)
25750974Swpaul			return -1;
25850974Swpaul		return number;
25950974Swpaul	default:
26050974Swpaul		return -1;
26150974Swpaul	}
26250974Swpaul}
263102334Salfred
264139740Sphkstatic int
26550974Swpaulget_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap)
266139708Sphk{
267212113Syongari	int c;
26850974Swpaul
26950974Swpaul	yyin = fd;
27050974Swpaul
27150974Swpaul	if (token < 0)
27250974Swpaul		token = yylex();
27350974Swpaul	switch (token) {
27462672Swpaul	case TNUM:
27562672Swpaul		c = get_key_definition_line(keymap);
27650974Swpaul		if (c < 0)
27750974Swpaul			errx(1, "invalid key definition");
27850974Swpaul		if (c > keymap->n_keys)
27950974Swpaul			keymap->n_keys = c;
28050974Swpaul		break;
28150974Swpaul	case TACC:
28250974Swpaul		c = get_accent_definition_line(accentmap);
28350974Swpaul		if (c < 0)
28450974Swpaul			errx(1, "invalid accent key definition");
28550974Swpaul		if (c > accentmap->n_accs)
28650974Swpaul			accentmap->n_accs = c;
28750974Swpaul		break;
28850974Swpaul	case 0:
28950974Swpaul		/* EOF */
29050974Swpaul		return -1;
29150974Swpaul	default:
29250974Swpaul		errx(1, "illegal definition line");
29350974Swpaul	}
29450974Swpaul	return c;
29550974Swpaul}
29650974Swpaul
29750974Swpaulint
29850974Swpaulget_key_definition_line(keymap_t *map)
29950974Swpaul{
30050974Swpaul	int i, def, scancode;
30150974Swpaul
30250974Swpaul	/* check scancode number */
30350974Swpaul	if (number < 0 || number >= NUM_KEYS)
30450974Swpaul		return -1;
30550974Swpaul	scancode = number;
306102334Salfred
307139740Sphk	/* get key definitions */
30850974Swpaul	map->key[scancode].spcl = 0;
30950974Swpaul	for (i=0; i<NUM_STATES; i++) {
310212113Syongari		if ((def = get_entry()) == -1)
31150974Swpaul			return -1;
31250974Swpaul		if (def & 0x100)
31350974Swpaul			map->key[scancode].spcl |= (0x80 >> i);
314212113Syongari		map->key[scancode].map[i] = def & 0xFF;
31550974Swpaul	}
31650974Swpaul	/* get lock state key def */
31750974Swpaul	if ((token = yylex()) != TFLAG)
31850974Swpaul		return -1;
31950974Swpaul	map->key[scancode].flgs = number;
32050974Swpaul	token = yylex();
32150974Swpaul	return (scancode + 1);
322144243Sobrien}
323102334Salfred
324139740Sphkint
32572197Swpaulget_accent_definition_line(accentmap_t *map)
32672197Swpaul{
32772197Swpaul	int accent;
32872197Swpaul	int c1, c2;
32972197Swpaul	int i;
33072197Swpaul
33172197Swpaul	if (ACC(number) < F_ACC || ACC(number) > L_ACC)
33287994Sarchie		/* number out of range */
33372197Swpaul		return -1;
33472197Swpaul	accent = number;
33572197Swpaul	if (map->acc[accent].accchar != 0) {
336212104Syongari		/* this entry has already been defined before! */
33772197Swpaul		errx(1, "duplicated accent key definition");
33872197Swpaul	}
33972197Swpaul
34072197Swpaul	switch ((token = yylex())) {
341182065Simp	case TLET:
342182065Simp		map->acc[accent].accchar = letter;
34372197Swpaul		break;
34472197Swpaul	case TNUM:
34572197Swpaul		map->acc[accent].accchar = number;
34672197Swpaul		break;
34787994Sarchie	default:
348182065Simp		return -1;
34987994Sarchie	}
35072197Swpaul
35172197Swpaul	for (i = 0; (token = yylex()) == '(';) {
352182065Simp		switch ((token = yylex())) {
35372197Swpaul		case TLET:
35472197Swpaul			c1 = letter;
35587994Sarchie			break;
35672197Swpaul		case TNUM:
357212104Syongari			c1 = number;
35872197Swpaul			break;
35972197Swpaul		default:
360102334Salfred			return -1;
361139740Sphk		}
36272197Swpaul		switch ((token = yylex())) {
36372197Swpaul		case TLET:
364212113Syongari			c2 = letter;
36572197Swpaul			break;
36672197Swpaul		case TNUM:
36772197Swpaul			c2 = number;
36872197Swpaul			break;
36972197Swpaul		default:
37072197Swpaul			return -1;
37172197Swpaul		}
37272197Swpaul		if ((token = yylex()) != ')')
37372197Swpaul			return -1;
37472197Swpaul		if (i >= NUM_ACCENTCHARS) {
375144243Sobrien			warnx("too many accented characters, ignored");
37672197Swpaul			continue;
377144243Sobrien		}
378144243Sobrien		map->acc[accent].map[i][0] = c1;
379144243Sobrien		map->acc[accent].map[i][1] = c2;
38072197Swpaul		++i;
38172197Swpaul	}
38272197Swpaul	return (accent + 1);
38372197Swpaul}
38472197Swpaul
38572197Swpaulvoid
38672197Swpaulprint_entry(FILE *fp, int value)
38772197Swpaul{
38889296Swpaul	int val = value & 0xFF;
389102334Salfred
390139740Sphk	switch (value) {
39189296Swpaul	case NOP | 0x100:
392212113Syongari		fprintf(fp, " nop   ");
39389296Swpaul		break;
39489296Swpaul	case LSH | 0x100:
39589296Swpaul		fprintf(fp, " lshift");
39689296Swpaul		break;
39789296Swpaul	case RSH | 0x100:
39889296Swpaul		fprintf(fp, " rshift");
399212103Syongari		break;
40089296Swpaul	case CLK | 0x100:
40189296Swpaul		fprintf(fp, " clock ");
40289296Swpaul		break;
403212113Syongari	case NLK | 0x100:
40489296Swpaul		fprintf(fp, " nlock ");
405212113Syongari		break;
40689296Swpaul	case SLK | 0x100:
407212113Syongari		fprintf(fp, " slock ");
40889296Swpaul		break;
40989296Swpaul	case BTAB | 0x100:
41089296Swpaul		fprintf(fp, " btab  ");
41189296Swpaul		break;
41272197Swpaul	case LALT | 0x100:
41372197Swpaul		fprintf(fp, " lalt  ");
414109060Smbr		break;
415109060Smbr	case LCTR | 0x100:
416109060Smbr		fprintf(fp, " lctrl ");
417139740Sphk		break;
418139740Sphk	case NEXT | 0x100:
419109060Smbr		fprintf(fp, " nscr  ");
420139708Sphk		break;
421212103Syongari	case PREV | 0x100:
422109060Smbr		fprintf(fp, " pscr  ");
423212103Syongari		break;
424109060Smbr	case RCTR | 0x100:
425109060Smbr		fprintf(fp, " rctrl ");
426109060Smbr		break;
427109060Smbr	case RALT | 0x100:
428109060Smbr		fprintf(fp, " ralt  ");
429109060Smbr		break;
430109060Smbr	case ALK | 0x100:
431212103Syongari		fprintf(fp, " alock ");
432109060Smbr		break;
433109060Smbr	case ASH | 0x100:
434109060Smbr		fprintf(fp, " ashift");
435139740Sphk		break;
436139740Sphk	case META | 0x100:
437109060Smbr		fprintf(fp, " meta  ");
438109060Smbr		break;
439212103Syongari	case RBT | 0x100:
440109060Smbr		fprintf(fp, " boot  ");
441212103Syongari		break;
442109060Smbr	case DBG | 0x100:
443109060Smbr		fprintf(fp, " debug ");
444109060Smbr		break;
445109060Smbr	case SUSP | 0x100:
446109060Smbr		fprintf(fp, " susp  ");
447109060Smbr		break;
448109060Smbr	case SPSC | 0x100:
449109060Smbr		fprintf(fp, " saver ");
450109060Smbr		break;
451109060Smbr	case PNC | 0x100:
452109060Smbr		fprintf(fp, " panic ");
453109060Smbr		break;
454212103Syongari	case LSHA | 0x100:
455109060Smbr		fprintf(fp, " lshifta");
456109060Smbr		break;
457109060Smbr	case RSHA | 0x100:
458139740Sphk		fprintf(fp, " rshifta");
459139740Sphk		break;
460109060Smbr	case LCTRA | 0x100:
461150583Sjhb		fprintf(fp, " lctrla");
462212103Syongari		break;
463109060Smbr	case RCTRA | 0x100:
464109060Smbr		fprintf(fp, " rctrla");
465109060Smbr		break;
466109060Smbr	case LALTA | 0x100:
467109060Smbr		fprintf(fp, " lalta ");
468109060Smbr		break;
469109060Smbr	case RALTA | 0x100:
470212103Syongari		fprintf(fp, " ralta ");
471109060Smbr		break;
472109060Smbr	case HALT | 0x100:
473109060Smbr		fprintf(fp, " halt  ");
474109060Smbr		break;
475109060Smbr	case PDWN | 0x100:
476109060Smbr		fprintf(fp, " pdwn  ");
477212103Syongari		break;
478109060Smbr	case PASTE | 0x100:
479109060Smbr		fprintf(fp, " paste ");
480109060Smbr		break;
481109060Smbr	default:
482109060Smbr		if (value & 0x100) {
483109060Smbr		 	if (val >= F_FN && val <= L_FN)
484109060Smbr				fprintf(fp, " fkey%02d", val - F_FN + 1);
485212103Syongari		 	else if (val >= F_SCR && val <= L_SCR)
486109060Smbr				fprintf(fp, " scr%02d ", val - F_SCR + 1);
487109060Smbr		 	else if (val >= F_ACC && val <= L_ACC)
488109060Smbr				fprintf(fp, " %-6s", acc_names[val - F_ACC]);
489109060Smbr			else if (hex)
490109060Smbr				fprintf(fp, " 0x%02x  ", val);
491212103Syongari			else
492109060Smbr				fprintf(fp, " %3d   ", val);
493109060Smbr		}
494212103Syongari		else {
495109060Smbr			if (val < ' ')
496109060Smbr				fprintf(fp, " %s   ", ctrl_names[val]);
497109060Smbr			else if (val == 127)
498109060Smbr				fprintf(fp, " del   ");
499109060Smbr			else if (isascii(val) && isprint(val))
500109060Smbr				fprintf(fp, " '%c'   ", val);
501212103Syongari			else if (hex)
502109060Smbr				fprintf(fp, " 0x%02x  ", val);
503109060Smbr			else
504109060Smbr				fprintf(fp, " %3d   ", val);
505109060Smbr		}
506109060Smbr	}
507212104Syongari}
508109060Smbr
509109060Smbrvoid
510109060Smbrprint_key_definition_line(FILE *fp, int scancode, struct keyent_t *key)
511109060Smbr{
512109060Smbr	int i;
513109060Smbr
514109060Smbr	/* print scancode number */
515212103Syongari	if (hex)
516109060Smbr		fprintf(fp, " 0x%02x  ", scancode);
517109060Smbr	else
518109060Smbr		fprintf(fp, "  %03d  ", scancode);
519109060Smbr
520109060Smbr	/* print key definitions */
521109060Smbr	for (i=0; i<NUM_STATES; i++) {
522109060Smbr		if (key->spcl & (0x80 >> i))
523109060Smbr			print_entry(fp, key->map[i] | 0x100);
524109060Smbr		else
525109060Smbr			print_entry(fp, key->map[i]);
526109060Smbr	}
527109060Smbr
528109060Smbr	/* print lock state key def */
529109060Smbr	switch (key->flgs) {
530109060Smbr	case 0:
531109060Smbr		fprintf(fp, "  O\n");
532109060Smbr		break;
533109060Smbr	case 1:
534109060Smbr		fprintf(fp, "  C\n");
535109060Smbr		break;
536212104Syongari	case 2:
537212104Syongari		fprintf(fp, "  N\n");
538109060Smbr		break;
539212103Syongari	case 3:
540109060Smbr		fprintf(fp, "  B\n");
541109060Smbr		break;
542109060Smbr	}
543139740Sphk}
544139740Sphk
545109060Smbrvoid
546212103Syongariprint_accent_definition_line(FILE *fp, int accent, struct acc_t *key)
547109060Smbr{
548109060Smbr	int c;
549109060Smbr	int i;
550212103Syongari
551109060Smbr	if (key->accchar == 0)
552109060Smbr		return;
553109060Smbr
554212103Syongari	/* print accent number */
555109060Smbr	fprintf(fp, "  %-6s", acc_names[accent]);
556109060Smbr	if (isascii(key->accchar) && isprint(key->accchar))
557109060Smbr		fprintf(fp, "'%c'  ", key->accchar);
558109060Smbr	else if (hex)
559212103Syongari		fprintf(fp, "0x%02x ", key->accchar);
560109060Smbr	else
561212103Syongari		fprintf(fp, "%03d  ", key->accchar);
562109060Smbr
563109060Smbr	for (i = 0; i < NUM_ACCENTCHARS; ++i) {
564109060Smbr		c = key->map[i][0];
565109060Smbr		if (c == 0)
566109060Smbr			break;
567109060Smbr		if ((i > 0) && ((i % 4) == 0))
568212103Syongari			fprintf(fp, "\n             ");
569109060Smbr		if (isascii(c) && isprint(c))
570109060Smbr			fprintf(fp, "( '%c' ", c);
571109060Smbr		else if (hex)
572109060Smbr			fprintf(fp, "(0x%02x ", c);
573109060Smbr		else
574212103Syongari			fprintf(fp, "( %03d ", c);
575109060Smbr		c = key->map[i][1];
576109060Smbr		if (isascii(c) && isprint(c))
577109060Smbr			fprintf(fp, "'%c' ) ", c);
578109060Smbr		else if (hex)
579212103Syongari			fprintf(fp, "0x%02x) ", c);
580212104Syongari		else
581109060Smbr			fprintf(fp, "%03d ) ", c);
582109060Smbr	}
583102334Salfred	fprintf(fp, "\n");
584139740Sphk}
58550974Swpaul
58650974Swpaulvoid
587109060Smbrdump_entry(int value)
58850974Swpaul{
58950974Swpaul	if (value & 0x100) {
59050974Swpaul		value &= 0x00ff;
59162672Swpaul		switch (value) {
59262672Swpaul		case NOP:
593212104Syongari			printf("  NOP, ");
59462672Swpaul			break;
59562672Swpaul		case LSH:
59662672Swpaul			printf("  LSH, ");
59762672Swpaul			break;
59862672Swpaul		case RSH:
59962672Swpaul			printf("  RSH, ");
60062672Swpaul			break;
60162672Swpaul		case CLK:
60262672Swpaul			printf("  CLK, ");
60362672Swpaul			break;
60462672Swpaul		case NLK:
60562672Swpaul			printf("  NLK, ");
606109060Smbr			break;
60762672Swpaul		case SLK:
60862672Swpaul			printf("  SLK, ");
609109976Smbr			break;
610109976Smbr		case BTAB:
611109976Smbr			printf(" BTAB, ");
612109976Smbr			break;
613109976Smbr		case LALT:
61489296Swpaul			printf(" LALT, ");
615109976Smbr			break;
616109976Smbr		case LCTR:
61750974Swpaul			printf(" LCTR, ");
618109976Smbr			break;
619212104Syongari		case NEXT:
62050974Swpaul			printf(" NEXT, ");
621109976Smbr			break;
622109976Smbr		case PREV:
623109976Smbr			printf(" PREV, ");
62450974Swpaul			break;
625109976Smbr		case RCTR:
626109976Smbr			printf(" RCTR, ");
627109976Smbr			break;
628109976Smbr		case RALT:
629109976Smbr			printf(" RALT, ");
630109976Smbr			break;
631162315Sglebius		case ALK:
632212104Syongari			printf("  ALK, ");
633109976Smbr			break;
634109976Smbr		case ASH:
635109976Smbr			printf("  ASH, ");
636109976Smbr			break;
637109976Smbr		case META:
638212104Syongari			printf(" META, ");
639109976Smbr			break;
640212104Syongari		case RBT:
641109976Smbr			printf("  RBT, ");
642109976Smbr			break;
643109976Smbr		case DBG:
644109976Smbr			printf("  DBG, ");
645109976Smbr			break;
646109976Smbr		case SUSP:
647109976Smbr			printf(" SUSP, ");
648212104Syongari			break;
649109976Smbr		case SPSC:
65050974Swpaul			printf(" SPSC, ");
65150974Swpaul			break;
652102334Salfred		case PNC:
653139740Sphk			printf("  PNC, ");
65450974Swpaul			break;
65550974Swpaul		case LSHA:
656109060Smbr			printf(" LSHA, ");
65750974Swpaul			break;
65850974Swpaul		case RSHA:
65950974Swpaul			printf(" RSHA, ");
66062672Swpaul			break;
66162672Swpaul		case LCTRA:
662212104Syongari			printf("LCTRA, ");
66362672Swpaul			break;
664212104Syongari		case RCTRA:
66562672Swpaul			printf("RCTRA, ");
66662672Swpaul			break;
667109976Smbr		case LALTA:
668109976Smbr			printf("LALTA, ");
669109976Smbr			break;
670109976Smbr		case RALTA:
671109976Smbr			printf("RALTA, ");
672109976Smbr			break;
673109976Smbr		case HALT:
674109976Smbr			printf(" HALT, ");
67550974Swpaul			break;
676109976Smbr		case PDWN:
677212104Syongari			printf(" PDWN, ");
67850974Swpaul			break;
679109976Smbr		case PASTE:
680109976Smbr			printf("PASTE, ");
681109976Smbr			break;
68250974Swpaul		default:
683109976Smbr	 		if (value >= F_FN && value <= L_FN)
684109976Smbr				printf(" F(%2d),", value - F_FN + 1);
685109976Smbr	 		else if (value >= F_SCR && value <= L_SCR)
686109976Smbr				printf(" S(%2d),", value - F_SCR + 1);
68750974Swpaul	 		else if (value >= F_ACC && value <= L_ACC)
688109976Smbr				printf(" %-4s, ", acc_names_u[value - F_ACC]);
689162315Sglebius			else
690109976Smbr				printf(" 0x%02X, ", value);
691109976Smbr			break;
692109976Smbr		}
693109976Smbr	} else if (value == '\'') {
694109976Smbr		printf(" '\\'', ");
695109976Smbr	} else if (value == '\\') {
696109976Smbr		printf(" '\\\\', ");
697109976Smbr	} else if (isascii(value) && isprint(value)) {
698212104Syongari		printf("  '%c', ", value);
69950974Swpaul	} else {
70050974Swpaul		printf(" 0x%02X, ", value);
701102334Salfred	}
702139717Sphk}
70350974Swpaul
70450974Swpaulvoid
705212116Syongaridump_key_definition(char *name, keymap_t *keymap)
706212116Syongari{
707212116Syongari	int	i, j;
70850974Swpaul
70950974Swpaul	printf("static keymap_t keymap_%s = { 0x%02x, {\n",
710139717Sphk	       name, (unsigned)keymap->n_keys);
711212116Syongari	printf(
712212116Syongari"/*                                                         alt\n"
713212116Syongari" * scan                       cntrl          alt    alt   cntrl\n"
714212116Syongari" * code  base   shift  cntrl  shift   alt   shift  cntrl  shift    spcl flgs\n"
715212116Syongari" * ---------------------------------------------------------------------------\n"
716212116Syongari" */\n");
717212116Syongari	for (i = 0; i < keymap->n_keys; i++) {
718212157Syongari		printf("/*%02x*/{{", i);
719212116Syongari		for (j = 0; j < NUM_STATES; j++) {
720212116Syongari			if (keymap->key[i].spcl & (0x80 >> j))
721212116Syongari				dump_entry(keymap->key[i].map[j] | 0x100);
722212116Syongari			else
723212116Syongari				dump_entry(keymap->key[i].map[j]);
724212157Syongari		}
725212116Syongari		printf("}, 0x%02X,0x%02X },\n",
726212116Syongari		       (unsigned)keymap->key[i].spcl,
727212116Syongari		       (unsigned)keymap->key[i].flgs);
728212157Syongari	}
729212116Syongari	printf("} };\n\n");
730212116Syongari}
731212116Syongari
732212116Syongarivoid
733212116Syongaridump_accent_definition(char *name, accentmap_t *accentmap)
734212116Syongari{
735212157Syongari	int i, j;
736212116Syongari	int c;
737212116Syongari
738212116Syongari	printf("static accentmap_t accentmap_%s = { %d",
739212116Syongari		name, accentmap->n_accs);
740212116Syongari	if (accentmap->n_accs <= 0) {
741212116Syongari		printf(" };\n\n");
742212116Syongari		return;
743212116Syongari	}
744212116Syongari	printf(", {\n");
745212116Syongari	for (i = 0; i < NUM_DEADKEYS; i++) {
746212116Syongari		printf("    /* %s=%d */\n    {", acc_names[i], i);
747212116Syongari		c = accentmap->acc[i].accchar;
748212116Syongari		if (c == '\'')
749212116Syongari			printf(" '\\'', {");
750212116Syongari		else if (c == '\\')
751212116Syongari			printf(" '\\\\', {");
752212116Syongari		else if (isascii(c) && isprint(c))
753212116Syongari			printf("  '%c', {", c);
754212116Syongari		else if (c == 0) {
755212116Syongari			printf(" 0x00 }, \n");
756212116Syongari			continue;
757212116Syongari		} else
758212116Syongari			printf(" 0x%02x, {", c);
759212116Syongari		for (j = 0; j < NUM_ACCENTCHARS; j++) {
760212116Syongari			c = accentmap->acc[i].map[j][0];
761212116Syongari			if (c == 0)
762212116Syongari				break;
763212116Syongari			if ((j > 0) && ((j % 4) == 0))
764212116Syongari				printf("\n\t     ");
765212116Syongari			if (isascii(c) && isprint(c))
766212116Syongari				printf(" {  '%c',", c);
767212116Syongari			else
768212116Syongari				printf(" { 0x%02x,", c);
769212116Syongari			printf("0x%02x },", accentmap->acc[i].map[j][1]);
770212116Syongari		}
771212116Syongari		printf(" }, },\n");
772212116Syongari	}
773212116Syongari	printf("} };\n\n");
774212116Syongari}
775212116Syongari
776212116Syongarivoid
777212116Syongariload_keymap(char *opt, int dumponly)
778212116Syongari{
779212116Syongari	keymap_t keymap;
780212116Syongari	accentmap_t accentmap;
781212116Syongari	FILE	*fd;
782212116Syongari	int	i, j;
783212116Syongari	char	*name, *cp;
784212116Syongari	char	blank[] = "", keymap_path[] = KEYMAP_PATH, dotkbd[] = ".kbd";
78550974Swpaul	char	*prefix[]  = {blank, blank, keymap_path, NULL};
78650974Swpaul	char	*postfix[] = {blank, dotkbd, NULL};
787139740Sphk
788139740Sphk	cp = getenv("KEYMAP_PATH");
78950974Swpaul	if (cp != NULL)
790130270Snaddy		asprintf(&(prefix[0]), "%s/", cp);
79150974Swpaul
79250974Swpaul	fd = NULL;
793130270Snaddy	for (i=0; prefix[i] && fd == NULL; i++) {
79450974Swpaul		for (j=0; postfix[j] && fd == NULL; j++) {
79562672Swpaul			name = mkfullname(prefix[i], opt, postfix[j]);
79662672Swpaul			fd = fopen(name, "r");
79762672Swpaul		}
79862672Swpaul	}
79962672Swpaul	if (fd == NULL) {
80062672Swpaul		warn("keymap file \"%s\" not found", opt);
80162672Swpaul		return;
802109060Smbr	}
803109976Smbr	memset(&keymap, 0, sizeof(keymap));
804109976Smbr	memset(&accentmap, 0, sizeof(accentmap));
805109060Smbr	token = -1;
806109976Smbr	while (1) {
807109976Smbr		if (get_definition_line(fd, &keymap, &accentmap) < 0)
80850974Swpaul			break;
80950974Swpaul    	}
810102334Salfred	if (dumponly) {
811139740Sphk		/* fix up the filename to make it a valid C identifier */
81250974Swpaul		for (cp = opt; *cp; cp++)
81350974Swpaul			if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_';
81450974Swpaul		printf("/*\n"
815212113Syongari		       " * Automatically generated from %s.\n"
81662672Swpaul	               " * DO NOT EDIT!\n"
81750974Swpaul		       " */\n", name);
818147256Sbrooks		dump_key_definition(opt, &keymap);
81950974Swpaul		dump_accent_definition(opt, &accentmap);
82050974Swpaul		return;
82162672Swpaul	}
82250974Swpaul	if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) {
82350974Swpaul		warn("setting keymap");
82450974Swpaul		fclose(fd);
82550974Swpaul		return;
82662672Swpaul	}
82762672Swpaul	if ((accentmap.n_accs > 0)
82862672Swpaul		&& (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) {
82962672Swpaul		warn("setting accentmap");
83062672Swpaul		fclose(fd);
83150974Swpaul		return;
83250974Swpaul	}
83350974Swpaul}
83450974Swpaul
83550974Swpaulvoid
83662672Swpaulprint_keymap(void)
83762672Swpaul{
83862672Swpaul	keymap_t keymap;
83962672Swpaul	accentmap_t accentmap;
84062672Swpaul	int i;
841195049Srwatson
84272084Sphk	if (ioctl(0, GIO_KEYMAP, &keymap) < 0)
84362672Swpaul		err(1, "getting keymap");
84462672Swpaul	if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0)
845122625Sobrien		memset(&accentmap, 0, sizeof(accentmap));
846122625Sobrien    	printf(
84762672Swpaul"#                                                         alt\n"
84862672Swpaul"# scan                       cntrl          alt    alt   cntrl lock\n"
84962672Swpaul"# code  base   shift  cntrl  shift  alt    shift  cntrl  shift state\n"
85062672Swpaul"# ------------------------------------------------------------------\n"
85162672Swpaul    	);
85262672Swpaul	for (i=0; i<keymap.n_keys; i++)
85362672Swpaul		print_key_definition_line(stdout, i, &keymap.key[i]);
854195049Srwatson
85562672Swpaul	printf("\n");
85662672Swpaul	for (i = 0; i < NUM_DEADKEYS; i++)
85762672Swpaul		print_accent_definition_line(stdout, i, &accentmap.acc[i]);
85862672Swpaul
859102334Salfred}
860139740Sphk
86162672Swpaulvoid
86262672Swpaulload_default_functionkeys(void)
86362672Swpaul{
864212113Syongari	fkeyarg_t fkey;
865212113Syongari	int i;
86662672Swpaul
867147256Sbrooks	for (i=0; i<NUM_FKEYS; i++) {
86862672Swpaul		fkey.keynum = i;
869109060Smbr		strcpy(fkey.keydef, fkey_table[i]);
870109976Smbr		fkey.flen = strlen(fkey_table[i]);
871109976Smbr		if (ioctl(0, SETFKEY, &fkey) < 0)
872109976Smbr			warn("setting function key");
873109976Smbr	}
874109976Smbr}
87562672Swpaul
876109060Smbrvoid
87762672Swpaulset_functionkey(char *keynumstr, char *string)
878109060Smbr{
879109060Smbr	fkeyarg_t fkey;
88062672Swpaul
881109060Smbr	if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) {
882109060Smbr		load_default_functionkeys();
883109060Smbr		return;
884109060Smbr	}
885109060Smbr	fkey.keynum = atoi(keynumstr);
886109060Smbr	if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) {
887109060Smbr		warnx("function key number must be between 1 and %d",
888109060Smbr			NUM_FKEYS);
889109060Smbr		return;
890109060Smbr	}
891195049Srwatson	if ((fkey.flen = strlen(string)) > MAXFK) {
892109060Smbr		warnx("function key string too long (%d > %d)",
893109060Smbr			fkey.flen, MAXFK);
894109060Smbr		return;
895122625Sobrien	}
896109060Smbr	strcpy(fkey.keydef, string);
897109060Smbr	fkey.keynum -= 1;
898109060Smbr	if (ioctl(0, SETFKEY, &fkey) < 0)
899109060Smbr		warn("setting function key");
900195049Srwatson}
901109060Smbr
902109060Smbrvoid
903109060Smbrset_bell_values(char *opt)
904109060Smbr{
905109060Smbr	int bell, duration, pitch;
90650974Swpaul
90750974Swpaul	bell = 0;
908109060Smbr	if (!strncmp(opt, "quiet.", 6)) {
909109060Smbr		bell = 2;
910109060Smbr		opt += 6;
91150974Swpaul	}
91250974Swpaul	if (!strcmp(opt, "visual"))
913109060Smbr		bell |= 1;
91450974Swpaul	else if (!strcmp(opt, "normal"))
91550974Swpaul		duration = 5, pitch = 800;
916102334Salfred	else if (!strcmp(opt, "off"))
917139717Sphk		duration = 0, pitch = 0;
91850974Swpaul	else {
919139708Sphk		char		*v1;
92050974Swpaul
92150974Swpaul		bell = 0;
92250974Swpaul		duration = strtol(opt, &v1, 0);
92350974Swpaul		if ((duration < 0) || (*v1 != '.'))
92450974Swpaul			goto badopt;
92550974Swpaul		opt = ++v1;
92650974Swpaul		pitch = strtol(opt, &v1, 0);
92750974Swpaul		if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) {
92850974Swpaulbadopt:
929162315Sglebius			warnx("argument to -b must be duration.pitch or [quiet.]visual|normal|off");
93050974Swpaul			return;
93150974Swpaul		}
93250974Swpaul		if (pitch != 0)
93372813Swpaul			pitch = 1193182 / pitch;	/* in Hz */
93472813Swpaul		duration /= 10;	/* in 10 m sec */
93572813Swpaul	}
93672813Swpaul
93772813Swpaul	ioctl(0, CONS_BELLTYPE, &bell);
93872813Swpaul	if ((bell & ~2) == 0)
93972813Swpaul		fprintf(stderr, "[=%d;%dB", pitch, duration);
94072813Swpaul}
941212167Syongari
942212167Syongarivoid
943212167Syongariset_keyrates(char *opt)
94472813Swpaul{
94550974Swpaul	int arg[2];
94650974Swpaul	int repeat;
94750974Swpaul	int delay;
94850974Swpaul	int r, d;
94950974Swpaul
95050974Swpaul	if (!strcmp(opt, "slow")) {
951102334Salfred		delay = 1000, repeat = 500;
952139740Sphk		d = 3, r = 31;
95350974Swpaul	} else if (!strcmp(opt, "normal")) {
95450974Swpaul		delay = 500, repeat = 125;
95550974Swpaul		d = 1, r = 15;
95650974Swpaul	} else if (!strcmp(opt, "fast")) {
95750974Swpaul		delay = repeat = 0;
958212104Syongari		d = r = 0;
95950974Swpaul	} else {
96050974Swpaul		int		n;
96150974Swpaul		char		*v1;
962142398Simp
96350974Swpaul		delay = strtol(opt, &v1, 0);
96450974Swpaul		if ((delay < 0) || (*v1 != '.'))
96550974Swpaul			goto badopt;
96650974Swpaul		opt = ++v1;
967212104Syongari		repeat = strtol(opt, &v1, 0);
96850974Swpaul		if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) {
96950974Swpaulbadopt:
97050974Swpaul			warnx("argument to -r must be delay.repeat or slow|normal|fast");
97150974Swpaul			return;
97250974Swpaul		}
97350974Swpaul		for (n = 0; n < ndelays - 1; n++)
974102334Salfred			if (delay <= delays[n])
975139740Sphk				break;
97650974Swpaul		d = n;
97750974Swpaul		for (n = 0; n < nrepeats - 1; n++)
97850974Swpaul			if (repeat <= repeats[n])
97950974Swpaul				break;
980212167Syongari		r = n;
98150974Swpaul	}
982109061Smbr
98350974Swpaul	arg[0] = delay;
98450974Swpaul	arg[1] = repeat;
985162315Sglebius	if (ioctl(0, KDSETREPEAT, arg)) {
986119712Sphk		if (ioctl(0, KDSETRAD, (d << 5) | r))
98793818Sjhb			warn("setting keyboard rate");
988139810Sphk	}
989150583Sjhb}
99069583Swpaul
99150974Swpaulstatic const char *
99250974Swpaulget_kbd_type_name(int type)
99350974Swpaul{
99450974Swpaul	static struct {
99562672Swpaul		int type;
99662672Swpaul		const char *name;
99750974Swpaul	} name_table[] = {
99889296Swpaul		{ KB_84,	"AT 84" },
99950974Swpaul		{ KB_101,	"AT 101/102" },
100050974Swpaul		{ KB_OTHER,	"generic" },
100150974Swpaul	};
100272813Swpaul	unsigned int i;
100350974Swpaul
1004150526Sphk	for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) {
1005150583Sjhb		if (type == name_table[i].type)
1006150583Sjhb			return name_table[i].name;
1007150583Sjhb	}
1008150583Sjhb	return "unknown";
100950974Swpaul}
101050974Swpaul
101150974Swpaulvoid
101250974Swpaulshow_kbd_info(void)
1013109976Smbr{
1014212103Syongari	keyboard_info_t info;
1015212103Syongari
1016109976Smbr	if (ioctl(0, KDGKBINFO, &info) == -1) {
1017109976Smbr		warn("unable to obtain keyboard information");
1018109976Smbr		return;
1019109976Smbr	}
102050974Swpaul	printf("kbd%d:\n", info.kb_index);
102150974Swpaul	printf("    %.*s%d, type:%s (%d)\n",
102250974Swpaul		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
102362672Swpaul		get_kbd_type_name(info.kb_type), info.kb_type);
102462672Swpaul}
1025119712Sphk
1026119712Sphkvoid
1027119712Sphkset_keyboard(char *device)
1028119712Sphk{
1029119712Sphk	keyboard_info_t info;
1030119712Sphk	int fd;
1031119712Sphk
1032119712Sphk	fd = open(device, O_RDONLY);
1033119712Sphk	if (fd < 0) {
1034119712Sphk		warn("cannot open %s", device);
1035119712Sphk		return;
1036119712Sphk	}
103762672Swpaul	if (ioctl(fd, KDGKBINFO, &info) == -1) {
103862672Swpaul		warn("unable to obtain keyboard information");
103962672Swpaul		close(fd);
104062672Swpaul		return;
104162672Swpaul	}
104262672Swpaul	/*
104362672Swpaul	 * The keyboard device driver won't release the keyboard by
104462672Swpaul	 * the following ioctl, but it automatically will, when the device
104562672Swpaul	 * is closed.  So, we don't check error here.
104662672Swpaul	 */
104762672Swpaul	ioctl(fd, CONS_RELKBD, 0);
104862672Swpaul	close(fd);
104962672Swpaul#if 1
1050212113Syongari	printf("kbd%d\n", info.kb_index);
105150974Swpaul	printf("    %.*s%d, type:%s (%d)\n",
105262672Swpaul		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
105362672Swpaul		get_kbd_type_name(info.kb_type), info.kb_type);
105462672Swpaul#endif
105562672Swpaul
105662672Swpaul	if (ioctl(0, CONS_SETKBD, info.kb_index) == -1)
105762681Swpaul		warn("unable to set keyboard");
105862672Swpaul}
105962681Swpaul
106062672Swpaulvoid
106162681Swpaulrelease_keyboard(void)
106262672Swpaul{
106362672Swpaul	keyboard_info_t info;
106462672Swpaul
106562672Swpaul	/*
106662672Swpaul	 * If stdin is not associated with a keyboard, the following ioctl
106762672Swpaul	 * will fail.
1068212156Syongari	 */
1069212156Syongari	if (ioctl(0, KDGKBINFO, &info) == -1) {
1070212156Syongari		warn("unable to obtain keyboard information");
1071212156Syongari		return;
1072212156Syongari	}
1073212156Syongari#if 1
107462672Swpaul	printf("kbd%d\n", info.kb_index);
107562672Swpaul	printf("    %.*s%d, type:%s (%d)\n",
107662672Swpaul		(int)sizeof(info.kb_name), info.kb_name, info.kb_unit,
107762672Swpaul		get_kbd_type_name(info.kb_type), info.kb_type);
1078144243Sobrien#endif
107972197Swpaul	if (ioctl(0, CONS_RELKBD, 0) == -1)
108072197Swpaul		warn("unable to release the keyboard");
108172197Swpaul}
108272197Swpaul
108372197Swpaul
108472197Swpaulvoid
108572197Swpaulusage()
108672197Swpaul{
108772197Swpaul	fprintf(stderr, "%s\n%s\n%s\n",
108872197Swpaul"usage: kbdcontrol [-dFKix] [-b duration.pitch | [quiet.]belltype]",
108972197Swpaul"                  [-r delay.repeat | speed] [-l mapfile] [-f # string]",
109072197Swpaul"                  [-k device] [-L mapfile]");
109172197Swpaul	exit(1);
109272197Swpaul}
109372197Swpaul
109489296Swpaul
109589296Swpaulint
109690328Sambriskomain(int argc, char **argv)
109772197Swpaul{
109889296Swpaul	int		opt;
109990328Sambrisko
110090328Sambrisko	while((opt = getopt(argc, argv, "b:df:iKk:Fl:L:r:x")) != -1)
110189296Swpaul		switch(opt) {
1102109061Smbr		case 'b':
1103109061Smbr			set_bell_values(optarg);
1104109061Smbr			break;
1105109061Smbr		case 'd':
1106109061Smbr			print_keymap();
1107109061Smbr			break;
1108109061Smbr		case 'l':
1109109061Smbr			load_keymap(optarg, 0);
1110109061Smbr			break;
1111109061Smbr		case 'L':
1112109061Smbr			load_keymap(optarg, 1);
1113109061Smbr			break;
1114109061Smbr		case 'f':
1115109061Smbr			set_functionkey(optarg,
1116109061Smbr			    nextarg(argc, argv, &optind, 'f'));
1117109061Smbr			break;
1118109061Smbr		case 'F':
1119109061Smbr			load_default_functionkeys();
1120109061Smbr			break;
1121109061Smbr		case 'i':
1122109061Smbr			show_kbd_info();
1123109061Smbr			break;
1124109061Smbr		case 'K':
1125109061Smbr			release_keyboard();
1126109061Smbr			break;
112772197Swpaul		case 'k':
112872197Swpaul			set_keyboard(optarg);
112972197Swpaul			break;
113062672Swpaul		case 'r':
113162672Swpaul			set_keyrates(optarg);
113262672Swpaul			break;
1133212157Syongari		case 'x':
1134212157Syongari			hex = 1;
1135212109Syongari			break;
1136212109Syongari		default:
1137112872Snjl			usage();
113850974Swpaul		}
1139147256Sbrooks	if ((optind != argc) || (argc == 1))
1140147256Sbrooks		usage();
1141150583Sjhb	exit(0);
1142147256Sbrooks}
1143147256Sbrooks