1 /* $OpenBSD: keyboard.c,v 1.14 2019/06/28 13:32:46 deraadt Exp $ */ 2 /* $NetBSD: keyboard.c 1.1 1998/12/28 14:01:17 hannken 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 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/ioctl.h> 34 #include <sys/time.h> 35 #include <dev/wscons/wsksymdef.h> 36 #include <dev/wscons/wsconsio.h> 37 #include <err.h> 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <stdio.h> 41 #include "wsconsctl.h" 42 43 static u_int kbtype; 44 static struct wskbd_bell_data bell; 45 static struct wskbd_bell_data dfbell; 46 static struct wscons_keymap mapdata[KS_NUMKEYCODES]; 47 struct wskbd_map_data kbmap = { KS_NUMKEYCODES, mapdata }; /* used in map_parse.y 48 and in util.c */ 49 static struct wskbd_keyrepeat_data repeat; 50 static struct wskbd_keyrepeat_data dfrepeat; 51 static int ledstate; 52 static kbd_t kbdencoding; 53 static struct field_pc backlight; 54 55 struct field keyboard_field_tab[] = { 56 { "type", &kbtype, FMT_KBDTYPE, FLG_RDONLY }, 57 { "bell.pitch", &bell.pitch, FMT_UINT, FLG_MODIFY }, 58 { "bell.period", &bell.period, FMT_UINT, FLG_MODIFY }, 59 { "bell.volume", &bell.volume, FMT_UINT, FLG_MODIFY }, 60 { "bell.pitch.default", &dfbell.pitch, FMT_UINT, FLG_MODIFY }, 61 { "bell.period.default", &dfbell.period, FMT_UINT, FLG_MODIFY }, 62 { "bell.volume.default", &dfbell.volume, FMT_UINT, FLG_MODIFY }, 63 { "map", &kbmap, FMT_KBMAP, FLG_MODIFY|FLG_NOAUTO }, 64 { "repeat.del1", &repeat.del1, FMT_UINT, FLG_MODIFY }, 65 { "repeat.deln", &repeat.delN, FMT_UINT, FLG_MODIFY }, 66 { "repeat.del1.default", &dfrepeat.del1, FMT_UINT, FLG_MODIFY }, 67 { "repeat.deln.default", &dfrepeat.delN, FMT_UINT, FLG_MODIFY }, 68 { "ledstate", &ledstate, FMT_UINT, 0 }, 69 { "encoding", &kbdencoding, FMT_KBDENC, FLG_MODIFY }, 70 { "backlight", &backlight, FMT_PC, FLG_MODIFY|FLG_INIT }, 71 { NULL } 72 }; 73 74 void 75 keyboard_get_values(int fd) 76 { 77 struct wskbd_backlight kbl; 78 struct field *pf; 79 80 if (field_by_value(keyboard_field_tab, &kbtype)->flags & FLG_GET) 81 if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) == -1) 82 warn("WSKBDIO_GTYPE"); 83 84 bell.which = 0; 85 if (field_by_value(keyboard_field_tab, &bell.pitch)->flags & FLG_GET) 86 bell.which |= WSKBD_BELL_DOPITCH; 87 if (field_by_value(keyboard_field_tab, &bell.period)->flags & FLG_GET) 88 bell.which |= WSKBD_BELL_DOPERIOD; 89 if (field_by_value(keyboard_field_tab, &bell.volume)->flags & FLG_GET) 90 bell.which |= WSKBD_BELL_DOVOLUME; 91 if (bell.which != 0 && ioctl(fd, WSKBDIO_GETBELL, &bell) == -1) 92 warn("WSKBDIO_GETBELL"); 93 94 dfbell.which = 0; 95 if (field_by_value(keyboard_field_tab, &dfbell.pitch)->flags & FLG_GET) 96 dfbell.which |= WSKBD_BELL_DOPITCH; 97 if (field_by_value(keyboard_field_tab, &dfbell.period)->flags & FLG_GET) 98 dfbell.which |= WSKBD_BELL_DOPERIOD; 99 if (field_by_value(keyboard_field_tab, &dfbell.volume)->flags & FLG_GET) 100 dfbell.which |= WSKBD_BELL_DOVOLUME; 101 if (dfbell.which != 0 && 102 ioctl(fd, WSKBDIO_GETDEFAULTBELL, &dfbell) == -1) 103 warn("WSKBDIO_GETDEFAULTBELL"); 104 105 if (field_by_value(keyboard_field_tab, &kbmap)->flags & FLG_GET) { 106 kbmap.maplen = KS_NUMKEYCODES; 107 if (ioctl(fd, WSKBDIO_GETMAP, &kbmap) == -1) 108 warn("WSKBDIO_GETMAP"); 109 if (ioctl(fd, WSKBDIO_GETENCODING, &kbdencoding) == -1) 110 warn("WSKBDIO_GETENCODING"); 111 ksymenc(kbdencoding); 112 } 113 114 repeat.which = 0; 115 if (field_by_value(keyboard_field_tab, &repeat.del1)->flags & FLG_GET) 116 repeat.which |= WSKBD_KEYREPEAT_DODEL1; 117 if (field_by_value(keyboard_field_tab, &repeat.delN)->flags & FLG_GET) 118 repeat.which |= WSKBD_KEYREPEAT_DODELN; 119 if (repeat.which != 0 && 120 ioctl(fd, WSKBDIO_GETKEYREPEAT, &repeat) == -1) 121 warn("WSKBDIO_GETKEYREPEAT"); 122 123 dfrepeat.which = 0; 124 if (field_by_value(keyboard_field_tab, &dfrepeat.del1)->flags & FLG_GET) 125 dfrepeat.which |= WSKBD_KEYREPEAT_DODEL1; 126 if (field_by_value(keyboard_field_tab, &dfrepeat.delN)->flags & FLG_GET) 127 dfrepeat.which |= WSKBD_KEYREPEAT_DODELN; 128 if (dfrepeat.which != 0 && 129 ioctl(fd, WSKBDIO_GETDEFAULTKEYREPEAT, &dfrepeat) == -1) 130 warn("WSKBDIO_GETDEFAULTKEYREPEAT"); 131 132 if (field_by_value(keyboard_field_tab, &ledstate)->flags & FLG_GET) 133 if (ioctl(fd, WSKBDIO_GETLEDS, &ledstate) == -1) 134 warn("WSKBDIO_GETLEDS"); 135 136 if (field_by_value(keyboard_field_tab, &kbdencoding)->flags & FLG_GET) 137 if (ioctl(fd, WSKBDIO_GETENCODING, &kbdencoding) == -1) 138 warn("WSKBDIO_GETENCODING"); 139 140 pf = field_by_value(keyboard_field_tab, &backlight); 141 if (pf->flags & FLG_GET && !(pf->flags & FLG_DEAD)) { 142 errno = ENOTTY; 143 if (ioctl(fd, WSKBDIO_GETBACKLIGHT, &kbl) == -1) { 144 if (errno == ENOTTY) 145 pf->flags |= FLG_DEAD; 146 else 147 warn("WSKBDIO_GETBACKLIGHT"); 148 } else { 149 backlight.min = kbl.min; 150 backlight.cur = kbl.curval; 151 backlight.max = kbl.max; 152 } 153 } 154 } 155 156 int 157 keyboard_put_values(int fd) 158 { 159 struct wskbd_backlight kbl; 160 struct field *pf; 161 162 bell.which = 0; 163 if (field_by_value(keyboard_field_tab, &bell.pitch)->flags & FLG_SET) 164 bell.which |= WSKBD_BELL_DOPITCH; 165 if (field_by_value(keyboard_field_tab, &bell.period)->flags & FLG_SET) 166 bell.which |= WSKBD_BELL_DOPERIOD; 167 if (field_by_value(keyboard_field_tab, &bell.volume)->flags & FLG_SET) 168 bell.which |= WSKBD_BELL_DOVOLUME; 169 if (bell.which != 0 && ioctl(fd, WSKBDIO_SETBELL, &bell) == -1) { 170 warn("WSKBDIO_SETBELL"); 171 return 1; 172 } 173 174 dfbell.which = 0; 175 if (field_by_value(keyboard_field_tab, &dfbell.pitch)->flags & FLG_SET) 176 dfbell.which |= WSKBD_BELL_DOPITCH; 177 if (field_by_value(keyboard_field_tab, &dfbell.period)->flags & FLG_SET) 178 dfbell.which |= WSKBD_BELL_DOPERIOD; 179 if (field_by_value(keyboard_field_tab, &dfbell.volume)->flags & FLG_SET) 180 dfbell.which |= WSKBD_BELL_DOVOLUME; 181 if (dfbell.which != 0 && 182 ioctl(fd, WSKBDIO_SETDEFAULTBELL, &dfbell) == -1) { 183 warn("WSKBDIO_SETDEFAULTBELL"); 184 return 1; 185 } 186 187 if (field_by_value(keyboard_field_tab, &kbmap)->flags & FLG_SET) { 188 if (ioctl(fd, WSKBDIO_SETMAP, &kbmap) == -1) { 189 warn("WSKBDIO_SETMAP"); 190 return 1; 191 } 192 } 193 194 repeat.which = 0; 195 if (field_by_value(keyboard_field_tab, &repeat.del1)->flags & FLG_SET) 196 repeat.which |= WSKBD_KEYREPEAT_DODEL1; 197 if (field_by_value(keyboard_field_tab, &repeat.delN)->flags & FLG_SET) 198 repeat.which |= WSKBD_KEYREPEAT_DODELN; 199 if (repeat.which != 0 && 200 ioctl(fd, WSKBDIO_SETKEYREPEAT, &repeat) == -1) { 201 warn("WSKBDIO_SETKEYREPEAT"); 202 return 1; 203 } 204 205 dfrepeat.which = 0; 206 if (field_by_value(keyboard_field_tab, &dfrepeat.del1)->flags & FLG_SET) 207 dfrepeat.which |= WSKBD_KEYREPEAT_DODEL1; 208 if (field_by_value(keyboard_field_tab, &dfrepeat.delN)->flags & FLG_SET) 209 dfrepeat.which |= WSKBD_KEYREPEAT_DODELN; 210 if (dfrepeat.which != 0 && 211 ioctl(fd, WSKBDIO_SETDEFAULTKEYREPEAT, &dfrepeat) == -1) { 212 warn("WSKBDIO_SETDEFAULTKEYREPEAT"); 213 return 1; 214 } 215 216 if (field_by_value(keyboard_field_tab, &ledstate)->flags & FLG_SET) { 217 if (ioctl(fd, WSKBDIO_SETLEDS, &ledstate) == -1) { 218 warn("WSKBDIO_SETLEDS"); 219 return 1; 220 } 221 } 222 223 if (field_by_value(keyboard_field_tab, &kbdencoding)->flags & FLG_SET) { 224 if (ioctl(fd, WSKBDIO_SETENCODING, &kbdencoding) == -1) { 225 warn("WSKBDIO_SETENCODING"); 226 return 1; 227 } 228 } 229 230 pf = field_by_value(keyboard_field_tab, &backlight); 231 if (pf->flags & FLG_SET && !(pf->flags & FLG_DEAD)) { 232 kbl.min = backlight.min; 233 kbl.curval = backlight.cur; 234 kbl.max = backlight.max; 235 errno = ENOTTY; 236 if (ioctl(fd, WSKBDIO_SETBACKLIGHT, &kbl) == -1) { 237 if (errno == ENOTTY) 238 pf->flags |= FLG_DEAD; 239 else { 240 warn("WSKBDIO_SETBACKLIGHT"); 241 return 1; 242 } 243 } 244 } 245 246 return 0; 247 } 248 249 char * 250 keyboard_next_device(int index) 251 { 252 static char devname[20]; 253 254 snprintf(devname, sizeof(devname), "/dev/wskbd%d", index); 255 return (devname); 256 } 257