1 /* $OpenBSD: kbd_wscons.c,v 1.34 2020/01/22 06:24:07 tedu 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 43 char *kbtype_tab[] = { 44 "pc-xt/pc-at", 45 "usb", 46 "adb", 47 "lk201", 48 "sun", 49 "sun5", 50 "hil", 51 "gsc", 52 "sgi" 53 }; 54 enum { 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 67 struct nameint { 68 int value; 69 char *name; 70 }; 71 72 struct nameint kbdenc_tab[] = { 73 KB_ENCTAB 74 , 75 { 0, NULL } 76 }; 77 78 struct nameint kbdvar_tab[] = { 79 KB_VARTAB 80 , 81 { 0, NULL } 82 }; 83 84 extern char *__progname; 85 86 void kbd_show_enc(struct wskbd_encoding_data *encs, int idx); 87 void kbd_get_encs(int fd, struct wskbd_encoding_data *encs); 88 void kbd_list(void); 89 void kbd_set(char *name, int verbose); 90 91 void 92 kbd_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 128 void 129 kbd_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) == -1) 140 err(1, "WSKBDIO_GETENCODINGS"); 141 if (encs->nencodings == nencodings) { 142 nencodings *= 2; 143 encs->nencodings = nencodings; 144 } 145 } 146 } 147 148 void 149 kbd_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 == -1) 164 fd = open(device, O_RDONLY); 165 if (fd >= 0) { 166 if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) == -1) 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 220 void 221 kbd_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 == -1) 262 fd = open(device, O_RDONLY); 263 if (fd >= 0) { 264 if (ioctl(fd, WSKBDIO_SETENCODING, &map) == -1) { 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