kbd_wscons.c revision 1.30
1/* $OpenBSD: kbd_wscons.c,v 1.30 2016/09/27 22:03:49 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 * 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 <string.h> 38#include <unistd.h> 39 40#define NUM_KBD 10 41 42char *kbtype_tab[] = { 43 "pc-xt/pc-at", 44 "usb", 45 "adb", 46 "lk201", 47 "sun", 48 "sun5", 49 "hil", 50 "gsc", 51 "sgi" 52}; 53enum { SA_PCKBD, 54 SA_UKBD, 55 SA_AKBD, 56 SA_LKKBD, 57 SA_SUNKBD, 58 SA_SUN5KBD, 59 SA_HILKBD, 60 SA_GSCKBD, 61 SA_SGIKBD, 62 63 SA_MAX 64}; 65 66struct nameint { 67 int value; 68 char *name; 69}; 70 71struct nameint kbdenc_tab[] = { 72 KB_ENCTAB 73 , 74 { 0, NULL } 75}; 76 77struct nameint kbdvar_tab[] = { 78 KB_VARTAB 79 , 80 { 0, NULL } 81}; 82 83extern char *__progname; 84 85void kbd_show_enc(int idx); 86void kbd_list(void); 87void kbd_set(char *name, int verbose); 88 89void 90kbd_show_enc(int idx) 91{ 92 int i; 93 94 printf("tables available for %s keyboard:\nencoding\n\n", 95 kbtype_tab[idx]); 96 97 for (i = 0; kbdenc_tab[i].value; i++) 98 printf("%s\n", kbdenc_tab[i].name); 99 printf("\n"); 100} 101 102void 103kbd_list(void) 104{ 105 int kbds[SA_MAX]; 106 int fd, i, kbtype; 107 char device[PATH_MAX]; 108 109 bzero(kbds, sizeof(kbds)); 110 111 /* Go through all keyboards. */ 112 for (i = 0; i < NUM_KBD; i++) { 113 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 114 fd = open(device, O_WRONLY); 115 if (fd < 0) 116 fd = open(device, O_RDONLY); 117 if (fd >= 0) { 118 if (ioctl(fd, WSKBDIO_GTYPE, &kbtype) < 0) 119 err(1, "WSKBDIO_GTYPE"); 120 switch (kbtype) { 121 case WSKBD_TYPE_PC_XT: 122 case WSKBD_TYPE_PC_AT: 123 kbds[SA_PCKBD]++; 124 break; 125 case WSKBD_TYPE_USB: 126 kbds[SA_UKBD]++; 127 break; 128 case WSKBD_TYPE_ADB: 129 kbds[SA_AKBD]++; 130 break; 131 case WSKBD_TYPE_LK201: 132 case WSKBD_TYPE_LK401: 133 kbds[SA_LKKBD]++; 134 break; 135 case WSKBD_TYPE_SUN: 136 kbds[SA_SUNKBD]++; 137 break; 138 case WSKBD_TYPE_SUN5: 139 kbds[SA_SUN5KBD]++; 140 break; 141 case WSKBD_TYPE_HIL: 142 kbds[SA_HILKBD]++; 143 break; 144 case WSKBD_TYPE_GSC: 145 kbds[SA_GSCKBD]++; 146 break; 147 case WSKBD_TYPE_SGI: 148 kbds[SA_SGIKBD]++; 149 break; 150 }; 151 close(fd); 152 } 153 } 154 155 for (i = 0; i < SA_MAX; i++) 156 if (kbds[i] != 0) 157 kbd_show_enc(i); 158} 159 160void 161kbd_set(char *name, int verbose) 162{ 163 char buf[LINE_MAX], *c, *b, device[sizeof "/dev/wskbd00"]; 164 int map = 0, v, i, fd; 165 struct nameint *n; 166 167 c = name; 168 b = buf; 169 while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1) 170 *b++ = *c++; 171 *b = '\0'; 172 n = &kbdenc_tab[0]; 173 while (n->value) { 174 if (strcmp(n->name, buf) == 0) 175 map = n->value; 176 n++; 177 } 178 if (map == 0) 179 errx(1, "unknown encoding %s", buf); 180 while (*c == '.') { 181 b = buf; 182 c++; 183 while (*c != '.' && *c != '\0' && b < buf + sizeof(buf) - 1) 184 *b++ = *c++; 185 *b = '\0'; 186 v = 0; 187 n = &kbdvar_tab[0]; 188 while (n->value) { 189 if (strcmp(n->name, buf) == 0) 190 v = n->value; 191 n++; 192 } 193 if (v == 0) 194 errx(1, "unknown variant %s", buf); 195 map |= v; 196 } 197 198 /* Go through all keyboards. */ 199 v = 0; 200 for (i = 0; i < NUM_KBD; i++) { 201 (void) snprintf(device, sizeof device, "/dev/wskbd%d", i); 202 fd = open(device, O_WRONLY); 203 if (fd < 0) 204 fd = open(device, O_RDONLY); 205 if (fd >= 0) { 206 if (ioctl(fd, WSKBDIO_SETENCODING, &map) < 0) { 207 if (errno == EINVAL) { 208 fprintf(stderr, 209 "%s: unsupported encoding %s on %s\n", 210 __progname, name, device); 211 } else 212 err(1, "WSKBDIO_SETENCODING: %s", device); 213 v--; 214 } 215 v++; 216 close(fd); 217 } 218 } 219 220 if (verbose && v > 0) 221 fprintf(stderr, "kbd: keyboard mapping set to %s\n", name); 222} 223