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