xref: /openbsd/sbin/wsconsctl/util.c (revision db3296cf)
1 /*	$OpenBSD: util.c,v 1.22 2003/06/17 21:21:26 miod Exp $ */
2 /*	$NetBSD: util.c,v 1.8 2000/03/14 08:11:53 sato Exp $ */
3 
4 /*-
5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Juergen Hannken-Illjes.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <sys/time.h>
41 #include <dev/wscons/wsconsio.h>
42 #include <dev/wscons/wsksymdef.h>
43 #include <err.h>
44 #include <string.h>
45 #include <stdio.h>
46 #include <unistd.h>
47 #include "wsconsctl.h"
48 
49 #define TABLEN(t)		(sizeof(t)/sizeof(t[0]))
50 
51 extern struct wskbd_map_data kbmap;	/* from keyboard.c */
52 extern struct wskbd_map_data newkbmap;	/* from map_parse.y */
53 
54 struct nameint {
55 	int value;
56 	char *name;
57 };
58 
59 static const struct nameint kbtype_tab[] = {
60 	{ WSKBD_TYPE_LK201,	"lk201" },
61 	{ WSKBD_TYPE_LK401,	"lk401" },
62 	{ WSKBD_TYPE_PC_XT,	"pc-xt" },
63 	{ WSKBD_TYPE_PC_AT,	"pc-at" },
64 	{ WSKBD_TYPE_USB,	"usb" },
65 	{ WSKBD_TYPE_NEXT,	"NeXT" },
66 	{ WSKBD_TYPE_HPC_KBD,	"hpc-kbd" },
67 	{ WSKBD_TYPE_HPC_BTN,	"hpc-btn" },
68 	{ WSKBD_TYPE_ADB,	"adb" },
69 	{ WSKBD_TYPE_SUN,	"sun" },
70 	{ WSKBD_TYPE_SUN5,	"sun5" },
71 	{ WSKBD_TYPE_HIL,	"hil" }
72 };
73 
74 static const struct nameint mstype_tab[] = {
75 	{ WSMOUSE_TYPE_VSXXX,	"dec-tc" },
76 	{ WSMOUSE_TYPE_PS2,	"ps2" },
77 	{ WSMOUSE_TYPE_USB,	"usb" },
78 	{ WSMOUSE_TYPE_LMS,	"lms" },
79 	{ WSMOUSE_TYPE_MMS,	"mms" },
80 	{ WSMOUSE_TYPE_TPANEL,	"touch-pannel" },
81 	{ WSMOUSE_TYPE_NEXT,	"NeXT" },
82 	{ WSMOUSE_TYPE_ARCHIMEDES, "archimedes" },
83 	{ WSMOUSE_TYPE_ADB,	"adb" },
84 	{ WSMOUSE_TYPE_HIL,	"hil" }
85 };
86 
87 static const struct nameint dpytype_tab[] = {
88 	{ WSDISPLAY_TYPE_UNKNOWN,	"unknown" },
89 	{ WSDISPLAY_TYPE_PM_MONO,	"dec-pm-mono" },
90 	{ WSDISPLAY_TYPE_PM_COLOR,	"dec-pm-color" },
91 	{ WSDISPLAY_TYPE_CFB,		"dec-cfb" },
92 	{ WSDISPLAY_TYPE_XCFB,		"dec-xcfb" },
93 	{ WSDISPLAY_TYPE_MFB,		"dec-mfb" },
94 	{ WSDISPLAY_TYPE_SFB,		"dec-sfb" },
95 	{ WSDISPLAY_TYPE_ISAVGA,	"vga-isa" },
96 	{ WSDISPLAY_TYPE_PCIVGA,	"vga-pci" },
97 	{ WSDISPLAY_TYPE_TGA,		"dec-tga-pci" },
98 	{ WSDISPLAY_TYPE_SFBP,		"dec-sfb+" },
99 	{ WSDISPLAY_TYPE_PCIMISC,	"generic-pci" },
100 	{ WSDISPLAY_TYPE_NEXTMONO,	"next-mono" },
101 	{ WSDISPLAY_TYPE_PX,		"dex-px" },
102 	{ WSDISPLAY_TYPE_PXG,		"dex-pxg" },
103 	{ WSDISPLAY_TYPE_TX,		"dex-tx" },
104 	{ WSDISPLAY_TYPE_HPCFB,		"generic-hpc" },
105 	{ WSDISPLAY_TYPE_VIDC,		"arm-vidc" },
106 	{ WSDISPLAY_TYPE_SPX,		"dec-spx" },
107 	{ WSDISPLAY_TYPE_GPX,		"dec-gpx" },
108 	{ WSDISPLAY_TYPE_LCG,		"dec-lcg" },
109 	{ WSDISPLAY_TYPE_VAX_MONO,	"dec-mono" },
110 	{ WSDISPLAY_TYPE_SB_P9100,	"p9100" },
111 	{ WSDISPLAY_TYPE_EGA,		"ega" },
112 	{ WSDISPLAY_TYPE_DCPVR,		"powervr" },
113 	{ WSDISPLAY_TYPE_SUN24,		"sun24" },
114 	{ WSDISPLAY_TYPE_SUNBW,		"sunbw" },
115 	{ WSDISPLAY_TYPE_STI,		"hp-sti" },
116 	{ WSDISPLAY_TYPE_SUNCG3,	"suncg3" },
117 	{ WSDISPLAY_TYPE_SUNCG6,	"suncg6" },
118 	{ WSDISPLAY_TYPE_SUNFFB,	"sunffb" },
119 	{ WSDISPLAY_TYPE_SUNCG14,	"suncg14" },
120 	{ WSDISPLAY_TYPE_SUNCG2,	"suncg2" },
121 	{ WSDISPLAY_TYPE_SUNCG4,	"suncg4" },
122 	{ WSDISPLAY_TYPE_SUNCG8,	"suncg8" },
123 	{ WSDISPLAY_TYPE_SUNTCX,	"suntcx" },
124 	{ WSDISPLAY_TYPE_AGTEN,		"agten" },
125 	{ WSDISPLAY_TYPE_XVIDEO,	"xvideo" },
126 	{ WSDISPLAY_TYPE_SUNCG12,	"suncg12" },
127 	{ WSDISPLAY_TYPE_MGX,		"mgx" },
128 	{ WSDISPLAY_TYPE_SB_P9000,	"p9000" },
129 };
130 
131 static const struct nameint kbdenc_tab[] = {
132 	KB_ENCTAB
133 };
134 
135 static const struct nameint kbdvar_tab[] = {
136 	KB_VARTAB
137 };
138 
139 char *int2name(int, int, const struct nameint *, int);
140 int name2int(char *, const struct nameint *, int);
141 void print_kmap(struct wskbd_map_data *);
142 
143 struct field *
144 field_by_name(struct field *field_tab, char *name)
145 {
146 	const char *p = strchr(name, '.');
147 
148 	if (!p++)
149 		errx(1, "%s: illegal variable name", name);
150 
151 	for (; field_tab->name; field_tab++)
152 		if (strcmp(field_tab->name, p) == 0)
153 			return (field_tab);
154 
155 	errx(1, "%s: not found", name);
156 }
157 
158 struct field *
159 field_by_value(struct field *field_tab, void *addr)
160 {
161 	for (; field_tab->name; field_tab++)
162 		if (field_tab->valp == addr)
163 			return (field_tab);
164 
165 	errx(1, "internal error: field_by_value: not found");
166 }
167 
168 char *
169 int2name(int val, int uflag, const struct nameint *tab, int len)
170 {
171 	static char tmp[20];
172 	int i;
173 
174 	for (i = 0; i < len; i++)
175 		if (tab[i].value == val)
176 			return(tab[i].name);
177 
178 	if (uflag) {
179 		snprintf(tmp, sizeof(tmp), "unknown_%d", val);
180 		return(tmp);
181 	} else
182 		return(NULL);
183 }
184 
185 int
186 name2int(char *val, const struct nameint *tab, int len)
187 {
188 	int i;
189 
190 	for (i = 0; i < len; i++)
191 		if (strcmp(tab[i].name, val) == 0)
192 			return(tab[i].value);
193 	return(-1);
194 }
195 
196 void
197 pr_field(const char *pre, struct field *f, const char *sep)
198 {
199 	struct field_pc *pc;
200 	u_int flags;
201 	int i, n;
202 	char *p;
203 
204 	if (sep)
205 		printf("%s.%s%s", pre, f->name, sep);
206 
207 	switch (f->format) {
208 	case FMT_UINT:
209 		printf("%u", *((u_int *) f->valp));
210 		break;
211 	case FMT_INT:
212 		printf("%d", *((int *) f->valp));
213 		break;
214 	case FMT_BOOL:
215 		printf("%s", *((u_int *) f->valp)? "on" : "off");
216 		break;
217 	case FMT_PC:
218 		pc = f->valp;
219 		i = pc->max - pc->min;
220 		n = pc->cur - pc->min;
221 		printf("%u.%02u%%", n * 100 / i, ((n * 100) % i) * 100 / i);
222 		break;
223 	case FMT_KBDTYPE:
224 		p = int2name(*((u_int *) f->valp), 1,
225 			     kbtype_tab, TABLEN(kbtype_tab));
226 		printf("%s", p);
227 		break;
228 	case FMT_MSTYPE:
229 		p = int2name(*((u_int *) f->valp), 1,
230 			     mstype_tab, TABLEN(mstype_tab));
231 		printf("%s", p);
232 		break;
233 	case FMT_DPYTYPE:
234 		p = int2name(*((u_int *) f->valp), 1,
235 			     dpytype_tab, TABLEN(dpytype_tab));
236 		printf("%s", p);
237 		break;
238 	case FMT_KBDENC:
239 		p = int2name(KB_ENCODING(*((u_int *) f->valp)), 1,
240 			     kbdenc_tab, TABLEN(kbdenc_tab));
241 		printf("%s", p);
242 
243 		flags = KB_VARIANT(*((u_int *) f->valp));
244 		for (i = 0; i < 32; i++) {
245 			if (!(flags & (1 << i)))
246 				continue;
247 			p = int2name(flags & (1 << i), 1,
248 				     kbdvar_tab, TABLEN(kbdvar_tab));
249 			printf(".%s", p);
250 		}
251 		break;
252 	case FMT_KBMAP:
253 		print_kmap((struct wskbd_map_data *) f->valp);
254 		break;
255 	default:
256 		errx(1, "internal error: pr_field: no format %d", f->format);
257 		break;
258 	}
259 
260 	printf("\n");
261 }
262 
263 void
264 rd_field(struct field *f, char *val, int merge)
265 {
266 	struct wscons_keymap *mp;
267 	struct field_pc *pc;
268 	u_int u, r, fr;
269 	char *p;
270 	int i;
271 
272 	switch (f->format) {
273 	case FMT_UINT:
274 		if (sscanf(val, "%u", &u) != 1)
275 			errx(1, "%s: not a number", val);
276 		if (merge)
277 			*((u_int *) f->valp) += u;
278 		else
279 			*((u_int *) f->valp) = u;
280 		break;
281 	case FMT_INT:
282 		if (sscanf(val, "%d", &i) != 1)
283 			errx(1, "%s: not a number", val);
284 		if (merge)
285 			*((int *) f->valp) += i;
286 		else
287 			*((int *) f->valp) = i;
288 		break;
289 	case FMT_BOOL:
290 		if (*val != 'o' || (val[1] != 'n' &&
291 		    (val[1] != 'f' || val[2] != 'f')))
292 			errx(1, "%s: invalid value (on/off)", val);
293 		*((u_int *) f->valp) = val[1] == 'n'? 1 : 0;
294 		break;
295 	case FMT_PC:
296 		fr = 0;
297 		if ((i = sscanf(val, "%u.%u%%", &u, &fr)) != 2 && i != 1)
298 			errx(1, "%s: not a valid number", val);
299 		pc = f->valp;
300 		r = pc->max - pc->min;
301 		i = pc->min + (r * u) / 100 + (r * fr) / 100 / 100;
302 		if (merge == '+')
303 			pc->cur += i;
304 		else if (merge == '-')
305 			pc->cur -= i;
306 		else
307 			pc->cur = i;
308 		if (pc->cur > pc->max)
309 			pc->cur = pc->max;
310 		if (pc->cur < pc->min)
311 			pc->cur = pc->min;
312 		break;
313 	case FMT_KBDENC:
314 		p = strchr(val, '.');
315 		if (p != NULL)
316 			*p++ = '\0';
317 
318 		i = name2int(val, kbdenc_tab, TABLEN(kbdenc_tab));
319 		if (i == -1)
320 			errx(1, "%s: not a valid encoding", val);
321 		*((u_int *) f->valp) = i;
322 
323 		while (p) {
324 			val = p;
325 			p = strchr(p, '.');
326 			if (p != NULL)
327 				*p++ = '\0';
328 			i = name2int(val, kbdvar_tab, TABLEN(kbdvar_tab));
329 			if (i == -1)
330 				errx(1, "%s: not a valid variant", val);
331 			*((u_int *) f->valp) |= i;
332 		}
333 		break;
334 	case FMT_KBMAP:
335 		if (! merge)
336 			kbmap.maplen = 0;
337 		map_scan_setinput(val);
338 		yyparse();
339 		if (merge) {
340 			if (newkbmap.maplen < kbmap.maplen)
341 				newkbmap.maplen = kbmap.maplen;
342 			for (i = 0; i < kbmap.maplen; i++) {
343 				mp = newkbmap.map + i;
344 				if (mp->command == KS_voidSymbol &&
345 				    mp->group1[0] == KS_voidSymbol &&
346 				    mp->group1[1] == KS_voidSymbol &&
347 				    mp->group2[0] == KS_voidSymbol &&
348 				    mp->group2[1] == KS_voidSymbol)
349 					*mp = kbmap.map[i];
350 			}
351 		}
352 		kbmap.maplen = newkbmap.maplen;
353 		bcopy(newkbmap.map, kbmap.map,
354 		      kbmap.maplen*sizeof(struct wscons_keymap));
355 		break;
356 	default:
357 		errx(1, "internal error: rd_field: no format %d", f->format);
358 		break;
359 	}
360 }
361 
362 void
363 print_kmap(struct wskbd_map_data *map)
364 {
365 	struct wscons_keymap *mp;
366 	int i;
367 
368 	for (i = 0; i < map->maplen; i++) {
369 		mp = map->map + i;
370 
371 		if (mp->command == KS_voidSymbol &&
372 		    mp->group1[0] == KS_voidSymbol &&
373 		    mp->group1[1] == KS_voidSymbol &&
374 		    mp->group2[0] == KS_voidSymbol &&
375 		    mp->group2[1] == KS_voidSymbol)
376 			continue;
377 		printf("\n");
378 		printf("keycode %u =", i);
379 		if (mp->command != KS_voidSymbol)
380 			printf(" %s", ksym2name(mp->command));
381 		printf(" %s", ksym2name(mp->group1[0]));
382 		if (mp->group1[0] != mp->group1[1] ||
383 		    mp->group1[0] != mp->group2[0] ||
384 		    mp->group1[0] != mp->group2[1]) {
385 			printf(" %s", ksym2name(mp->group1[1]));
386 			if (mp->group1[0] != mp->group2[0] ||
387 			    mp->group1[1] != mp->group2[1]) {
388 				printf(" %s", ksym2name(mp->group2[0]));
389 				printf(" %s", ksym2name(mp->group2[1]));
390 			}
391 		}
392 	}
393 }
394