kbd_wscons.c revision 1.19
1/* $OpenBSD: kbd_wscons.c,v 1.19 2004/10/08 17:26:35 millert 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 45#define SA_PCKBD 0 46#define SA_UKBD 1 47#define SA_AKBD 2 48#define SA_ZSKBD 3 49#define SA_SUNKBD 4 50#define SA_SUN5KBD 5 51#define SA_HILKBD 6 52#define SA_GSCKBD 7 53 54#ifndef NOKVM 55struct nlist nl[] = { 56 { "_pckbd_keydesctab" }, 57 { "_ukbd_keydesctab" }, 58 { "_akbd_keydesctab" }, 59 { "_zskbd_keydesctab" }, 60 { "_sunkbd_keydesctab" }, 61 { "_sunkbd5_keydesctab" }, 62 { "_hilkbd_keydesctab" }, 63 { "_gsckbd_keydesctab" }, 64 { NULL }, 65}; 66 67char *kbtype_tab[] = { 68 "pc-xt/pc-at", 69 "usb", 70 "adb", 71 "lk201", 72 "sun", 73 "sun5", 74 "hil", 75 "gsc", 76}; 77 78int rebuild = 0; 79 80#endif /* NOKVM */ 81 82struct nameint { 83 int value; 84 char *name; 85}; 86 87struct nameint kbdenc_tab[] = { 88 KB_ENCTAB 89 , 90 { 0, 0 } 91}; 92 93struct nameint kbdvar_tab[] = { 94 KB_VARTAB 95 , 96 { 0, 0 } 97}; 98 99extern char *__progname; 100 101void kbd_show_enc(kvm_t *kd, int idx); 102void kbd_list(void); 103void kbd_set(char *name, int verbose); 104 105#ifndef NOKVM 106void 107kbd_show_enc(kvm_t *kd, int idx) 108{ 109 struct wscons_keydesc r; 110 unsigned long p; 111 struct nameint *n; 112 int found; 113 u_int32_t variant; 114 115 printf("tables available for %s keyboard:\nencoding\n\n", 116 kbtype_tab[idx]); 117 p = nl[idx].n_value; 118 kvm_read(kd, p, &r, sizeof(r)); 119 while (r.name != 0) { 120 n = &kbdenc_tab[0]; 121 found = 0; 122 while (n->value) { 123 if (n->value == KB_ENCODING(r.name)) { 124 printf("%s",n->name); 125 found++; 126 } 127 n++; 128 } 129 if (found == 0) { 130 printf("<encoding 0x%04x>",KB_ENCODING(r.name)); 131 rebuild++; 132 } 133 n = &kbdvar_tab[0]; 134 found = 0; 135 variant = KB_VARIANT(r.name); 136 while (n->value) { 137 if ((n->value & KB_VARIANT(r.name)) == n->value) { 138 printf(".%s",n->name); 139 variant &= ~n->value; 140 } 141 n++; 142 } 143 if (variant != 0) { 144 printf(".<variant 0x%08x>",variant); 145 rebuild++; 146 } 147 printf("\n"); 148 p += sizeof(r); 149 kvm_read(kd, p, &r, sizeof(r)); 150 } 151 printf("\n"); 152} 153#endif 154 155void 156kbd_list(void) 157{ 158 int fd, i, kbtype; 159#ifndef NOKVM 160 kvm_t *kd; 161 char errbuf[LINE_MAX]; 162#endif 163 char device[MAXPATHLEN]; 164 int pc_kbd = 0; 165 int usb_kbd = 0; 166 int adb_kbd = 0; 167 int zs_kbd = 0; 168 int sun_kbd = 0; 169 int sun5_kbd = 0; 170 int hil_kbd = 0; 171 int gsc_kbd = 0; 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 210 if (pc_kbd > 0) 211 kbd_show_enc(kd, SA_PCKBD); 212 213 if (usb_kbd > 0) 214 kbd_show_enc(kd, SA_UKBD); 215 216 if (adb_kbd > 0) 217 kbd_show_enc(kd, SA_AKBD); 218 219 if (zs_kbd > 0) 220 kbd_show_enc(kd, SA_ZSKBD); 221 222 if (sun_kbd > 0) 223 kbd_show_enc(kd, SA_SUNKBD); 224 225 if (sun5_kbd > 0) 226 kbd_show_enc(kd, SA_SUN5KBD); 227 228 if (hil_kbd > 0) 229 kbd_show_enc(kd, SA_HILKBD); 230 231 if (gsc_kbd > 0) 232 kbd_show_enc(kd, SA_GSCKBD); 233 234 kvm_close(kd); 235 236 if (rebuild > 0) { 237 printf("Unknown encoding or variant. kbd(1) needs to be rebuilt.\n"); 238 } 239#else 240 printf("List not available; sorry.\n"); 241#endif 242} 243 244void 245kbd_set(char *name, int verbose) 246{ 247 char buf[LINE_MAX]; 248 char *c,*b; 249 struct nameint *n; 250 int map = 0,v,i,fd; 251 char device[sizeof "/dev/wskbd00"]; 252 253 c = name; 254 b = buf; 255 while ((*c != '.') && (*c != '\0') && 256 (b < buf + sizeof(buf) - 1)) { 257 *b++ = *c++; 258 } 259 *b = '\0'; 260 n = &kbdenc_tab[0]; 261 while (n->value) { 262 if (strcmp(n->name,buf) == 0) { 263 map = n->value; 264 } 265 n++; 266 } 267 if (map == 0) 268 errx(1, "unknown encoding %s", buf); 269 while (*c == '.') { 270 b = buf; 271 c++; 272 while ((*c != '.') && (*c != '\0') && 273 (b < buf + sizeof(buf) - 1)) { 274 *b++ = *c++; 275 } 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 } 283 n++; 284 } 285 if (v == 0) 286 errx(1, "unknown variant %s", buf); 287 map |= v; 288 } 289 290 /* Go through all keyboards. */ 291 v = 0; 292 for (i = 0; i < NUM_KBD; i++) { 293 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 294 fd = open(device, O_WRONLY); 295 if (fd < 0) 296 fd = open(device, O_RDONLY); 297 if (fd >= 0) { 298 if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) { 299 if (errno == EINVAL) { 300 fprintf(stderr, 301 "%s: unsupported encoding %s on %s\n", 302 __progname, name, device); 303 } else { 304 err(1, "WSKBDIO_SETENCODING: %s", device); 305 } 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