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