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