xref: /netbsd-src/sbin/wsconsctl/keyboard.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: keyboard.c,v 1.8 2006/02/05 18:11:46 jmmv Exp $ */
2 
3 /*-
4  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Juergen Hannken-Illjes.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/ioctl.h>
40 #include <sys/time.h>
41 
42 #include <dev/wscons/wsksymdef.h>
43 #include <dev/wscons/wsconsio.h>
44 
45 #include <err.h>
46 #include <errno.h>
47 #include <stdlib.h>
48 
49 #include "wsconsctl.h"
50 
51 static int kbtype;
52 static int keyclick;
53 static struct wskbd_bell_data bell;
54 static struct wskbd_bell_data dfbell;
55 static struct wscons_keymap mapdata[KS_NUMKEYCODES];
56 struct wskbd_map_data kbmap = /* used in map_parse.y and in util.c */
57     { KS_NUMKEYCODES, mapdata };
58 static struct wskbd_keyrepeat_data repeat;
59 static struct wskbd_keyrepeat_data dfrepeat;
60 static struct wskbd_scroll_data scroll;
61 static int ledstate;
62 static kbd_t kbdencoding;
63 static int havescroll = 1;
64 
65 struct field keyboard_field_tab[] = {
66     { "type",			&kbtype,	FMT_KBDTYPE,	FLG_RDONLY },
67     { "bell.pitch",		&bell.pitch,	FMT_UINT,	FLG_MODIFY },
68     { "bell.period",		&bell.period,	FMT_UINT,	FLG_MODIFY },
69     { "bell.volume",		&bell.volume,	FMT_UINT,	FLG_MODIFY },
70     { "bell.pitch.default",	&dfbell.pitch,	FMT_UINT,	FLG_MODIFY },
71     { "bell.period.default",	&dfbell.period,	FMT_UINT,	FLG_MODIFY },
72     { "bell.volume.default",	&dfbell.volume,	FMT_UINT,	FLG_MODIFY },
73     { "map",			&kbmap,		FMT_KBMAP,	FLG_MODIFY |
74     								FLG_NOAUTO },
75     { "repeat.del1",		&repeat.del1,	FMT_UINT,	FLG_MODIFY },
76     { "repeat.deln",		&repeat.delN,	FMT_UINT,	FLG_MODIFY },
77     { "repeat.del1.default",	&dfrepeat.del1,	FMT_UINT,	FLG_MODIFY },
78     { "repeat.deln.default",	&dfrepeat.delN,	FMT_UINT,	FLG_MODIFY },
79     { "ledstate",		&ledstate,	FMT_UINT,	0 },
80     { "encoding",		&kbdencoding,	FMT_KBDENC,	FLG_MODIFY },
81     { "keyclick",		&keyclick,	FMT_UINT,	FLG_MODIFY },
82     { "scroll.mode",		&scroll.mode,	FMT_UINT,	FLG_MODIFY },
83     { "scroll.modifier",	&scroll.modifier, FMT_UINT,	FLG_MODIFY },
84 };
85 
86 int keyboard_field_tab_len = sizeof(keyboard_field_tab) /
87 	sizeof(keyboard_field_tab[0]);
88 
89 void
90 keyboard_get_values(int fd)
91 {
92 
93 	if (field_by_value(&kbtype)->flags & FLG_GET)
94 		if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0)
95 			err(EXIT_FAILURE, "WSKBDIO_GTYPE");
96 
97 	bell.which = 0;
98 	if (field_by_value(&bell.pitch)->flags & FLG_GET)
99 		bell.which |= WSKBD_BELL_DOPITCH;
100 	if (field_by_value(&bell.period)->flags & FLG_GET)
101 		bell.which |= WSKBD_BELL_DOPERIOD;
102 	if (field_by_value(&bell.volume)->flags & FLG_GET)
103 		bell.which |= WSKBD_BELL_DOVOLUME;
104 	if (bell.which != 0 && ioctl(fd, WSKBDIO_GETBELL, &bell) < 0)
105 		err(EXIT_FAILURE, "WSKBDIO_GETBELL");
106 
107 	dfbell.which = 0;
108 	if (field_by_value(&dfbell.pitch)->flags & FLG_GET)
109 		dfbell.which |= WSKBD_BELL_DOPITCH;
110 	if (field_by_value(&dfbell.period)->flags & FLG_GET)
111 		dfbell.which |= WSKBD_BELL_DOPERIOD;
112 	if (field_by_value(&dfbell.volume)->flags & FLG_GET)
113 		dfbell.which |= WSKBD_BELL_DOVOLUME;
114 	if (dfbell.which != 0 &&
115 	    ioctl(fd, WSKBDIO_GETDEFAULTBELL, &dfbell) < 0)
116 		err(EXIT_FAILURE, "WSKBDIO_GETDEFAULTBELL");
117 
118 	if (field_by_value(&kbmap)->flags & FLG_GET) {
119 		kbmap.maplen = KS_NUMKEYCODES;
120 		if (ioctl(fd, WSKBDIO_GETMAP, &kbmap) < 0)
121 			err(EXIT_FAILURE, "WSKBDIO_GETMAP");
122 	}
123 
124 	repeat.which = 0;
125 	if (field_by_value(&repeat.del1)->flags & FLG_GET)
126 		repeat.which |= WSKBD_KEYREPEAT_DODEL1;
127 	if (field_by_value(&repeat.delN)->flags & FLG_GET)
128 		repeat.which |= WSKBD_KEYREPEAT_DODELN;
129 	if (repeat.which != 0 &&
130 	    ioctl(fd, WSKBDIO_GETKEYREPEAT, &repeat) < 0)
131 		err(EXIT_FAILURE, "WSKBDIO_GETKEYREPEAT");
132 
133 	dfrepeat.which = 0;
134 	if (field_by_value(&dfrepeat.del1)->flags & FLG_GET)
135 		dfrepeat.which |= WSKBD_KEYREPEAT_DODEL1;
136 	if (field_by_value(&dfrepeat.delN)->flags & FLG_GET)
137 		dfrepeat.which |= WSKBD_KEYREPEAT_DODELN;
138 	if (dfrepeat.which != 0 &&
139 	    ioctl(fd, WSKBDIO_GETKEYREPEAT, &dfrepeat) < 0)
140 		err(EXIT_FAILURE, "WSKBDIO_GETKEYREPEAT");
141 
142 	if (field_by_value(&ledstate)->flags & FLG_GET)
143 		if (ioctl(fd, WSKBDIO_GETLEDS, &ledstate) < 0)
144 			err(EXIT_FAILURE, "WSKBDIO_GETLEDS");
145 
146 	if (field_by_value(&kbdencoding)->flags & FLG_GET)
147 		if (ioctl(fd, WSKBDIO_GETENCODING, &kbdencoding) < 0)
148 			err(EXIT_FAILURE, "WSKBDIO_GETENCODING");
149 
150 	if (field_by_value(&keyclick)->flags & FLG_GET) {
151 		ioctl(fd, WSKBDIO_GETKEYCLICK, &keyclick);
152 		/* Optional; don't complain. */
153 	}
154 
155 	scroll.which = 0;
156 	if (field_by_value(&scroll.mode)->flags & FLG_GET)
157 		scroll.which |= WSKBD_SCROLL_DOMODE;
158 	if (field_by_value(&scroll.modifier)->flags & FLG_GET)
159 		scroll.which |= WSKBD_SCROLL_DOMODIFIER;
160 	if (scroll.which != 0) {
161 		if (ioctl(fd, WSKBDIO_GETSCROLL, &scroll) == -1) {
162 			if (errno != ENODEV)
163 				err(EXIT_FAILURE, "WSKBDIO_GETSCROLL");
164 			else
165 				havescroll = 0;
166 		}
167 	}
168 }
169 
170 void
171 keyboard_put_values(int fd)
172 {
173 
174 	bell.which = 0;
175 	if (field_by_value(&bell.pitch)->flags & FLG_SET)
176 		bell.which |= WSKBD_BELL_DOPITCH;
177 	if (field_by_value(&bell.period)->flags & FLG_SET)
178 		bell.which |= WSKBD_BELL_DOPERIOD;
179 	if (field_by_value(&bell.volume)->flags & FLG_SET)
180 		bell.which |= WSKBD_BELL_DOVOLUME;
181 	if (bell.which != 0 && ioctl(fd, WSKBDIO_SETBELL, &bell) < 0)
182 		err(EXIT_FAILURE, "WSKBDIO_SETBELL");
183 	if (bell.which & WSKBD_BELL_DOPITCH)
184 		pr_field(field_by_value(&bell.pitch), " -> ");
185 	if (bell.which & WSKBD_BELL_DOPERIOD)
186 		pr_field(field_by_value(&bell.period), " -> ");
187 	if (bell.which & WSKBD_BELL_DOVOLUME)
188 		pr_field(field_by_value(&bell.volume), " -> ");
189 
190 	dfbell.which = 0;
191 	if (field_by_value(&dfbell.pitch)->flags & FLG_SET)
192 		dfbell.which |= WSKBD_BELL_DOPITCH;
193 	if (field_by_value(&dfbell.period)->flags & FLG_SET)
194 		dfbell.which |= WSKBD_BELL_DOPERIOD;
195 	if (field_by_value(&dfbell.volume)->flags & FLG_SET)
196 		dfbell.which |= WSKBD_BELL_DOVOLUME;
197 	if (dfbell.which != 0 &&
198 	    ioctl(fd, WSKBDIO_SETDEFAULTBELL, &dfbell) < 0)
199 		err(EXIT_FAILURE, "WSKBDIO_SETDEFAULTBELL");
200 	if (dfbell.which & WSKBD_BELL_DOPITCH)
201 		pr_field(field_by_value(&dfbell.pitch), " -> ");
202 	if (dfbell.which & WSKBD_BELL_DOPERIOD)
203 		pr_field(field_by_value(&dfbell.period), " -> ");
204 	if (dfbell.which & WSKBD_BELL_DOVOLUME)
205 		pr_field(field_by_value(&dfbell.volume), " -> ");
206 
207 	if (field_by_value(&kbmap)->flags & FLG_SET) {
208 		if (ioctl(fd, WSKBDIO_SETMAP, &kbmap) < 0)
209 			err(EXIT_FAILURE, "WSKBDIO_SETMAP");
210 		pr_field(field_by_value(&kbmap), " -> ");
211 	}
212 
213 	repeat.which = 0;
214 	if (field_by_value(&repeat.del1)->flags & FLG_SET)
215 		repeat.which |= WSKBD_KEYREPEAT_DODEL1;
216 	if (field_by_value(&repeat.delN)->flags & FLG_SET)
217 		repeat.which |= WSKBD_KEYREPEAT_DODELN;
218 	if (repeat.which != 0 &&
219 	    ioctl(fd, WSKBDIO_SETKEYREPEAT, &repeat) < 0)
220 		err(EXIT_FAILURE, "WSKBDIO_SETKEYREPEAT");
221 	if (repeat.which & WSKBD_KEYREPEAT_DODEL1)
222 		pr_field(field_by_value(&repeat.del1), " -> ");
223 	if (repeat.which & WSKBD_KEYREPEAT_DODELN)
224 		pr_field(field_by_value(&repeat.delN), " -> ");
225 
226 	dfrepeat.which = 0;
227 	if (field_by_value(&dfrepeat.del1)->flags & FLG_SET)
228 		dfrepeat.which |= WSKBD_KEYREPEAT_DODEL1;
229 	if (field_by_value(&dfrepeat.delN)->flags & FLG_SET)
230 		dfrepeat.which |= WSKBD_KEYREPEAT_DODELN;
231 	if (dfrepeat.which != 0 &&
232 	    ioctl(fd, WSKBDIO_SETDEFAULTKEYREPEAT, &dfrepeat) < 0)
233 		err(EXIT_FAILURE, "WSKBDIO_SETDEFAULTKEYREPEAT");
234 	if (dfrepeat.which &WSKBD_KEYREPEAT_DODEL1)
235 		pr_field(field_by_value(&dfrepeat.del1), " -> ");
236 	if (dfrepeat.which & WSKBD_KEYREPEAT_DODELN)
237 		pr_field(field_by_value(&dfrepeat.delN), " -> ");
238 
239 	if (field_by_value(&ledstate)->flags & FLG_SET) {
240 		if (ioctl(fd, WSKBDIO_SETLEDS, &ledstate) < 0)
241 			err(EXIT_FAILURE, "WSKBDIO_SETLEDS");
242 		pr_field(field_by_value(&ledstate), " -> ");
243 	}
244 
245 	if (field_by_value(&kbdencoding)->flags & FLG_SET) {
246 		if (ioctl(fd, WSKBDIO_SETENCODING, &kbdencoding) < 0)
247 			err(EXIT_FAILURE, "WSKBDIO_SETENCODING");
248 		pr_field(field_by_value(&kbdencoding), " -> ");
249 	}
250 
251 	if (field_by_value(&keyclick)->flags & FLG_SET) {
252 		if (ioctl(fd, WSKBDIO_SETKEYCLICK, &keyclick) < 0)
253 			err(EXIT_FAILURE, "WSKBDIO_SETKEYCLICK");
254 		pr_field(field_by_value(&keyclick), " -> ");
255 	}
256 
257 
258 	if (havescroll == 0)
259 		return;
260 
261 	scroll.which = 0;
262 	if (field_by_value(&scroll.mode)->flags & FLG_SET)
263 		scroll.which |= WSKBD_SCROLL_DOMODE;
264 	if (field_by_value(&scroll.modifier)->flags & FLG_SET)
265 		scroll.which |= WSKBD_SCROLL_DOMODIFIER;
266 
267 	if (scroll.which & WSKBD_SCROLL_DOMODE)
268 		pr_field(field_by_value(&scroll.mode), " -> ");
269 	if (scroll.which & WSKBD_SCROLL_DOMODIFIER)
270 		pr_field(field_by_value(&scroll.modifier), " -> ");
271 	if (scroll.which != 0) {
272 		if (ioctl(fd, WSKBDIO_SETSCROLL, &scroll) == -1) {
273 			if (errno != ENODEV)
274 				err(EXIT_FAILURE, "WSKBDIO_SETSCROLL");
275 			else {
276 				warnx("scrolling is not supported by this "
277 				    "kernel");
278 				havescroll = 0;
279 			}
280 		}
281 	}
282 }
283 
284