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 * 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 42#include "wsconsctl.h" 43 44static int kbtype; 45static int keyclick; 46static struct wskbd_bell_data bell; 47static struct wskbd_bell_data dfbell; 48static struct wscons_keymap mapdata[KS_NUMKEYCODES]; 49struct wskbd_map_data kbmap = /* used in map_parse.y and in util.c */ 50 { KS_NUMKEYCODES, mapdata }; 51static struct wskbd_keyrepeat_data repeat; 52static struct wskbd_keyrepeat_data dfrepeat; 53static struct wskbd_scroll_data scroll; 54static int ledstate; 55static kbd_t kbdencoding; 56static int havescroll = 1; 57 58struct field keyboard_field_tab[] = { 59 { "type", &kbtype, FMT_KBDTYPE, FLG_RDONLY }, 60 { "bell.pitch", &bell.pitch, FMT_UINT, FLG_MODIFY }, 61 { "bell.period", &bell.period, FMT_UINT, FLG_MODIFY }, 62 { "bell.volume", &bell.volume, FMT_UINT, FLG_MODIFY }, 63 { "bell.pitch.default", &dfbell.pitch, FMT_UINT, FLG_MODIFY }, 64 { "bell.period.default", &dfbell.period, FMT_UINT, FLG_MODIFY }, 65 { "bell.volume.default", &dfbell.volume, FMT_UINT, FLG_MODIFY }, 66 { "map", &kbmap, FMT_KBMAP, FLG_MODIFY | 67 FLG_NOAUTO }, 68 { "repeat.del1", &repeat.del1, FMT_UINT, FLG_MODIFY }, 69 { "repeat.deln", &repeat.delN, FMT_UINT, FLG_MODIFY }, 70 { "repeat.del1.default", &dfrepeat.del1, FMT_UINT, FLG_MODIFY }, 71 { "repeat.deln.default", &dfrepeat.delN, FMT_UINT, FLG_MODIFY }, 72 { "ledstate", &ledstate, FMT_UINT, 0 }, 73 { "encoding", &kbdencoding, FMT_KBDENC, FLG_MODIFY }, 74 { "keyclick", &keyclick, FMT_UINT, FLG_MODIFY }, 75 { "scroll.mode", &scroll.mode, FMT_UINT, FLG_MODIFY }, 76 { "scroll.modifier", &scroll.modifier, FMT_UINT, FLG_MODIFY }, 77}; 78 79int keyboard_field_tab_len = sizeof(keyboard_field_tab) / 80 sizeof(keyboard_field_tab[0]); 81 82void 83keyboard_get_values(int fd) 84{ 85 86 if (field_by_value(&kbtype)->flags & FLG_GET) 87 if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0) 88 err(EXIT_FAILURE, "WSKBDIO_GTYPE"); 89 90 bell.which = 0; 91 if (field_by_value(&bell.pitch)->flags & FLG_GET) 92 bell.which |= WSKBD_BELL_DOPITCH; 93 if (field_by_value(&bell.period)->flags & FLG_GET) 94 bell.which |= WSKBD_BELL_DOPERIOD; 95 if (field_by_value(&bell.volume)->flags & FLG_GET) 96 bell.which |= WSKBD_BELL_DOVOLUME; 97 if (bell.which != 0 && ioctl(fd, WSKBDIO_GETBELL, &bell) < 0) 98 err(EXIT_FAILURE, "WSKBDIO_GETBELL"); 99 100 dfbell.which = 0; 101 if (field_by_value(&dfbell.pitch)->flags & FLG_GET) 102 dfbell.which |= WSKBD_BELL_DOPITCH; 103 if (field_by_value(&dfbell.period)->flags & FLG_GET) 104 dfbell.which |= WSKBD_BELL_DOPERIOD; 105 if (field_by_value(&dfbell.volume)->flags & FLG_GET) 106 dfbell.which |= WSKBD_BELL_DOVOLUME; 107 if (dfbell.which != 0 && 108 ioctl(fd, WSKBDIO_GETDEFAULTBELL, &dfbell) < 0) 109 err(EXIT_FAILURE, "WSKBDIO_GETDEFAULTBELL"); 110 111 if (field_by_value(&kbmap)->flags & FLG_GET) { 112 kbmap.maplen = KS_NUMKEYCODES; 113 if (ioctl(fd, WSKBDIO_GETMAP, &kbmap) < 0) 114 err(EXIT_FAILURE, "WSKBDIO_GETMAP"); 115 } 116 117 repeat.which = 0; 118 if (field_by_value(&repeat.del1)->flags & FLG_GET) 119 repeat.which |= WSKBD_KEYREPEAT_DODEL1; 120 if (field_by_value(&repeat.delN)->flags & FLG_GET) 121 repeat.which |= WSKBD_KEYREPEAT_DODELN; 122 if (repeat.which != 0 && 123 ioctl(fd, WSKBDIO_GETKEYREPEAT, &repeat) < 0) 124 err(EXIT_FAILURE, "WSKBDIO_GETKEYREPEAT"); 125 126 dfrepeat.which = 0; 127 if (field_by_value(&dfrepeat.del1)->flags & FLG_GET) 128 dfrepeat.which |= WSKBD_KEYREPEAT_DODEL1; 129 if (field_by_value(&dfrepeat.delN)->flags & FLG_GET) 130 dfrepeat.which |= WSKBD_KEYREPEAT_DODELN; 131 if (dfrepeat.which != 0 && 132 ioctl(fd, WSKBDIO_GETKEYREPEAT, &dfrepeat) < 0) 133 err(EXIT_FAILURE, "WSKBDIO_GETKEYREPEAT"); 134 135 if (field_by_value(&ledstate)->flags & FLG_GET) 136 if (ioctl(fd, WSKBDIO_GETLEDS, &ledstate) < 0) 137 err(EXIT_FAILURE, "WSKBDIO_GETLEDS"); 138 139 if (field_by_value(&kbdencoding)->flags & FLG_GET) 140 if (ioctl(fd, WSKBDIO_GETENCODING, &kbdencoding) < 0) 141 err(EXIT_FAILURE, "WSKBDIO_GETENCODING"); 142 143 if (field_by_value(&keyclick)->flags & FLG_GET) { 144 ioctl(fd, WSKBDIO_GETKEYCLICK, &keyclick); 145 /* Optional; don't complain. */ 146 } 147 148 scroll.which = 0; 149 if (field_by_value(&scroll.mode)->flags & FLG_GET) 150 scroll.which |= WSKBD_SCROLL_DOMODE; 151 if (field_by_value(&scroll.modifier)->flags & FLG_GET) 152 scroll.which |= WSKBD_SCROLL_DOMODIFIER; 153 if (scroll.which != 0) { 154 if (ioctl(fd, WSKBDIO_GETSCROLL, &scroll) == -1) { 155 if (errno != ENODEV) 156 err(EXIT_FAILURE, "WSKBDIO_GETSCROLL"); 157 else 158 havescroll = 0; 159 } 160 } 161} 162 163void 164keyboard_put_values(int fd) 165{ 166 167 bell.which = 0; 168 if (field_by_value(&bell.pitch)->flags & FLG_SET) 169 bell.which |= WSKBD_BELL_DOPITCH; 170 if (field_by_value(&bell.period)->flags & FLG_SET) 171 bell.which |= WSKBD_BELL_DOPERIOD; 172 if (field_by_value(&bell.volume)->flags & FLG_SET) 173 bell.which |= WSKBD_BELL_DOVOLUME; 174 if (bell.which != 0 && ioctl(fd, WSKBDIO_SETBELL, &bell) < 0) 175 err(EXIT_FAILURE, "WSKBDIO_SETBELL"); 176 if (bell.which & WSKBD_BELL_DOPITCH) 177 pr_field(field_by_value(&bell.pitch), " -> "); 178 if (bell.which & WSKBD_BELL_DOPERIOD) 179 pr_field(field_by_value(&bell.period), " -> "); 180 if (bell.which & WSKBD_BELL_DOVOLUME) 181 pr_field(field_by_value(&bell.volume), " -> "); 182 183 dfbell.which = 0; 184 if (field_by_value(&dfbell.pitch)->flags & FLG_SET) 185 dfbell.which |= WSKBD_BELL_DOPITCH; 186 if (field_by_value(&dfbell.period)->flags & FLG_SET) 187 dfbell.which |= WSKBD_BELL_DOPERIOD; 188 if (field_by_value(&dfbell.volume)->flags & FLG_SET) 189 dfbell.which |= WSKBD_BELL_DOVOLUME; 190 if (dfbell.which != 0 && 191 ioctl(fd, WSKBDIO_SETDEFAULTBELL, &dfbell) < 0) 192 err(EXIT_FAILURE, "WSKBDIO_SETDEFAULTBELL"); 193 if (dfbell.which & WSKBD_BELL_DOPITCH) 194 pr_field(field_by_value(&dfbell.pitch), " -> "); 195 if (dfbell.which & WSKBD_BELL_DOPERIOD) 196 pr_field(field_by_value(&dfbell.period), " -> "); 197 if (dfbell.which & WSKBD_BELL_DOVOLUME) 198 pr_field(field_by_value(&dfbell.volume), " -> "); 199 200 if (field_by_value(&kbmap)->flags & FLG_SET) { 201 if (ioctl(fd, WSKBDIO_SETMAP, &kbmap) < 0) 202 err(EXIT_FAILURE, "WSKBDIO_SETMAP"); 203 pr_field(field_by_value(&kbmap), " -> "); 204 } 205 206 repeat.which = 0; 207 if (field_by_value(&repeat.del1)->flags & FLG_SET) 208 repeat.which |= WSKBD_KEYREPEAT_DODEL1; 209 if (field_by_value(&repeat.delN)->flags & FLG_SET) 210 repeat.which |= WSKBD_KEYREPEAT_DODELN; 211 if (repeat.which != 0 && 212 ioctl(fd, WSKBDIO_SETKEYREPEAT, &repeat) < 0) 213 err(EXIT_FAILURE, "WSKBDIO_SETKEYREPEAT"); 214 if (repeat.which & WSKBD_KEYREPEAT_DODEL1) 215 pr_field(field_by_value(&repeat.del1), " -> "); 216 if (repeat.which & WSKBD_KEYREPEAT_DODELN) 217 pr_field(field_by_value(&repeat.delN), " -> "); 218 219 dfrepeat.which = 0; 220 if (field_by_value(&dfrepeat.del1)->flags & FLG_SET) 221 dfrepeat.which |= WSKBD_KEYREPEAT_DODEL1; 222 if (field_by_value(&dfrepeat.delN)->flags & FLG_SET) 223 dfrepeat.which |= WSKBD_KEYREPEAT_DODELN; 224 if (dfrepeat.which != 0 && 225 ioctl(fd, WSKBDIO_SETDEFAULTKEYREPEAT, &dfrepeat) < 0) 226 err(EXIT_FAILURE, "WSKBDIO_SETDEFAULTKEYREPEAT"); 227 if (dfrepeat.which &WSKBD_KEYREPEAT_DODEL1) 228 pr_field(field_by_value(&dfrepeat.del1), " -> "); 229 if (dfrepeat.which & WSKBD_KEYREPEAT_DODELN) 230 pr_field(field_by_value(&dfrepeat.delN), " -> "); 231 232 if (field_by_value(&ledstate)->flags & FLG_SET) { 233 if (ioctl(fd, WSKBDIO_SETLEDS, &ledstate) < 0) 234 err(EXIT_FAILURE, "WSKBDIO_SETLEDS"); 235 pr_field(field_by_value(&ledstate), " -> "); 236 } 237 238 if (field_by_value(&kbdencoding)->flags & FLG_SET) { 239 if (ioctl(fd, WSKBDIO_SETENCODING, &kbdencoding) < 0) 240 err(EXIT_FAILURE, "WSKBDIO_SETENCODING"); 241 pr_field(field_by_value(&kbdencoding), " -> "); 242 } 243 244 if (field_by_value(&keyclick)->flags & FLG_SET) { 245 if (ioctl(fd, WSKBDIO_SETKEYCLICK, &keyclick) < 0) 246 err(EXIT_FAILURE, "WSKBDIO_SETKEYCLICK"); 247 pr_field(field_by_value(&keyclick), " -> "); 248 } 249 250 251 if (havescroll == 0) 252 return; 253 254 scroll.which = 0; 255 if (field_by_value(&scroll.mode)->flags & FLG_SET) 256 scroll.which |= WSKBD_SCROLL_DOMODE; 257 if (field_by_value(&scroll.modifier)->flags & FLG_SET) 258 scroll.which |= WSKBD_SCROLL_DOMODIFIER; 259 260 if (scroll.which & WSKBD_SCROLL_DOMODE) 261 pr_field(field_by_value(&scroll.mode), " -> "); 262 if (scroll.which & WSKBD_SCROLL_DOMODIFIER) 263 pr_field(field_by_value(&scroll.modifier), " -> "); 264 if (scroll.which != 0) { 265 if (ioctl(fd, WSKBDIO_SETSCROLL, &scroll) == -1) { 266 if (errno != ENODEV) 267 err(EXIT_FAILURE, "WSKBDIO_SETSCROLL"); 268 else { 269 warnx("scrolling is not supported by this " 270 "kernel"); 271 havescroll = 0; 272 } 273 } 274 } 275} 276 277