kbd_wscons.c revision 1.31
1/* $OpenBSD: kbd_wscons.c,v 1.31 2016/09/30 12:07:23 kettenis 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 n = &kbdenc_tab[0]; 104 found = 0; 105 encoding = encs->encodings[i]; 106 while (n->value) { 107 if (n->value == KB_ENCODING(encoding)) { 108 printf("%s", n->name); 109 found++; 110 } 111 n++; 112 } 113 if (found == 0) 114 printf("<encoding 0x%04x>", KB_ENCODING(encoding)); 115 n = &kbdvar_tab[0]; 116 found = 0; 117 variant = KB_VARIANT(encoding); 118 while (n->value) { 119 if ((n->value & KB_VARIANT(encoding)) == n->value) { 120 printf(".%s", n->name); 121 variant &= ~n->value; 122 } 123 n++; 124 } 125 if (variant != 0) 126 printf(".<variant 0x%08x>", variant); 127 printf("\n"); 128 } 129 printf("\n"); 130} 131 132void 133kbd_get_encs(int fd, struct wskbd_encoding_data *encs) 134{ 135 int nencodings = 64; 136 137 encs->nencodings = nencodings; 138 while (encs->nencodings == nencodings) { 139 encs->encodings = reallocarray(encs->encodings, 140 encs->nencodings, sizeof(kbd_t)); 141 if (encs->encodings == NULL) 142 err(1, NULL); 143 if (ioctl(fd, WSKBDIO_GETENCODINGS, encs) < 0) 144 err(1, "WSKBDIO_GETENCODINGS"); 145 if (encs->nencodings == nencodings) { 146 nencodings *= 2; 147 encs->nencodings = nencodings; 148 } 149 } 150} 151 152void 153kbd_list(void) 154{ 155 int kbds[SA_MAX]; 156 struct wskbd_encoding_data encs[SA_MAX]; 157 int fd, i, kbtype, t; 158 char device[PATH_MAX]; 159 160 memset(kbds, 0, sizeof(kbds)); 161 memset(encs, 0, sizeof(encs)); 162 163 /* Go through all keyboards. */ 164 for (i = 0; i < NUM_KBD; i++) { 165 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 166 fd = open(device, O_WRONLY); 167 if (fd < 0) 168 fd = open(device, O_RDONLY); 169 if (fd >= 0) { 170 if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0) 171 err(1, "WSKBDIO_GTYPE"); 172 switch (kbtype) { 173 case WSKBD_TYPE_PC_XT: 174 case WSKBD_TYPE_PC_AT: 175 t = SA_PCKBD; 176 break; 177 case WSKBD_TYPE_USB: 178 t = SA_UKBD; 179 break; 180 case WSKBD_TYPE_ADB: 181 t = SA_AKBD; 182 break; 183 case WSKBD_TYPE_LK201: 184 case WSKBD_TYPE_LK401: 185 t = SA_LKKBD; 186 break; 187 case WSKBD_TYPE_SUN: 188 t = SA_SUNKBD; 189 break; 190 case WSKBD_TYPE_SUN5: 191 t = SA_SUN5KBD; 192 break; 193 case WSKBD_TYPE_HIL: 194 t = SA_HILKBD; 195 break; 196 case WSKBD_TYPE_GSC: 197 t = SA_GSCKBD; 198 break; 199 case WSKBD_TYPE_SGI: 200 t = SA_SGIKBD; 201 break; 202 default: 203 t = SA_MAX; 204 break; 205 }; 206 207 if (t != SA_MAX) { 208 kbds[t]++; 209 if (encs[t].encodings == NULL) 210 kbd_get_encs(fd, &encs[t]); 211 } 212 close(fd); 213 } 214 } 215 216 for (i = 0; i < SA_MAX; i++) 217 if (kbds[i] != 0) 218 kbd_show_enc(&encs[i], i); 219 220 for (i = 0; i < SA_MAX; i++) 221 free(encs[i].encodings); 222} 223 224void 225kbd_set(char *name, int verbose) 226{ 227 char buf[LINE_MAX], *c, *b, device[sizeof "/dev/wskbd00"]; 228 int map = 0, v, i, fd; 229 struct nameint *n; 230 231 c = name; 232 b = buf; 233 while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1) 234 *b++ = *c++; 235 *b = '\0'; 236 n = &kbdenc_tab[0]; 237 while (n->value) { 238 if (strcmp(n->name, buf) == 0) 239 map = n->value; 240 n++; 241 } 242 if (map == 0) 243 errx(1, "unknown encoding %s", buf); 244 while (*c == '.') { 245 b = buf; 246 c++; 247 while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1) 248 *b++ = *c++; 249 *b = '\0'; 250 v = 0; 251 n = &kbdvar_tab[0]; 252 while (n->value) { 253 if (strcmp(n->name, buf) == 0) 254 v = n->value; 255 n++; 256 } 257 if (v == 0) 258 errx(1, "unknown variant %s", buf); 259 map |= v; 260 } 261 262 /* Go through all keyboards. */ 263 v = 0; 264 for (i = 0; i < NUM_KBD; i++) { 265 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 266 fd = open(device, O_WRONLY); 267 if (fd < 0) 268 fd = open(device, O_RDONLY); 269 if (fd >= 0) { 270 if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) { 271 if (errno == EINVAL) { 272 fprintf(stderr, 273 "%s: unsupported encoding %s on %s\n", 274 __progname, name, device); 275 } else 276 err(1, "WSKBDIO_SETENCODING: %s", device); 277 v--; 278 } 279 v++; 280 close(fd); 281 } 282 } 283 284 if (verbose && v > 0) 285 fprintf(stderr, "kbd: keyboard mapping set to %s\n", name); 286} 287