GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/kbd/kbd_wscons.c Lines: 0 115 0.0 %
Date: 2016-12-06 Branches: 0 78 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: kbd_wscons.c,v 1.28 2015/01/16 06:39:59 deraadt 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
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include <sys/ioctl.h>
28
#include <sys/time.h>
29
#include <dev/wscons/wsconsio.h>
30
#include <dev/wscons/wsksymdef.h>
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 <string.h>
40
#include <unistd.h>
41
42
#define	NUM_KBD	10
43
44
char *kbtype_tab[] = {
45
	"pc-xt/pc-at",
46
	"usb",
47
	"adb",
48
	"lk201",
49
	"sun",
50
	"sun5",
51
	"hil",
52
	"gsc",
53
	"sgi"
54
};
55
enum {	SA_PCKBD,
56
	SA_UKBD,
57
	SA_AKBD,
58
	SA_LKKBD,
59
	SA_SUNKBD,
60
	SA_SUN5KBD,
61
	SA_HILKBD,
62
	SA_GSCKBD,
63
	SA_SGIKBD,
64
65
	SA_MAX
66
};
67
68
#ifndef NOKVM
69
struct nlist nl[] = {
70
	{ "_pckbd_keydesctab" },
71
	{ "_ukbd_keydesctab" },
72
	{ "_akbd_keydesctab" },
73
	{ "_lkkbd_keydesctab" },
74
	{ "_sunkbd_keydesctab" },
75
	{ "_sunkbd5_keydesctab" },
76
	{ "_hilkbd_keydesctab" },
77
	{ "_gsckbd_keydesctab" },
78
	{ "_wssgi_keydesctab" },
79
	{ NULL },
80
};
81
#endif /* NOKVM */
82
83
#ifndef NOKVM
84
int rebuild = 0;
85
#endif
86
87
struct nameint {
88
	int value;
89
	char *name;
90
};
91
92
struct nameint kbdenc_tab[] = {
93
	KB_ENCTAB
94
	,
95
	{ 0, NULL }
96
};
97
98
struct nameint kbdvar_tab[] = {
99
	KB_VARTAB
100
	,
101
	{ 0, NULL }
102
};
103
104
extern char *__progname;
105
106
void	kbd_show_enc(kvm_t *kd, int idx);
107
void	kbd_list(void);
108
void	kbd_set(char *name, int verbose);
109
110
void
111
kbd_show_enc(kvm_t *kd, int idx)
112
{
113
#ifndef NOKVM
114
	struct wscons_keydesc r;
115
	unsigned long p;
116
	int found;
117
	u_int32_t variant;
118
	struct nameint *n;
119
#else
120
	int i;
121
#endif /* NOKVM */
122
123
#ifndef NOKVM
124
	p = nl[idx].n_value;
125
	if (p == 0) {
126
		printf("no tables available for %s keyboard\n\n",
127
		    kbtype_tab[idx]);
128
		return;
129
	}
130
#endif
131
132
	printf("tables available for %s keyboard:\nencoding\n\n",
133
	    kbtype_tab[idx]);
134
135
#ifdef NOKVM
136
	for (i = 0; kbdenc_tab[i].value; i++)
137
		printf("%s\n", kbdenc_tab[i].name);
138
#else
139
	kvm_read(kd, p, &r, sizeof(r));
140
	while (r.name != 0) {
141
		n = &kbdenc_tab[0];
142
		found = 0;
143
		while (n->value) {
144
			if (n->value == KB_ENCODING(r.name)) {
145
				printf("%s",n->name);
146
				found++;
147
			}
148
			n++;
149
		}
150
		if (found == 0) {
151
			printf("<encoding 0x%04x>",KB_ENCODING(r.name));
152
			rebuild++;
153
		}
154
		n = &kbdvar_tab[0];
155
		found = 0;
156
		variant = KB_VARIANT(r.name);
157
		while (n->value) {
158
			if ((n->value & KB_VARIANT(r.name)) == n->value) {
159
				printf(".%s",n->name);
160
				variant &= ~n->value;
161
			}
162
			n++;
163
		}
164
		if (variant != 0) {
165
			printf(".<variant 0x%08x>",variant);
166
			rebuild++;
167
		}
168
		printf("\n");
169
		p += sizeof(r);
170
		kvm_read(kd, p, &r, sizeof(r));
171
	}
172
#endif
173
	printf("\n");
174
}
175
176
void
177
kbd_list(void)
178
{
179
	int	kbds[SA_MAX];
180
	int	fd, i, kbtype;
181
	char	device[PATH_MAX];
182
	kvm_t	*kd = NULL;
183
#ifndef NOKVM
184
	char	errbuf[LINE_MAX];
185
#endif
186
187
	bzero(kbds, sizeof(kbds));
188
189
	/* Go through all keyboards. */
190
	for (i = 0; i < NUM_KBD; i++) {
191
		(void) snprintf(device, sizeof device, "/dev/wskbd%d", i);
192
		fd = open(device, O_WRONLY);
193
		if (fd < 0)
194
			fd = open(device, O_RDONLY);
195
		if (fd >= 0) {
196
			if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0)
197
				err(1, "WSKBDIO_GTYPE");
198
			switch (kbtype) {
199
			case WSKBD_TYPE_PC_XT:
200
			case WSKBD_TYPE_PC_AT:
201
				kbds[SA_PCKBD]++;
202
				break;
203
			case WSKBD_TYPE_USB:
204
				kbds[SA_UKBD]++;
205
				break;
206
			case WSKBD_TYPE_ADB:
207
				kbds[SA_AKBD]++;
208
				break;
209
			case WSKBD_TYPE_LK201:
210
			case WSKBD_TYPE_LK401:
211
				kbds[SA_LKKBD]++;
212
				break;
213
			case WSKBD_TYPE_SUN:
214
				kbds[SA_SUNKBD]++;
215
				break;
216
			case WSKBD_TYPE_SUN5:
217
				kbds[SA_SUN5KBD]++;
218
				break;
219
			case WSKBD_TYPE_HIL:
220
				kbds[SA_HILKBD]++;
221
				break;
222
			case WSKBD_TYPE_GSC:
223
				kbds[SA_GSCKBD]++;
224
				break;
225
			case WSKBD_TYPE_SGI:
226
				kbds[SA_SGIKBD]++;
227
				break;
228
			};
229
			close(fd);
230
		}
231
	}
