kbd_wscons.c revision 1.24
1/* $OpenBSD: kbd_wscons.c,v 1.24 2006/07/31 22:09:37 miod 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 "domain" 55}; 56enum { SA_PCKBD, 57 SA_UKBD, 58 SA_AKBD, 59 SA_LKKBD, 60 SA_SUNKBD, 61 SA_SUN5KBD, 62 SA_HILKBD, 63 SA_GSCKBD, 64 SA_DOMAINKBD, 65 66 SA_MAX 67}; 68 69#ifndef NOKVM 70struct nlist nl[] = { 71 { "_pckbd_keydesctab" }, 72 { "_ukbd_keydesctab" }, 73 { "_akbd_keydesctab" }, 74 { "_lkkbd_keydesctab" }, 75 { "_sunkbd_keydesctab" }, 76 { "_sunkbd5_keydesctab" }, 77 { "_hilkbd_keydesctab" }, 78 { "_gsckbd_keydesctab" }, 79 { "_dnkbd_keydesctab" }, 80 { NULL }, 81}; 82#endif /* NOKVM */ 83 84int rebuild = 0; 85 86struct nameint { 87 int value; 88 char *name; 89}; 90 91struct nameint kbdenc_tab[] = { 92 KB_ENCTAB 93 , 94 { 0, 0 } 95}; 96 97struct nameint kbdvar_tab[] = { 98 KB_VARTAB 99 , 100 { 0, 0 } 101}; 102 103extern char *__progname; 104 105void kbd_show_enc(kvm_t *kd, int idx); 106void kbd_list(void); 107void kbd_set(char *name, int verbose); 108 109void 110kbd_show_enc(kvm_t *kd, int idx) 111{ 112#ifndef NOKVM 113 struct wscons_keydesc r; 114 unsigned long p; 115 int found; 116 u_int32_t variant; 117 struct nameint *n; 118#else 119 int i; 120#endif /* NOKVM */ 121 122#ifndef NOKVM 123 p = nl[idx].n_value; 124 if (p == 0) { 125 printf("no tables available for %s keyboard\n\n", 126 kbtype_tab[idx]); 127 return; 128 } 129#endif 130 131 printf("tables available for %s keyboard:\nencoding\n\n", 132 kbtype_tab[idx]); 133 134#ifdef NOKVM 135 for (i = 0; kbdenc_tab[i].value; i++) 136 printf("%s\n", kbdenc_tab[i].name); 137#else 138 kvm_read(kd, p, &r, sizeof(r)); 139 while (r.name != 0) { 140 n = &kbdenc_tab[0]; 141 found = 0; 142 while (n->value) { 143 if (n->value == KB_ENCODING(r.name)) { 144 printf("%s",n->name); 145 found++; 146 } 147 n++; 148 } 149 if (found == 0) { 150 printf("<encoding 0x%04x>",KB_ENCODING(r.name)); 151 rebuild++; 152 } 153 n = &kbdvar_tab[0]; 154 found = 0; 155 variant = KB_VARIANT(r.name); 156 while (n->value) { 157 if ((n->value & KB_VARIANT(r.name)) == n->value) { 158 printf(".%s",n->name); 159 variant &= ~n->value; 160 } 161 n++; 162 } 163 if (variant != 0) { 164 printf(".<variant 0x%08x>",variant); 165 rebuild++; 166 } 167 printf("\n"); 168 p += sizeof(r); 169 kvm_read(kd, p, &r, sizeof(r)); 170 } 171#endif 172 printf("\n"); 173} 174 175void 176kbd_list(void) 177{ 178 int kbds[SA_MAX]; 179 int fd, i, kbtype; 180 char device[MAXPATHLEN]; 181 kvm_t *kd = NULL; 182#ifndef NOKVM 183 char errbuf[LINE_MAX]; 184#endif 185 186 bzero(kbds, sizeof(kbds)); 187 188 /* Go through all keyboards. */ 189 for (i = 0; i < NUM_KBD; i++) { 190 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 191 fd = open(device, O_WRONLY); 192 if (fd < 0) 193 fd = open(device, O_RDONLY); 194 if (fd >= 0) { 195 if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0) 196 err(1, "WSKBDIO_GTYPE"); 197 switch (kbtype) { 198 case WSKBD_TYPE_PC_XT: 199 case WSKBD_TYPE_PC_AT: 200 kbds[SA_PCKBD]++; 201 break; 202 case WSKBD_TYPE_USB: 203 kbds[SA_UKBD]++; 204 break; 205 case WSKBD_TYPE_ADB: 206 kbds[SA_AKBD]++; 207 break; 208 case WSKBD_TYPE_LK201: 209 case WSKBD_TYPE_LK401: 210 kbds[SA_LKKBD]++; 211 break; 212 case WSKBD_TYPE_SUN: 213 kbds[SA_SUNKBD]++; 214 break; 215 case WSKBD_TYPE_SUN5: 216 kbds[SA_SUN5KBD]++; 217 break; 218 case WSKBD_TYPE_HIL: 219 kbds[SA_HILKBD]++; 220 break; 221 case WSKBD_TYPE_GSC: 222 kbds[SA_GSCKBD]++; 223 break; 224 case WSKBD_TYPE_DOMAIN: 225 kbds[SA_DOMAINKBD]++; 226 break; 227 }; 228 close(fd); 229 } 230 } 231 232#ifndef NOKVM 233 if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == 0) 234 errx(1, "kvm_openfiles: %s", errbuf); 235 236 if (kvm_nlist(kd, nl) == -1) 237 errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 238#endif 239 240 for (i = 0; i < SA_MAX; i++) 241 if (kbds[i] != 0) 242 kbd_show_enc(kd, i); 243 244#ifndef NOKVM 245 kvm_close(kd); 246#endif 247 if (rebuild > 0) 248 printf("Unknown encoding or variant. kbd(8) needs to be rebuilt.\n"); 249} 250 251void 252kbd_set(char *name, int verbose) 253{ 254 char buf[LINE_MAX], *c, *b, device[sizeof "/dev/wskbd00"]; 255 int map = 0, v, i, fd; 256 struct nameint *n; 257 258 c = name; 259 b = buf; 260 while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1) 261 *b++ = *c++; 262 *b = '\0'; 263 n = &kbdenc_tab[0]; 264 while (n->value) { 265 if (strcmp(n->name, buf) == 0) 266 map = n->value; 267 n++; 268 } 269 if (map == 0) 270 errx(1, "unknown encoding %s", buf); 271 while (*c == '.') { 272 b = buf; 273 c++; 274 while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1) 275 *b++ = *c++; 276 *b = '\0'; 277 v = 0; 278 n = &kbdvar_tab[0]; 279 while (n->value) { 280 if (strcmp(n->name, buf) == 0) 281 v = n->value; 282 n++; 283 } 284 if (v == 0) 285 errx(1, "unknown variant %s", buf); 286 map |= v; 287 } 288 289 /* Go through all keyboards. */ 290 v = 0; 291 for (i = 0; i < NUM_KBD; i++) { 292 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 293 fd = open(device, O_WRONLY); 294 if (fd < 0) 295 fd = open(device, O_RDONLY); 296 if (fd >= 0) { 297 if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) { 298 if (errno == EINVAL) { 299 fprintf(stderr, 300 "%s: unsupported encoding %s on %s\n", 301 __progname, name, device); 302 } else 303 err(1, "WSKBDIO_SETENCODING: %s", device); 304 v--; 305 } 306 v++; 307 close(fd); 308 } 309 } 310 311 if (verbose && v > 0) 312 fprintf(stderr, "kbd: keyboard mapping set to %s\n", name); 313} 314