1 /* $NetBSD: util.c,v 1.26 2006/06/19 15:44:36 gdamore Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Juergen Hannken-Illjes and Julio M. Merino Vidal. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/time.h> 40 41 #include <dev/wscons/wsconsio.h> 42 #include <dev/wscons/wsksymdef.h> 43 44 #include <err.h> 45 #include <errno.h> 46 #include <limits.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 52 #include "wsconsctl.h" 53 54 #define TABLEN(t) (sizeof(t)/sizeof(t[0])) 55 56 extern struct wskbd_map_data kbmap; /* from keyboard.c */ 57 extern struct wskbd_map_data newkbmap; /* from map_parse.y */ 58 59 struct nameint { 60 int value; 61 const char *name; 62 }; 63 64 static struct nameint kbtype_tab[] = { 65 { WSKBD_TYPE_LK201, "lk201" }, 66 { WSKBD_TYPE_LK401, "lk401" }, 67 { WSKBD_TYPE_PC_XT, "pc-xt" }, 68 { WSKBD_TYPE_PC_AT, "pc-at" }, 69 { WSKBD_TYPE_USB, "usb" }, 70 { WSKBD_TYPE_HPC_KBD, "hpc-kbd" }, 71 { WSKBD_TYPE_HPC_BTN, "hpc-btn" }, 72 { WSKBD_TYPE_ARCHIMEDES, "archimedes" }, 73 { WSKBD_TYPE_RISCPC, "riscpc" }, 74 { WSKBD_TYPE_ADB, "adb" }, 75 { WSKBD_TYPE_HIL, "hil" }, 76 { WSKBD_TYPE_AMIGA, "amiga" }, 77 { WSKBD_TYPE_MAPLE, "maple" }, 78 { WSKBD_TYPE_ATARI, "atari" }, 79 { WSKBD_TYPE_SUN, "sun" }, 80 { WSKBD_TYPE_SUN5, "sun-type5" }, 81 { WSKBD_TYPE_SGI, "sgi" }, 82 { WSKBD_TYPE_MATRIXKP, "matrix-keypad" }, 83 { WSKBD_TYPE_BLUETOOTH, "bluetooth" }, 84 }; 85 86 static struct nameint mstype_tab[] = { 87 { WSMOUSE_TYPE_VSXXX, "dec-tc" }, 88 { WSMOUSE_TYPE_PS2, "ps2" }, 89 { WSMOUSE_TYPE_USB, "usb" }, 90 { WSMOUSE_TYPE_LMS, "logitech-bus" }, 91 { WSMOUSE_TYPE_MMS, "ms-inport" }, 92 { WSMOUSE_TYPE_TPANEL, "touch-panel" }, 93 { WSMOUSE_TYPE_NEXT, "next" }, 94 { WSMOUSE_TYPE_ARCHIMEDES, "archimedes" }, 95 { WSMOUSE_TYPE_HIL, "hil" }, 96 { WSMOUSE_TYPE_AMIGA, "amiga" }, 97 { WSMOUSE_TYPE_MAXINE, "dec-maxine" }, 98 { WSMOUSE_TYPE_MAPLE, "maple" }, 99 { WSMOUSE_TYPE_BLUETOOTH, "bluetooth" }, 100 }; 101 102 static struct nameint dpytype_tab[] = { 103 { WSDISPLAY_TYPE_UNKNOWN, "unknown" }, 104 { WSDISPLAY_TYPE_PM_MONO, "dec-pm-mono" }, 105 { WSDISPLAY_TYPE_PM_COLOR, "dec-pm-color" }, 106 { WSDISPLAY_TYPE_CFB, "dec-cfb" }, 107 { WSDISPLAY_TYPE_XCFB, "dec-xcfb" }, 108 { WSDISPLAY_TYPE_MFB, "dec-mfb" }, 109 { WSDISPLAY_TYPE_SFB, "dec-sfb" }, 110 { WSDISPLAY_TYPE_ISAVGA, "vga-isa" }, 111 { WSDISPLAY_TYPE_PCIVGA, "vga-pci" }, 112 { WSDISPLAY_TYPE_TGA, "dec-tga-pci" }, 113 { WSDISPLAY_TYPE_SFBP, "dec-sfb+" }, 114 { WSDISPLAY_TYPE_PCIMISC, "generic-pci" }, 115 { WSDISPLAY_TYPE_NEXTMONO, "next-mono" }, 116 { WSDISPLAY_TYPE_PX, "dec-px" }, 117 { WSDISPLAY_TYPE_PXG, "dec-pxg" }, 118 { WSDISPLAY_TYPE_TX, "dec-tx" }, 119 { WSDISPLAY_TYPE_HPCFB, "generic-hpc" }, 120 { WSDISPLAY_TYPE_VIDC, "arm-vidc" }, 121 { WSDISPLAY_TYPE_SPX, "dec-spx" }, 122 { WSDISPLAY_TYPE_GPX, "dec-gpx" }, 123 { WSDISPLAY_TYPE_LCG, "dec-lcg" }, 124 { WSDISPLAY_TYPE_VAX_MONO, "dec-vax-mono" }, 125 { WSDISPLAY_TYPE_SB_P9100, "sparcbook-p9100" }, 126 { WSDISPLAY_TYPE_EGA, "ega" }, 127 { WSDISPLAY_TYPE_DCPVR, "dreamcast-pvr" }, 128 { WSDISPLAY_TYPE_GATOR, "hp-gator" }, 129 { WSDISPLAY_TYPE_TOPCAT, "hp-topcat" }, 130 { WSDISPLAY_TYPE_RENAISSANCE, "hp-renaissance" }, 131 { WSDISPLAY_TYPE_CATSEYE, "hp-catseye" }, 132 { WSDISPLAY_TYPE_DAVINCI, "hp-davinci" }, 133 { WSDISPLAY_TYPE_TIGER, "hp-tiger" }, 134 { WSDISPLAY_TYPE_HYPERION, "hp-hyperion" }, 135 { WSDISPLAY_TYPE_AMIGACC, "amiga-cc" }, 136 { WSDISPLAY_TYPE_SUN24, "sun24" }, 137 { WSDISPLAY_TYPE_NEWPORT, "sgi-newport" }, 138 { WSDISPLAY_TYPE_GR2, "sgi-gr2" }, 139 { WSDISPLAY_TYPE_SUNCG12, "suncg12" }, 140 { WSDISPLAY_TYPE_SUNCG14, "suncg14" }, 141 { WSDISPLAY_TYPE_SUNTCX, "suntcx" }, 142 { WSDISPLAY_TYPE_SUNFFB, "sunffb" }, 143 }; 144 145 static struct nameint kbdenc_tab[] = { 146 KB_ENCTAB 147 }; 148 149 static struct nameint kbdvar_tab[] = { 150 KB_VARTAB 151 }; 152 153 static struct nameint color_tab[] = { 154 { WSCOL_UNSUPPORTED, "unsupported" }, 155 { WSCOL_BLACK, "black" }, 156 { WSCOL_RED, "red" }, 157 { WSCOL_GREEN, "green" }, 158 { WSCOL_BROWN, "brown" }, 159 { WSCOL_BLUE, "blue" }, 160 { WSCOL_MAGENTA, "magenta" }, 161 { WSCOL_CYAN, "cyan" }, 162 { WSCOL_WHITE, "white" }, 163 }; 164 165 static struct nameint attr_tab[] = { 166 { WSATTR_NONE, "none" }, 167 { WSATTR_REVERSE, "reverse" }, 168 { WSATTR_HILIT, "hilit" }, 169 { WSATTR_BLINK, "blink" }, 170 { WSATTR_UNDERLINE, "underline" }, 171 { WSATTR_WSCOLORS, "color" }, 172 }; 173 174 static struct field *field_tab; 175 static int field_tab_len; 176 177 static const char *int2name(int, int, struct nameint *, int); 178 static int name2int(char *, struct nameint *, int); 179 static void print_kmap(struct wskbd_map_data *); 180 static unsigned int rd_bitfield(const char *); 181 static void pr_bitfield(unsigned int); 182 183 void 184 field_setup(struct field *ftab, int len) 185 { 186 187 field_tab = ftab; 188 field_tab_len = len; 189 } 190 191 struct field * 192 field_by_name(char *name) 193 { 194 int i; 195 196 for (i = 0; i < field_tab_len; i++) 197 if (strcmp(field_tab[i].name, name) == 0) 198 return field_tab + i; 199 200 errx(EXIT_FAILURE, "%s: not found", name); 201 } 202 203 struct field * 204 field_by_value(void *addr) 205 { 206 int i; 207 208 for (i = 0; i < field_tab_len; i++) 209 if (field_tab[i].valp == addr) 210 return field_tab + i; 211 212 errx(EXIT_FAILURE, "internal error: field_by_value: not found"); 213 } 214 215 void 216 field_disable_by_value(void *addr) 217 { 218 struct field *f; 219 220 f = field_by_value(addr); 221 f->flags |= FLG_DISABLED; 222 } 223 224 static const char * 225 int2name(int val, int uflag, struct nameint *tab, int len) 226 { 227 static char tmp[20]; 228 int i; 229 230 for (i = 0; i < len; i++) 231 if (tab[i].value == val) 232 return tab[i].name; 233 234 if (uflag) { 235 (void)snprintf(tmp, sizeof(tmp), "unknown_%d", val); 236 return tmp; 237 } else 238 return NULL; 239 } 240 241 static int 242 name2int(char *val, struct nameint *tab, int len) 243 { 244 int i; 245 246 for (i = 0; i < len; i++) 247 if (strcmp(tab[i].name, val) == 0) 248 return tab[i].value; 249 return -1; 250 } 251 252 void 253 pr_field(struct field *f, const char *sep) 254 { 255 const char *p; 256 unsigned int flags; 257 int first, i, mask; 258 259 if (sep) 260 (void)printf("%s%s", f->name, sep); 261 262 switch (f->format) { 263 case FMT_UINT: 264 (void)printf("%u", *((unsigned int *) f->valp)); 265 break; 266 case FMT_STRING: 267 (void)printf("\"%s\"", *((char **) f->valp)); 268 break; 269 case FMT_BITFIELD: 270 pr_bitfield(*((unsigned int *) f->valp)); 271 break; 272 case FMT_KBDTYPE: 273 p = int2name(*((unsigned int *) f->valp), 1, 274 kbtype_tab, TABLEN(kbtype_tab)); 275 (void)printf("%s", p); 276 break; 277 case FMT_MSTYPE: 278 p = int2name(*((unsigned int *) f->valp), 1, 279 mstype_tab, TABLEN(mstype_tab)); 280 (void)printf("%s", p); 281 break; 282 case FMT_DPYTYPE: 283 p = int2name(*((unsigned int *) f->valp), 1, 284 dpytype_tab, TABLEN(dpytype_tab)); 285 (void)printf("%s", p); 286 break; 287 case FMT_KBDENC: 288 p = int2name(KB_ENCODING(*((unsigned int *) f->valp)), 1, 289 kbdenc_tab, TABLEN(kbdenc_tab)); 290 (void)printf("%s", p); 291 292 flags = KB_VARIANT(*((unsigned int *) f->valp)); 293 for (i = 0; i < 32; i++) { 294 if (!(flags & (1 << i))) 295 continue; 296 p = int2name(flags & (1 << i), 1, 297 kbdvar_tab, TABLEN(kbdvar_tab)); 298 (void)printf(".%s", p); 299 } 300 break; 301 case FMT_KBMAP: 302 print_kmap((struct wskbd_map_data *) f->valp); 303 break; 304 case FMT_COLOR: 305 p = int2name(*((unsigned int *) f->valp), 1, 306 color_tab, TABLEN(color_tab)); 307 (void)printf("%s", p); 308 break; 309 case FMT_ATTRS: 310 mask = 0x10; 311 first = 1; 312 while (mask > 0) { 313 if (*((unsigned int *) f->valp) & mask) { 314 p = int2name(*((unsigned int *) f->valp) & mask, 315 1, attr_tab, TABLEN(attr_tab)); 316 (void)printf("%s%s", first ? "" : ",", p); 317 first = 0; 318 } 319 mask >>= 1; 320 } 321 if (first) 322 (void)printf("none"); 323 break; 324 default: 325 errx(EXIT_FAILURE, "internal error: pr_field: no format %d", 326 f->format); 327 break; 328 } 329 330 (void)printf("\n"); 331 } 332 333 static void 334 pr_bitfield(unsigned int f) 335 { 336 337 if (f == 0) 338 (void)printf("none"); 339 else { 340 int i, first, mask; 341 342 for (i = 0, first = 1, mask = 1; i < sizeof(f) * 8; i++) { 343 if (f & mask) { 344 (void)printf("%s%d", first ? "" : " ", i); 345 first = 0; 346 } 347 mask = mask << 1; 348 } 349 } 350 } 351 352 void 353 rd_field(struct field *f, char *val, int merge) 354 { 355 int i; 356 unsigned int u; 357 char *p; 358 struct wscons_keymap *mp; 359 360 switch (f->format) { 361 case FMT_UINT: 362 if (sscanf(val, "%u", &u) != 1) 363 errx(EXIT_FAILURE, "%s: not a number", val); 364 if (merge) 365 *((unsigned int *) f->valp) += u; 366 else 367 *((unsigned int *) f->valp) = u; 368 break; 369 case FMT_STRING: 370 if ((*((char **) f->valp) = strdup(val)) == NULL) 371 err(EXIT_FAILURE, "strdup"); 372 break; 373 case FMT_BITFIELD: 374 *((unsigned int *) f->valp) = rd_bitfield(val); 375 break; 376 case FMT_KBDENC: 377 p = strchr(val, '.'); 378 if (p != NULL) 379 *p++ = '\0'; 380 381 i = name2int(val, kbdenc_tab, TABLEN(kbdenc_tab)); 382 if (i == -1) 383 errx(EXIT_FAILURE, "%s: not a valid encoding", val); 384 *((unsigned int *) f->valp) = i; 385 386 while (p) { 387 val = p; 388 p = strchr(p, '.'); 389 if (p != NULL) 390 *p++ = '\0'; 391 i = name2int(val, kbdvar_tab, TABLEN(kbdvar_tab)); 392 if (i == -1) 393 errx(EXIT_FAILURE, "%s: not a valid variant", 394 val); 395 *((unsigned int *) f->valp) |= i; 396 } 397 break; 398 case FMT_KBMAP: 399 if (! merge) 400 kbmap.maplen = 0; 401 map_scan_setinput(val); 402 yyparse(); 403 if (merge) { 404 if (newkbmap.maplen < kbmap.maplen) 405 newkbmap.maplen = kbmap.maplen; 406 for (i = 0; i < kbmap.maplen; i++) { 407 mp = newkbmap.map + i; 408 if (mp->command == KS_voidSymbol && 409 mp->group1[0] == KS_voidSymbol && 410 mp->group1[1] == KS_voidSymbol && 411 mp->group2[0] == KS_voidSymbol && 412 mp->group2[1] == KS_voidSymbol) 413 *mp = kbmap.map[i]; 414 } 415 } 416 kbmap.maplen = newkbmap.maplen; 417 bcopy(newkbmap.map, kbmap.map, 418 kbmap.maplen * sizeof(struct wscons_keymap)); 419 break; 420 case FMT_COLOR: 421 i = name2int(val, color_tab, TABLEN(color_tab)); 422 if (i == -1) 423 errx(EXIT_FAILURE, "%s: not a valid color", val); 424 *((unsigned int *) f->valp) = i; 425 break; 426 case FMT_ATTRS: 427 p = val; 428 while (p) { 429 val = p; 430 p = strchr(p, ','); 431 if (p != NULL) 432 *p++ = '\0'; 433 i = name2int(val, attr_tab, TABLEN(attr_tab)); 434 if (i == -1) 435 errx(EXIT_FAILURE, "%s: not a valid attribute", 436 val); 437 *((unsigned int *) f->valp) |= i; 438 } 439 break; 440 default: 441 errx(EXIT_FAILURE, "internal error: rd_field: no format %d", 442 f->format); 443 break; 444 } 445 } 446 447 static unsigned int 448 rd_bitfield(const char *str) 449 { 450 const char *ptr; 451 char *ep; 452 long lval; 453 unsigned int result; 454 455 ep = NULL; 456 ptr = str; 457 result = 0; 458 while (*ptr != '\0') { 459 errno = 0; 460 lval = strtol(ptr, &ep, 10); 461 if (*ep != '\0' && *ep != ' ') 462 errx(EXIT_FAILURE, "%s: not a valid number list", str); 463 if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) 464 errx(EXIT_FAILURE, "%s: not a valid number list", str); 465 if (lval >= sizeof(result) * 8) 466 errx(EXIT_FAILURE, "%ld: number out of range", lval); 467 result |= (1 << lval); 468 469 ptr = ep; 470 while (*ptr == ' ') 471 ptr++; 472 } 473 474 return result; 475 } 476 477 static void 478 print_kmap(struct wskbd_map_data *map) 479 { 480 int i; 481 struct wscons_keymap *mp; 482 483 for (i = 0; i < map->maplen; i++) { 484 mp = map->map + i; 485 486 if (mp->command == KS_voidSymbol && 487 mp->group1[0] == KS_voidSymbol && 488 mp->group1[1] == KS_voidSymbol && 489 mp->group2[0] == KS_voidSymbol && 490 mp->group2[1] == KS_voidSymbol) 491 continue; 492 (void)printf("\n"); 493 (void)printf("keycode %u =", i); 494 if (mp->command != KS_voidSymbol) 495 (void)printf(" %s", ksym2name(mp->command)); 496 (void)printf(" %s", ksym2name(mp->group1[0])); 497 if (mp->group1[0] != mp->group1[1] || 498 mp->group1[0] != mp->group2[0] || 499 mp->group1[0] != mp->group2[1]) { 500 (void)printf(" %s", ksym2name(mp->group1[1])); 501 if (mp->group1[0] != mp->group2[0] || 502 mp->group1[1] != mp->group2[1]) { 503 (void)printf(" %s", ksym2name(mp->group2[0])); 504 (void)printf(" %s", ksym2name(mp->group2[1])); 505 } 506 } 507 } 508 } 509