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