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