kbd_wscons.c revision 1.1
1/*	$OpenBSD: kbd_wscons.c,v 1.1 2001/03/08 08:00:16 maja Exp $ */
2
3/*
4 * Copyright (c) 2001 Mats O Jansson.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by Mats O Jansson.
17 * 4. The name of the author may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <err.h>
33#include <errno.h>
34#include <kvm.h>
35#include <fcntl.h>
36#include <limits.h>
37#include <nlist.h>
38#include <stdio.h>
39#include <sys/ioctl.h>
40#include <sys/time.h>
41#include <dev/wscons/wsconsio.h>
42#include <dev/wscons/wsksymdef.h>
43
44#define	NUM_KBD	10
45
46#define SA_PCKBD 0
47#define SA_UKBD  1
48#define SA_AKBD	 2
49
50struct nlist nl[] = {
51	{ "_pckbd_keydesctab" },
52	{ "_ukbd_keydesctab" },
53	{ "_akbd_keydesctab" },
54	{ NULL },
55};
56
57char *kbtype_tab[] = {
58	"pc-xt/pc-at",
59	"usb",
60	"adb",
61};
62
63struct nameint {
64	int value;
65	char *name;
66};
67
68struct nameint kbdenc_tab[] = {
69	KB_ENCTAB
70	,
71	{ 0, 0 }
72};
73
74struct nameint kbdvar_tab[] = {
75	KB_VARTAB
76	,
77	{ 0, 0 }
78};
79
80extern char *__progname;
81
82void
83kbd_show_enc(kd, idx)
84	kvm_t *kd;
85	int idx;
86{
87	struct wscons_keydesc r;
88	unsigned long p;
89	struct nameint *n;
90
91	printf("tables available for %s keyboard:\nencoding\n\n",
92	       kbtype_tab[idx]);
93	p = nl[idx].n_value;
94	kvm_read(kd, p, &r, sizeof(r));
95	while (r.name != 0) {
96		n = &kbdenc_tab[0];
97		while(n->value) {
98			if (n->value == KB_ENCODING(r.name)) {
99				printf("%s",n->name);
100			}
101			n++;
102		}
103		n = &kbdvar_tab[0];
104		while(n->value) {
105			if ((n->value & KB_VARIANT(r.name)) == n->value) {
106				printf(".%s",n->name);
107			}
108			n++;
109		}
110		printf("\n");
111		p += sizeof(r);
112		kvm_read(kd, p, &r, sizeof(r));
113	}
114	printf("\n");
115}
116
117void
118kbd_list()
119{
120	int	fd, i, kbtype, ret;
121	kvm_t	*kd;
122	char	device[sizeof "/dev/wskbd00"];
123	char	errbuf[_POSIX2_LINE_MAX];
124	int	pc_kbd = 0;
125	int	usb_kbd = 0;
126	int	adb_kbd = 0;
127
128	/* Go through all keyboards. */
129	for (i = 0; i < NUM_KBD; i++) {
130		(void) sprintf(device, "/dev/wskbd%d", i);
131		fd = open(device, O_WRONLY);
132		if (fd < 0)
133			fd = open(device, O_RDONLY);
134		if (fd >= 0) {
135			if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0)
136				err(1, "WDKBDIO_GTYPE");
137			if ((kbtype == WSKBD_TYPE_PC_XT) ||
138			    (kbtype == WSKBD_TYPE_PC_AT))
139		  		pc_kbd++;
140			if (kbtype == WSKBD_TYPE_USB)
141				usb_kbd++;
142			if (kbtype == WSKBD_TYPE_ADB)
143				adb_kbd++;
144			close(fd);
145		}
146	}
147
148	if ((kd = kvm_openfiles(NULL,NULL,NULL,O_RDONLY, errbuf)) == 0)
149		errx(1, "kvm_openfiles: %s", errbuf);
150
151	if ((ret = kvm_nlist(kd, nl)) == -1)
152		errx(1, "kvm_nlist: %s", kvm_geterr(kd));
153
154	if (pc_kbd > 0)
155		kbd_show_enc(kd, SA_PCKBD);
156
157	if (usb_kbd > 0)
158		kbd_show_enc(kd, SA_UKBD);
159
160	if (adb_kbd > 0)
161		kbd_show_enc(kd, SA_AKBD);
162
163	kvm_close(kd);
164}
165
166void
167kbd_set(name, verbose)
168	char *name;
169	int verbose;
170{
171	char	buf[_POSIX2_LINE_MAX];
172	char	*c,*b;
173	struct nameint *n;
174	int	map = 0,v,i,fd;
175	char	device[sizeof "/dev/wskbd00"];
176
177	c = name;
178	b = buf;
179	while((*c != '.') && (*c != '\0')) {
180		*b++ = *c++;
181	}
182	*b = '\0';
183	n = &kbdenc_tab[0];
184	while(n->value) {
185		if (strcmp(n->name,buf) == 0) {
186			map = n->value;
187		}
188		n++;
189	}
190	if (map == 0)
191		errx(1, "unknown encodeing %s", buf);
192	while(*c == '.') {
193		b = buf;
194		c++;
195		while((*c != '.') && (*c != '\0')) {
196			*b++ = *c++;
197		}
198		*b = '\0';
199		v = 0;
200		n = &kbdvar_tab[0];
201		while(n->value) {
202			if (strcmp(n->name,buf) == 0) {
203				v = n->value;
204			}
205			n++;
206		}
207		if (v == 0)
208			errx(1, "unknown variant %s", buf);
209		map |= v;
210	}
211
212	/* Go through all keyboards. */
213	v = 0;
214	for (i = 0; i < NUM_KBD; i++) {
215		(void) sprintf(device, "/dev/wskbd%d", i);
216		fd = open(device, O_WRONLY);
217		if (fd < 0)
218			fd = open(device, O_RDONLY);
219		if (fd >= 0) {
220			if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) {
221				if (errno == EINVAL) {
222					fprintf(stderr, "%s: unsupported encoding %s on %s\n",
223						__progname, name, device);
224				} else {
225					err(1, "WDKBDIO_SETENCODING: %s", device);
226				}
227				v--;
228			}
229			v++;
230			close(fd);
231		}
232	}
233
234	if (verbose && v > 0)
235		fprintf(stderr, "keyboard mapping set to %s\n", name);
236}
237