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