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