kbd_wscons.c revision 1.21
1/* $OpenBSD: kbd_wscons.c,v 1.21 2005/03/27 05:21:19 deraadt Exp $ */ 2 3/* 4 * Copyright (c) 2001 Mats O Jansson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/param.h> 28#include <sys/ioctl.h> 29#include <sys/time.h> 30#include <dev/wscons/wsconsio.h> 31#include <dev/wscons/wsksymdef.h> 32 33#include <err.h> 34#include <errno.h> 35#include <kvm.h> 36#include <fcntl.h> 37#include <limits.h> 38#include <nlist.h> 39#include <stdio.h> 40#include <string.h> 41#include <unistd.h> 42 43#define NUM_KBD 10 44 45char *kbtype_tab[] = { 46 "pc-xt/pc-at", 47 "usb", 48 "adb", 49 "lk201", 50 "sun", 51 "sun5", 52 "hil", 53 "gsc", 54}; 55#define SA_PCKBD 0 56#define SA_UKBD 1 57#define SA_AKBD 2 58#define SA_ZSKBD 3 59#define SA_SUNKBD 4 60#define SA_SUN5KBD 5 61#define SA_HILKBD 6 62#define SA_GSCKBD 7 63 64#ifndef NOKVM 65struct nlist nl[] = { 66 { "_pckbd_keydesctab" }, 67 { "_ukbd_keydesctab" }, 68 { "_akbd_keydesctab" }, 69 { "_zskbd_keydesctab" }, 70 { "_sunkbd_keydesctab" }, 71 { "_sunkbd5_keydesctab" }, 72 { "_hilkbd_keydesctab" }, 73 { "_gsckbd_keydesctab" }, 74 { NULL }, 75}; 76#endif /* NOKVM */ 77 78int rebuild = 0; 79 80struct nameint { 81 int value; 82 char *name; 83}; 84 85struct nameint kbdenc_tab[] = { 86 KB_ENCTAB 87 , 88 { 0, 0 } 89}; 90 91struct nameint kbdvar_tab[] = { 92 KB_VARTAB 93 , 94 { 0, 0 } 95}; 96 97extern char *__progname; 98 99void kbd_show_enc(kvm_t *kd, int idx); 100void kbd_list(void); 101void kbd_set(char *name, int verbose); 102 103void 104kbd_show_enc(kvm_t *kd, int idx) 105{ 106#ifndef NOKVM 107 struct wscons_keydesc r; 108 unsigned long p; 109 int found; 110 u_int32_t variant; 111 struct nameint *n; 112#else 113 int i; 114#endif /* NOKVM */ 115 116 printf("tables available for %s keyboard:\nencoding\n\n", 117 kbtype_tab[idx]); 118 119#ifdef NOKVM 120 for (i = 0; kbdenc_tab[i].value; i++) 121 printf("%s\n", kbdenc_tab[i].name); 122#else 123 p = nl[idx].n_value; 124 kvm_read(kd, p, &r, sizeof(r)); 125 while (r.name != 0) { 126 n = &kbdenc_tab[0]; 127 found = 0; 128 while (n->value) { 129 if (n->value == KB_ENCODING(r.name)) { 130 printf("%s",n->name); 131 found++; 132 } 133 n++; 134 } 135 if (found == 0) { 136 printf("<encoding 0x%04x>",KB_ENCODING(r.name)); 137 rebuild++; 138 } 139 n = &kbdvar_tab[0]; 140 found = 0; 141 variant = KB_VARIANT(r.name); 142 while (n->value) { 143 if ((n->value & KB_VARIANT(r.name)) == n->value) { 144 printf(".%s",n->name); 145 variant &= ~n->value; 146 } 147 n++; 148 } 149 if (variant != 0) { 150 printf(".<variant 0x%08x>",variant); 151 rebuild++; 152 } 153 printf("\n"); 154 p += sizeof(r); 155 kvm_read(kd, p, &r, sizeof(r)); 156 } 157#endif 158 printf("\n"); 159} 160 161void 162kbd_list(void) 163{ 164 int pc_kbd = 0, usb_kbd = 0, adb_kbd = 0; 165 int zs_kbd = 0, sun_kbd = 0, sun5_kbd = 0; 166 int hil_kbd = 0, gsc_kbd = 0, fd, i, kbtype; 167 char device[MAXPATHLEN]; 168 kvm_t *kd = NULL; 169#ifndef NOKVM 170 char errbuf[LINE_MAX]; 171#endif 172 173 /* Go through all keyboards. */ 174 for (i = 0; i < NUM_KBD; i++) { 175 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 176 fd = open(device, O_WRONLY); 177 if (fd < 0) 178 fd = open(device, O_RDONLY); 179 if (fd >= 0) { 180 if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0) 181 err(1, "WSKBDIO_GTYPE"); 182 if (kbtype == WSKBD_TYPE_PC_XT || 183 kbtype == WSKBD_TYPE_PC_AT) 184 pc_kbd++; 185 if (kbtype == WSKBD_TYPE_USB) 186 usb_kbd++; 187 if (kbtype == WSKBD_TYPE_ADB) 188 adb_kbd++; 189 if (kbtype == WSKBD_TYPE_LK201) 190 zs_kbd++; 191 if (kbtype == WSKBD_TYPE_SUN) 192 sun_kbd++; 193 if (kbtype == WSKBD_TYPE_SUN5) 194 sun5_kbd++; 195 if (kbtype == WSKBD_TYPE_HIL) 196 hil_kbd++; 197 if (kbtype == WSKBD_TYPE_GSC) 198 gsc_kbd++; 199 close(fd); 200 } 201 } 202 203#ifndef NOKVM 204 if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == 0) 205 errx(1, "kvm_openfiles: %s", errbuf); 206 207 if (kvm_nlist(kd, nl) == -1) 208 errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 209#endif 210 211 if (pc_kbd > 0) 212 kbd_show_enc(kd, SA_PCKBD); 213 if (usb_kbd > 0) 214 kbd_show_enc(kd, SA_UKBD); 215 if (adb_kbd > 0) 216 kbd_show_enc(kd, SA_AKBD); 217 if (zs_kbd > 0) 218 kbd_show_enc(kd, SA_ZSKBD); 219 if (sun_kbd > 0) 220 kbd_show_enc(kd, SA_SUNKBD); 221 if (sun5_kbd > 0) 222 kbd_show_enc(kd, SA_SUN5KBD); 223 if (hil_kbd > 0) 224 kbd_show_enc(kd, SA_HILKBD); 225 if (gsc_kbd > 0) 226 kbd_show_enc(kd, SA_GSCKBD); 227#ifndef NOKVM 228 kvm_close(kd); 229#endif 230 if (rebuild > 0) 231 printf("Unknown encoding or variant. kbd(8) needs to be rebuilt.\n"); 232} 233 234void 235kbd_set(char *name, int verbose) 236{ 237 char buf[LINE_MAX], *c, *b, device[sizeof "/dev/wskbd00"]; 238 int map = 0, v, i, fd; 239 struct nameint *n; 240 241 c = name; 242 b = buf; 243 while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1) 244 *b++ = *c++; 245 *b = '\0'; 246 n = &kbdenc_tab[0]; 247 while (n->value) { 248 if (strcmp(n->name, buf) == 0) 249 map = n->value; 250 n++; 251 } 252 if (map == 0) 253 errx(1, "unknown encoding %s", buf); 254 while (*c == '.') { 255 b = buf; 256 c++; 257 while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1) 258 *b++ = *c++; 259 *b = '\0'; 260 v = 0; 261 n = &kbdvar_tab[0]; 262 while (n->value) { 263 if (strcmp(n->name, buf) == 0) 264 v = n->value; 265 n++; 266 } 267 if (v == 0) 268 errx(1, "unknown variant %s", buf); 269 map |= v; 270 } 271 272 /* Go through all keyboards. */ 273 v = 0; 274 for (i = 0; i < NUM_KBD; i++) { 275 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 276 fd = open(device, O_WRONLY); 277 if (fd < 0) 278 fd = open(device, O_RDONLY); 279 if (fd >= 0) { 280 if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) { 281 if (errno == EINVAL) { 282 fprintf(stderr, 283 "%s: unsupported encoding %s on %s\n", 284 __progname, name, device); 285 } else 286 err(1, "WSKBDIO_SETENCODING: %s", device); 287 v--; 288 } 289 v++; 290 close(fd); 291 } 292 } 293 294 if (verbose && v > 0) 295 fprintf(stderr, "kbd: keyboard mapping set to %s\n", name); 296} 297