GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/kbd/kbd_wscons.c Lines: 0 102 0.0 %
Date: 2017-11-07 Branches: 0 90 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: kbd_wscons.c,v 1.32 2016/10/03 13:03:49 jca 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 <fcntl.h>
35
#include <limits.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
41
#define	NUM_KBD	10
42
43
char *kbtype_tab[] = {
44
	"pc-xt/pc-at",
45
	"usb",
46
	"adb",
47
	"lk201",
48
	"sun",
49
	"sun5",
50
	"hil",
51
	"gsc",
52
	"sgi"
53
};
54
enum {	SA_PCKBD,
55
	SA_UKBD,
56
	SA_AKBD,
57
	SA_LKKBD,
58
	SA_SUNKBD,
59
	SA_SUN5KBD,
60
	SA_HILKBD,
61
	SA_GSCKBD,
62
	SA_SGIKBD,
63
64
	SA_MAX
65
};
66
67
struct nameint {
68
	int value;
69
	char *name;
70
};
71
72
struct nameint kbdenc_tab[] = {
73
	KB_ENCTAB
74
	,
75
	{ 0, NULL }
76
};
77
78
struct nameint kbdvar_tab[] = {
79
	KB_VARTAB
80
	,
81
	{ 0, NULL }
82
};
83
84
extern char *__progname;
85
86
void	kbd_show_enc(struct wskbd_encoding_data *encs, int idx);
87
void	kbd_get_encs(int fd, struct wskbd_encoding_data *encs);
88
void	kbd_list(void);
89
void	kbd_set(char *name, int verbose);
90
91
void
92
kbd_show_enc(struct wskbd_encoding_data *encs, int idx)
93
{
94
	int found;
95
	kbd_t encoding, variant;
96
	struct nameint *n;
97
	int i;
98
99
	printf("tables available for %s keyboard:\nencoding\n\n",
100
	    kbtype_tab[idx]);
101
102
	for (i = 0; i < encs->nencodings; i++) {
103
		found = 0;
104
		encoding = encs->encodings[i];
105
		for (n = &kbdenc_tab[0]; n->value; n++) {
106
			if (n->value == KB_ENCODING(encoding)) {
107
				printf("%s", n->name);
108
				found++;
109
			}
110
		}
111
		if (found == 0)
112
			printf("<encoding 0x%04x>", KB_ENCODING(encoding));
113
		found = 0;
114
		variant = KB_VARIANT(encoding);
115
		for (n = &kbdvar_tab[0]; n->value; n++) {
116
			if ((n->value & KB_VARIANT(encoding)) == n->value) {
117
				printf(".%s", n->name);
118
				variant &= ~n->value;
119
			}
120
		}
121
		if (variant != 0)
122
			printf(".<variant 0x%08x>", variant);
123
		printf("\n");
124
	}
125
	printf("\n");
126
}
127
128
void
129
kbd_get_encs(int fd, struct wskbd_encoding_data *encs)
130
{
131
	int nencodings = 64;
132
133
	encs->nencodings = nencodings;
134
	while (encs->nencodings == nencodings) {
135
		encs->encodings = reallocarray(encs->encodings,
136
		    encs->nencodings, sizeof(kbd_t));
137
		if (encs->encodings == NULL)
138
			err(1, NULL);
139
		if (ioctl(fd, WSKBDIO_GETENCODINGS, encs) < 0)
140
			err(1, "WSKBDIO_GETENCODINGS");
141
		if (encs->nencodings == nencodings) {
142
			nencodings *= 2;
143
			encs->nencodings = nencodings;
144
		}
145
	}
146
}
147
148
void
149
kbd_list(void)
150
{
151
	int	kbds[SA_MAX];
152
	struct wskbd_encoding_data encs[SA_MAX];
153
	int	fd, i, kbtype, t;
154
	char	device[PATH_MAX];
155
156
	memset(kbds, 0, sizeof(kbds));
157
	memset(encs, 0, sizeof(encs));
158
159
	/* Go through all keyboards. */
160
	for (i = 0; i < NUM_KBD; i++) {
161
		(void) snprintf(device, sizeof device, "/dev/wskbd%d", i);
162
		fd = open(device, O_WRONLY);
163
		if (fd < 0)
164
			fd = open(device, O_RDONLY);
165
		if (fd >= 0) {
166
			if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0)
167
				err(1, "WSKBDIO_GTYPE");
168
			switch (kbtype) {
169
			case WSKBD_TYPE_PC_XT:
170
			case WSKBD_TYPE_PC_AT:
171
				t = SA_PCKBD;
172
				break;
173
			case WSKBD_TYPE_USB:
174
				t = SA_UKBD;
175
				break;
176
			case WSKBD_TYPE_ADB:
177
				t = SA_AKBD;
178
				break;
179
			case WSKBD_TYPE_LK201:
180
			case WSKBD_TYPE_LK401:
181
				t = SA_LKKBD;
182
				break;
183
			case WSKBD_TYPE_SUN:
184
				t = SA_SUNKBD;
185
				break;
186
			case WSKBD_TYPE_SUN5:
187
				t = SA_SUN5KBD;
188
				break;
189
			case WSKBD_TYPE_HIL:
190
				t = SA_HILKBD;
191
				break;
192
			case WSKBD_TYPE_GSC:
193
				t = SA_GSCKBD;
194
				break;
195
			case WSKBD_TYPE_SGI:
196
				t = SA_SGIKBD;
197
				break;
198
			default:
199
				t = SA_MAX;
200
				break;
201
			};
202
203
			if (t != SA_MAX) {
204
				kbds[t]++;
205
				if (encs[t].encodings == NULL)
206
					kbd_get_encs(fd, &encs[t]);
207
			}
208
			close(fd);
209
		}
210
	}
