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