1*d9c815adSmlelstv /* $NetBSD: keyboard.c,v 1.12 2021/09/22 14:15:29 mlelstv Exp $ */
204ee2eceShannken
304ee2eceShannken /*-
4ea287a80Sjmmv * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
504ee2eceShannken * All rights reserved.
604ee2eceShannken *
704ee2eceShannken * This code is derived from software contributed to The NetBSD Foundation
804ee2eceShannken * by Juergen Hannken-Illjes.
904ee2eceShannken *
1004ee2eceShannken * Redistribution and use in source and binary forms, with or without
1104ee2eceShannken * modification, are permitted provided that the following conditions
1204ee2eceShannken * are met:
1304ee2eceShannken * 1. Redistributions of source code must retain the above copyright
1404ee2eceShannken * notice, this list of conditions and the following disclaimer.
1504ee2eceShannken * 2. Redistributions in binary form must reproduce the above copyright
1604ee2eceShannken * notice, this list of conditions and the following disclaimer in the
1704ee2eceShannken * documentation and/or other materials provided with the distribution.
1804ee2eceShannken *
1904ee2eceShannken * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2004ee2eceShannken * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2104ee2eceShannken * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2204ee2eceShannken * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2304ee2eceShannken * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2404ee2eceShannken * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2504ee2eceShannken * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2604ee2eceShannken * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2704ee2eceShannken * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2804ee2eceShannken * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2904ee2eceShannken * POSSIBILITY OF SUCH DAMAGE.
3004ee2eceShannken */
3104ee2eceShannken
3204ee2eceShannken #include <sys/ioctl.h>
3304ee2eceShannken #include <sys/time.h>
34c799a9c4Sjmmv
3504ee2eceShannken #include <dev/wscons/wsksymdef.h>
3604ee2eceShannken #include <dev/wscons/wsconsio.h>
37c799a9c4Sjmmv
3804ee2eceShannken #include <err.h>
39d12d56b3Schristos #include <errno.h>
40c799a9c4Sjmmv #include <stdlib.h>
4171e18f4bSmlelstv #include <string.h>
42c799a9c4Sjmmv
4304ee2eceShannken #include "wsconsctl.h"
4404ee2eceShannken
4504ee2eceShannken static int kbtype;
469824683bSad static int keyclick;
4704ee2eceShannken static struct wskbd_bell_data bell;
4804ee2eceShannken static struct wskbd_bell_data dfbell;
4904ee2eceShannken static struct wscons_keymap mapdata[KS_NUMKEYCODES];
50c799a9c4Sjmmv struct wskbd_map_data kbmap = /* used in map_parse.y and in util.c */
51c799a9c4Sjmmv { KS_NUMKEYCODES, mapdata };
5271e18f4bSmlelstv static struct wscons_keymap oldmapdata[KS_NUMKEYCODES];
5371e18f4bSmlelstv static struct wskbd_map_data oldkbmap =
5471e18f4bSmlelstv { KS_NUMKEYCODES, oldmapdata };
5504ee2eceShannken static struct wskbd_keyrepeat_data repeat;
5604ee2eceShannken static struct wskbd_keyrepeat_data dfrepeat;
5779884742Schristos static struct wskbd_scroll_data scroll;
5804ee2eceShannken static int ledstate;
59c2697758Shannken static kbd_t kbdencoding;
60d12d56b3Schristos static int havescroll = 1;
61ad2d0017Smlelstv static int kbmode;
6204ee2eceShannken
6304ee2eceShannken struct field keyboard_field_tab[] = {
6404ee2eceShannken { "type", &kbtype, FMT_KBDTYPE, FLG_RDONLY },
65ad2d0017Smlelstv { "mode", &kbmode, FMT_UINT, FLG_MODIFY },
6604ee2eceShannken { "bell.pitch", &bell.pitch, FMT_UINT, FLG_MODIFY },
6704ee2eceShannken { "bell.period", &bell.period, FMT_UINT, FLG_MODIFY },
6804ee2eceShannken { "bell.volume", &bell.volume, FMT_UINT, FLG_MODIFY },
6904ee2eceShannken { "bell.pitch.default", &dfbell.pitch, FMT_UINT, FLG_MODIFY },
7004ee2eceShannken { "bell.period.default", &dfbell.period, FMT_UINT, FLG_MODIFY },
7104ee2eceShannken { "bell.volume.default", &dfbell.volume, FMT_UINT, FLG_MODIFY },
72c799a9c4Sjmmv { "map", &kbmap, FMT_KBMAP, FLG_MODIFY |
73c799a9c4Sjmmv FLG_NOAUTO },
7404ee2eceShannken { "repeat.del1", &repeat.del1, FMT_UINT, FLG_MODIFY },
7504ee2eceShannken { "repeat.deln", &repeat.delN, FMT_UINT, FLG_MODIFY },
7604ee2eceShannken { "repeat.del1.default", &dfrepeat.del1, FMT_UINT, FLG_MODIFY },
7704ee2eceShannken { "repeat.deln.default", &dfrepeat.delN, FMT_UINT, FLG_MODIFY },
7804ee2eceShannken { "ledstate", &ledstate, FMT_UINT, 0 },
7904ee2eceShannken { "encoding", &kbdencoding, FMT_KBDENC, FLG_MODIFY },
809824683bSad { "keyclick", &keyclick, FMT_UINT, FLG_MODIFY },
8179884742Schristos { "scroll.mode", &scroll.mode, FMT_UINT, FLG_MODIFY },
8279884742Schristos { "scroll.modifier", &scroll.modifier, FMT_UINT, FLG_MODIFY },
8304ee2eceShannken };
8404ee2eceShannken
8504ee2eceShannken int keyboard_field_tab_len = sizeof(keyboard_field_tab) /
8604ee2eceShannken sizeof(keyboard_field_tab[0]);
8704ee2eceShannken
8871e18f4bSmlelstv static void
diff_kmap(struct wskbd_map_data * omap,struct wskbd_map_data * nmap)8971e18f4bSmlelstv diff_kmap(struct wskbd_map_data *omap, struct wskbd_map_data *nmap)
9071e18f4bSmlelstv {
9171e18f4bSmlelstv unsigned int u;
9271e18f4bSmlelstv struct wscons_keymap *op, *np;
9371e18f4bSmlelstv
9471e18f4bSmlelstv for (u = 0; u < nmap->maplen; u++) {
9571e18f4bSmlelstv op = omap->map + u;
9671e18f4bSmlelstv np = nmap->map + u;
9771e18f4bSmlelstv if (op->command == np->command &&
9871e18f4bSmlelstv op->group1[0] == np->group1[0] &&
9971e18f4bSmlelstv op->group1[1] == np->group1[1] &&
10071e18f4bSmlelstv op->group2[0] == np->group2[0] &&
10171e18f4bSmlelstv op->group2[1] == np->group2[1]) {
10271e18f4bSmlelstv np->command = KS_voidSymbol;
10371e18f4bSmlelstv np->group1[0] = KS_voidSymbol;
10471e18f4bSmlelstv np->group1[1] = KS_voidSymbol;
10571e18f4bSmlelstv np->group2[0] = KS_voidSymbol;
10671e18f4bSmlelstv np->group2[1] = KS_voidSymbol;
10771e18f4bSmlelstv }
10871e18f4bSmlelstv }
10971e18f4bSmlelstv }
11071e18f4bSmlelstv
11104ee2eceShannken void
keyboard_get_values(int fd)112844f4c52Sxtraeme keyboard_get_values(int fd)
11304ee2eceShannken {
114c799a9c4Sjmmv
11504ee2eceShannken if (field_by_value(&kbtype)->flags & FLG_GET)
11604ee2eceShannken if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0)
117c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GTYPE");
11804ee2eceShannken
119ad2d0017Smlelstv if (field_by_value(&kbmode)->flags & FLG_GET) {
120ad2d0017Smlelstv ioctl(fd, WSKBDIO_GETMODE, &kbmode);
121ad2d0017Smlelstv /* Optional; don't complain. */
122ad2d0017Smlelstv }
123ad2d0017Smlelstv
12404ee2eceShannken bell.which = 0;
12504ee2eceShannken if (field_by_value(&bell.pitch)->flags & FLG_GET)
12604ee2eceShannken bell.which |= WSKBD_BELL_DOPITCH;
12704ee2eceShannken if (field_by_value(&bell.period)->flags & FLG_GET)
12804ee2eceShannken bell.which |= WSKBD_BELL_DOPERIOD;
12904ee2eceShannken if (field_by_value(&bell.volume)->flags & FLG_GET)
13004ee2eceShannken bell.which |= WSKBD_BELL_DOVOLUME;
13104ee2eceShannken if (bell.which != 0 && ioctl(fd, WSKBDIO_GETBELL, &bell) < 0)
132c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GETBELL");
13304ee2eceShannken
13404ee2eceShannken dfbell.which = 0;
13504ee2eceShannken if (field_by_value(&dfbell.pitch)->flags & FLG_GET)
13604ee2eceShannken dfbell.which |= WSKBD_BELL_DOPITCH;
13704ee2eceShannken if (field_by_value(&dfbell.period)->flags & FLG_GET)
13804ee2eceShannken dfbell.which |= WSKBD_BELL_DOPERIOD;
13904ee2eceShannken if (field_by_value(&dfbell.volume)->flags & FLG_GET)
14004ee2eceShannken dfbell.which |= WSKBD_BELL_DOVOLUME;
14104ee2eceShannken if (dfbell.which != 0 &&
14204ee2eceShannken ioctl(fd, WSKBDIO_GETDEFAULTBELL, &dfbell) < 0)
143c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GETDEFAULTBELL");
14404ee2eceShannken
14504ee2eceShannken if (field_by_value(&kbmap)->flags & FLG_GET) {
14604ee2eceShannken kbmap.maplen = KS_NUMKEYCODES;
14704ee2eceShannken if (ioctl(fd, WSKBDIO_GETMAP, &kbmap) < 0)
148c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GETMAP");
14971e18f4bSmlelstv memcpy(oldmapdata, mapdata, sizeof(oldmapdata));
15004ee2eceShannken }
15104ee2eceShannken
15204ee2eceShannken repeat.which = 0;
15304ee2eceShannken if (field_by_value(&repeat.del1)->flags & FLG_GET)
15404ee2eceShannken repeat.which |= WSKBD_KEYREPEAT_DODEL1;
15504ee2eceShannken if (field_by_value(&repeat.delN)->flags & FLG_GET)
15604ee2eceShannken repeat.which |= WSKBD_KEYREPEAT_DODELN;
15704ee2eceShannken if (repeat.which != 0 &&
15804ee2eceShannken ioctl(fd, WSKBDIO_GETKEYREPEAT, &repeat) < 0)
159c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GETKEYREPEAT");
16004ee2eceShannken
16104ee2eceShannken dfrepeat.which = 0;
16204ee2eceShannken if (field_by_value(&dfrepeat.del1)->flags & FLG_GET)
16304ee2eceShannken dfrepeat.which |= WSKBD_KEYREPEAT_DODEL1;
16404ee2eceShannken if (field_by_value(&dfrepeat.delN)->flags & FLG_GET)
16504ee2eceShannken dfrepeat.which |= WSKBD_KEYREPEAT_DODELN;
16604ee2eceShannken if (dfrepeat.which != 0 &&
16704ee2eceShannken ioctl(fd, WSKBDIO_GETKEYREPEAT, &dfrepeat) < 0)
168c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GETKEYREPEAT");
16904ee2eceShannken
17004ee2eceShannken if (field_by_value(&ledstate)->flags & FLG_GET)
17104ee2eceShannken if (ioctl(fd, WSKBDIO_GETLEDS, &ledstate) < 0)
172c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GETLEDS");
17304ee2eceShannken
17404ee2eceShannken if (field_by_value(&kbdencoding)->flags & FLG_GET)
17504ee2eceShannken if (ioctl(fd, WSKBDIO_GETENCODING, &kbdencoding) < 0)
176c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GETENCODING");
1779824683bSad
1789824683bSad if (field_by_value(&keyclick)->flags & FLG_GET) {
1799824683bSad ioctl(fd, WSKBDIO_GETKEYCLICK, &keyclick);
1809824683bSad /* Optional; don't complain. */
1819824683bSad }
18279884742Schristos
18379884742Schristos scroll.which = 0;
18479884742Schristos if (field_by_value(&scroll.mode)->flags & FLG_GET)
18579884742Schristos scroll.which |= WSKBD_SCROLL_DOMODE;
18679884742Schristos if (field_by_value(&scroll.modifier)->flags & FLG_GET)
18779884742Schristos scroll.which |= WSKBD_SCROLL_DOMODIFIER;
188d12d56b3Schristos if (scroll.which != 0) {
189d12d56b3Schristos if (ioctl(fd, WSKBDIO_GETSCROLL, &scroll) == -1) {
190d12d56b3Schristos if (errno != ENODEV)
191c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_GETSCROLL");
192d12d56b3Schristos else
193d12d56b3Schristos havescroll = 0;
194d12d56b3Schristos }
195d12d56b3Schristos }
19604ee2eceShannken }
19704ee2eceShannken
19804ee2eceShannken void
keyboard_put_values(int fd)199844f4c52Sxtraeme keyboard_put_values(int fd)
20004ee2eceShannken {
201c799a9c4Sjmmv
202ad2d0017Smlelstv if (field_by_value(&kbmode)->flags & FLG_SET) {
203*d9c815adSmlelstv if (ioctl(fd, WSKBDIO_SETMODE, &kbmode) < 0)
204ad2d0017Smlelstv err(EXIT_FAILURE, "WSKBDIO_SETMODE");
205ad2d0017Smlelstv pr_field(field_by_value(&kbmode), " -> ");
206ad2d0017Smlelstv }
207ad2d0017Smlelstv
20804ee2eceShannken bell.which = 0;
20904ee2eceShannken if (field_by_value(&bell.pitch)->flags & FLG_SET)
21004ee2eceShannken bell.which |= WSKBD_BELL_DOPITCH;
21104ee2eceShannken if (field_by_value(&bell.period)->flags & FLG_SET)
21204ee2eceShannken bell.which |= WSKBD_BELL_DOPERIOD;
21304ee2eceShannken if (field_by_value(&bell.volume)->flags & FLG_SET)
21404ee2eceShannken bell.which |= WSKBD_BELL_DOVOLUME;
21504ee2eceShannken if (bell.which != 0 && ioctl(fd, WSKBDIO_SETBELL, &bell) < 0)
216c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETBELL");
21704ee2eceShannken if (bell.which & WSKBD_BELL_DOPITCH)
21804ee2eceShannken pr_field(field_by_value(&bell.pitch), " -> ");
21904ee2eceShannken if (bell.which & WSKBD_BELL_DOPERIOD)
22004ee2eceShannken pr_field(field_by_value(&bell.period), " -> ");
22104ee2eceShannken if (bell.which & WSKBD_BELL_DOVOLUME)
22204ee2eceShannken pr_field(field_by_value(&bell.volume), " -> ");
22304ee2eceShannken
22404ee2eceShannken dfbell.which = 0;
22504ee2eceShannken if (field_by_value(&dfbell.pitch)->flags & FLG_SET)
22604ee2eceShannken dfbell.which |= WSKBD_BELL_DOPITCH;
22704ee2eceShannken if (field_by_value(&dfbell.period)->flags & FLG_SET)
22804ee2eceShannken dfbell.which |= WSKBD_BELL_DOPERIOD;
22904ee2eceShannken if (field_by_value(&dfbell.volume)->flags & FLG_SET)
23004ee2eceShannken dfbell.which |= WSKBD_BELL_DOVOLUME;
23104ee2eceShannken if (dfbell.which != 0 &&
23204ee2eceShannken ioctl(fd, WSKBDIO_SETDEFAULTBELL, &dfbell) < 0)
233c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETDEFAULTBELL");
23404ee2eceShannken if (dfbell.which & WSKBD_BELL_DOPITCH)
23504ee2eceShannken pr_field(field_by_value(&dfbell.pitch), " -> ");
23604ee2eceShannken if (dfbell.which & WSKBD_BELL_DOPERIOD)
23704ee2eceShannken pr_field(field_by_value(&dfbell.period), " -> ");
23804ee2eceShannken if (dfbell.which & WSKBD_BELL_DOVOLUME)
23904ee2eceShannken pr_field(field_by_value(&dfbell.volume), " -> ");
24004ee2eceShannken
24104ee2eceShannken if (field_by_value(&kbmap)->flags & FLG_SET) {
24204ee2eceShannken if (ioctl(fd, WSKBDIO_SETMAP, &kbmap) < 0)
243c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETMAP");
24471e18f4bSmlelstv if (field_by_value(&kbmap)->flags & FLG_MODIFIED) {
24571e18f4bSmlelstv diff_kmap(&oldkbmap, &kbmap);
24671e18f4bSmlelstv pr_field(field_by_value(&kbmap), " +> ");
24771e18f4bSmlelstv } else
24804ee2eceShannken pr_field(field_by_value(&kbmap), " -> ");
24904ee2eceShannken }
25004ee2eceShannken
25104ee2eceShannken repeat.which = 0;
25204ee2eceShannken if (field_by_value(&repeat.del1)->flags & FLG_SET)
25304ee2eceShannken repeat.which |= WSKBD_KEYREPEAT_DODEL1;
25404ee2eceShannken if (field_by_value(&repeat.delN)->flags & FLG_SET)
25504ee2eceShannken repeat.which |= WSKBD_KEYREPEAT_DODELN;
25604ee2eceShannken if (repeat.which != 0 &&
25704ee2eceShannken ioctl(fd, WSKBDIO_SETKEYREPEAT, &repeat) < 0)
258c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETKEYREPEAT");
25904ee2eceShannken if (repeat.which & WSKBD_KEYREPEAT_DODEL1)
26004ee2eceShannken pr_field(field_by_value(&repeat.del1), " -> ");
26104ee2eceShannken if (repeat.which & WSKBD_KEYREPEAT_DODELN)
26204ee2eceShannken pr_field(field_by_value(&repeat.delN), " -> ");
26304ee2eceShannken
26404ee2eceShannken dfrepeat.which = 0;
26504ee2eceShannken if (field_by_value(&dfrepeat.del1)->flags & FLG_SET)
26604ee2eceShannken dfrepeat.which |= WSKBD_KEYREPEAT_DODEL1;
26704ee2eceShannken if (field_by_value(&dfrepeat.delN)->flags & FLG_SET)
26804ee2eceShannken dfrepeat.which |= WSKBD_KEYREPEAT_DODELN;
26904ee2eceShannken if (dfrepeat.which != 0 &&
27004ee2eceShannken ioctl(fd, WSKBDIO_SETDEFAULTKEYREPEAT, &dfrepeat) < 0)
271c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETDEFAULTKEYREPEAT");
27204ee2eceShannken if (dfrepeat.which &WSKBD_KEYREPEAT_DODEL1)
27304ee2eceShannken pr_field(field_by_value(&dfrepeat.del1), " -> ");
27404ee2eceShannken if (dfrepeat.which & WSKBD_KEYREPEAT_DODELN)
27504ee2eceShannken pr_field(field_by_value(&dfrepeat.delN), " -> ");
27604ee2eceShannken
27704ee2eceShannken if (field_by_value(&ledstate)->flags & FLG_SET) {
27804ee2eceShannken if (ioctl(fd, WSKBDIO_SETLEDS, &ledstate) < 0)
279c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETLEDS");
28004ee2eceShannken pr_field(field_by_value(&ledstate), " -> ");
28104ee2eceShannken }
28204ee2eceShannken
28304ee2eceShannken if (field_by_value(&kbdencoding)->flags & FLG_SET) {
28404ee2eceShannken if (ioctl(fd, WSKBDIO_SETENCODING, &kbdencoding) < 0)
285c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETENCODING");
28604ee2eceShannken pr_field(field_by_value(&kbdencoding), " -> ");
28704ee2eceShannken }
2889824683bSad
2899824683bSad if (field_by_value(&keyclick)->flags & FLG_SET) {
2909824683bSad if (ioctl(fd, WSKBDIO_SETKEYCLICK, &keyclick) < 0)
291c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETKEYCLICK");
2929824683bSad pr_field(field_by_value(&keyclick), " -> ");
2939824683bSad }
29479884742Schristos
29579884742Schristos
296d12d56b3Schristos if (havescroll == 0)
297d12d56b3Schristos return;
298d12d56b3Schristos
29979884742Schristos scroll.which = 0;
30079884742Schristos if (field_by_value(&scroll.mode)->flags & FLG_SET)
30179884742Schristos scroll.which |= WSKBD_SCROLL_DOMODE;
30279884742Schristos if (field_by_value(&scroll.modifier)->flags & FLG_SET)
30379884742Schristos scroll.which |= WSKBD_SCROLL_DOMODIFIER;
30479884742Schristos
30579884742Schristos if (scroll.which & WSKBD_SCROLL_DOMODE)
30679884742Schristos pr_field(field_by_value(&scroll.mode), " -> ");
30779884742Schristos if (scroll.which & WSKBD_SCROLL_DOMODIFIER)
30879884742Schristos pr_field(field_by_value(&scroll.modifier), " -> ");
309d12d56b3Schristos if (scroll.which != 0) {
310d12d56b3Schristos if (ioctl(fd, WSKBDIO_SETSCROLL, &scroll) == -1) {
311d12d56b3Schristos if (errno != ENODEV)
312c799a9c4Sjmmv err(EXIT_FAILURE, "WSKBDIO_SETSCROLL");
313d12d56b3Schristos else {
314c799a9c4Sjmmv warnx("scrolling is not supported by this "
315c799a9c4Sjmmv "kernel");
316d12d56b3Schristos havescroll = 0;
317d12d56b3Schristos }
318d12d56b3Schristos }
319d12d56b3Schristos }
32004ee2eceShannken }
32179884742Schristos
322