211
212
	for (i = 0; i < SA_MAX; i++)
213
		if (kbds[i] != 0)
214
			kbd_show_enc(&encs[i], i);
215
216
	for (i = 0; i < SA_MAX; i++)
217
		free(encs[i].encodings);
218
}
219
220
void
221
kbd_set(char *name, int verbose)
222
{
223
	char	buf[LINE_MAX], *c, *b, device[sizeof "/dev/wskbd00"];
224
	int	map = 0, v, i, fd;
225
	struct nameint *n;
226
227
	c = name;
228
	b = buf;
229
	while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1)
230
		*b++ = *c++;
231
	*b = '\0';
232
	n = &kbdenc_tab[0];
233
	while (n->value) {
234
		if (strcmp(n->name, buf) == 0)
235
			map = n->value;
236
		n++;
237
	}
238
	if (map == 0)
239
		errx(1, "unknown encoding %s", buf);
240
	while (*c == '.') {
241
		b = buf;
242
		c++;
243
		while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1)
244
			*b++ = *c++;
245
		*b = '\0';
246
		v = 0;
247
		for (n = &kbdvar_tab[0]; n->value; n++) {
248
			if (strcmp(n->name, buf) == 0)
249
				v = n->value;
250
		}
251
		if (v == 0)
252
			errx(1, "unknown variant %s", buf);
253
		map |= v;
254
	}
255
256
	/* Go through all keyboards. */
257
	v = 0;
258
	for (i = 0; i < NUM_KBD; i++) {
259
		(void) snprintf(device, sizeof device, "/dev/wskbd%d", i);
260
		fd = open(device, O_WRONLY);
261
		if (fd < 0)
262
			fd = open(device, O_RDONLY);
263
		if (fd >= 0) {
264
			if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) {
265
				if (errno == EINVAL) {
266
					fprintf(stderr,
267
					    "%s: unsupported encoding %s on %s\n",
268
					    __progname, name, device);
269
				} else
270
					err(1, "WSKBDIO_SETENCODING: %s", device);
271
				v--;
272
			}
273
			v++;
274
			close(fd);
275
		}
276
	}
277
278
	if (verbose && v > 0)
279
		fprintf(stderr, "kbd: keyboard mapping set to %s\n", name);
280
}