232
233
#ifndef NOKVM
234
	if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL)
235
		errx(1, "kvm_openfiles: %s", errbuf);
236
237
	if (kvm_nlist(kd, nl) == -1)
238
		errx(1, "kvm_nlist: %s", kvm_geterr(kd));
239
#endif
240
241
	for (i = 0; i < SA_MAX; i++)
242
		if (kbds[i] != 0)
243
			kbd_show_enc(kd, i);
244
245
#ifndef NOKVM
246
	kvm_close(kd);
247
	if (rebuild > 0)
248
		printf("Unknown encoding or variant. kbd(8) needs to be rebuilt.\n");
249
#endif
250
}
251
252
void
253
kbd_set(char *name, int verbose)
254
{
255
	char	buf[LINE_MAX], *c, *b, device[sizeof "/dev/wskbd00"];
256
	int	map = 0, v, i, fd;
257
	struct nameint *n;
258
259
	c = name;
260
	b = buf;
261
	while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1)
262
		*b++ = *c++;
263
	*b = '\0';
264
	n = &kbdenc_tab[0];
265
	while (n->value) {
266
		if (strcmp(n->name, buf) == 0)
267
			map = n->value;
268
		n++;
269
	}
270
	if (map == 0)
271
		errx(1, "unknown encoding %s", buf);
272
	while (*c == '.') {
273
		b = buf;
274
		c++;
275
		while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1)
276
			*b++ = *c++;
277
		*b = '\0';
278
		v = 0;
279
		n = &kbdvar_tab[0];
280
		while (n->value) {
281
			if (strcmp(n->name, buf) == 0)
282
				v = n->value;
283
			n++;
284
		}
285
		if (v == 0)
286
			errx(1, "unknown variant %s", buf);
287
		map |= v;
288
	}
289
290
	/* Go through all keyboards. */
291
	v = 0;
292
	for (i = 0; i < NUM_KBD; i++) {
293
		(void) snprintf(device, sizeof device, "/dev/wskbd%d", i);
294
		fd = open(device, O_WRONLY);
295
		if (fd < 0)
296
			fd = open(device, O_RDONLY);
297
		if (fd >= 0) {
298
			if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) {
299
				if (errno == EINVAL) {
300
					fprintf(stderr,
301
					    "%s: unsupported encoding %s on %s\n",
302
					    __progname, name, device);
303
				} else
304
					err(1, "WSKBDIO_SETENCODING: %s", device);
305
				v--;
306
			}
307
			v++;
308
			close(fd);
309
		}
310
	}
311
312
	if (verbose && v > 0)
313
		fprintf(stderr, "kbd: keyboard mapping set to %s\n", name);
314
}