1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 #ifndef lint 23 #ident "%Z%%M% %I% %E% SMI" 24 #endif 25 26 /* 27 * Copyright (c) 1988 by Sun Microsystems, Inc. 28 */ 29 30 #include <sys/types.h> 31 #include <ctype.h> 32 #include <stdio.h> 33 #include <fcntl.h> 34 #include <sys/kbd.h> 35 #include <sys/kbio.h> 36 #include <errno.h> 37 38 typedef enum { 39 SM_INVALID, /* this shift mask is invalid for this keyboard */ 40 SM_NORMAL, /* "normal", valid shift mask */ 41 SM_NUMLOCK, /* "Num Lock" shift mask */ 42 SM_UP /* "Up" shift mask */ 43 } smtype_t; 44 45 typedef struct { 46 char *sm_name; 47 int sm_mask; 48 smtype_t sm_type; 49 } smentry_t; 50 51 52 smentry_t shiftmasks[] = { 53 { "base", 0, SM_NORMAL }, 54 { "shift", SHIFTMASK, SM_NORMAL }, 55 { "caps", CAPSMASK, SM_NORMAL }, 56 { "ctrl", CTRLMASK, SM_NORMAL }, 57 { "altg", ALTGRAPHMASK, SM_NORMAL }, 58 { "numl", NUMLOCKMASK, SM_NUMLOCK }, 59 { "up", UPMASK, SM_UP }, 60 }; 61 62 #define NSHIFTS (sizeof (shiftmasks) / sizeof (shiftmasks[0])) 63 64 static void printentry(struct kiockeymap *kio); 65 static void printchar(int character, int delim); 66 67 /*ARGSUSED*/ 68 int 69 main(argc, argv) 70 int argc; 71 char **argv; 72 { 73 register int kbdfd; 74 register int keystation; 75 register int shift; 76 int ktype; 77 struct kiockeymap keyentry[NSHIFTS]; 78 register int allsame; 79 80 if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) { 81 perror("dumpkeys: /dev/kbd"); 82 return (1); 83 } 84 if (ioctl(kbdfd, KIOCTYPE, &ktype) < 0) { 85 perror("dumpkeys: ioctl(KIOCTYPE)"); 86 return (1); 87 } 88 /* if no keyboard detected, or ascii terminal, exit silently */ 89 if (ktype == KB_ASCII || ktype < 0) 90 exit(0); 91 92 /* 93 * See which shift masks are valid for this keyboard. 94 * We do that by trying to get the entry for keystation 0 and that 95 * shift mask; if the "ioctl" fails, we assume it's because the shift 96 * mask is invalid. 97 */ 98 for (shift = 0; shift < NSHIFTS; shift++) { 99 keyentry[shift].kio_tablemask = 100 shiftmasks[shift].sm_mask; 101 keyentry[shift].kio_station = 0; 102 if (ioctl(kbdfd, KIOCGKEY, &keyentry[shift]) < 0) 103 shiftmasks[shift].sm_type = SM_INVALID; 104 } 105 106 /* 107 * Loop until we get an EINVAL, so we don't have to know 108 * how big the table might be. 109 */ 110 for (keystation = 0; ; keystation++) { 111 for (shift = 0; shift < NSHIFTS; shift++) { 112 if (shiftmasks[shift].sm_type != SM_INVALID) { 113 keyentry[shift].kio_tablemask = 114 shiftmasks[shift].sm_mask; 115 keyentry[shift].kio_station = keystation; 116 if (ioctl(kbdfd, KIOCGKEY, 117 &keyentry[shift]) < 0) { 118 if (errno == EINVAL) 119 return (0); 120 perror("dumpkeys: KIOCGKEY"); 121 return (1); 122 } 123 } 124 } 125 126 (void) printf("key %d\t", keystation); 127 128 /* 129 * See if all the "normal" entries (all but the Num Lock and Up 130 * entries) are the same. 131 */ 132 allsame = 1; 133 for (shift = 1; shift < NSHIFTS; shift++) { 134 if (shiftmasks[shift].sm_type == SM_NORMAL) { 135 if (keyentry[0].kio_entry 136 != keyentry[shift].kio_entry) { 137 allsame = 0; 138 break; 139 } 140 } 141 } 142 143 if (allsame) { 144 /* 145 * All of the "normal" entries are the same; just print 146 * "all". 147 */ 148 (void) printf(" all "); 149 printentry(&keyentry[0]); 150 } else { 151 /* 152 * The normal entries aren't all the same; print them 153 * individually. 154 */ 155 for (shift = 0; shift < NSHIFTS; shift++) { 156 if (shiftmasks[shift].sm_type == SM_NORMAL) { 157 (void) printf(" %s ", 158 shiftmasks[shift].sm_name); 159 printentry(&keyentry[shift]); 160 } 161 } 162 } 163 if (allsame && keyentry[0].kio_entry == HOLE) { 164 /* 165 * This key is a "hole"; if either the Num Lock or Up 166 * entry isn't a "hole", print it. 167 */ 168 for (shift = 0; shift < NSHIFTS; shift++) { 169 switch (shiftmasks[shift].sm_type) { 170 171 case SM_NUMLOCK: 172 case SM_UP: 173 if (keyentry[shift].kio_entry 174 != HOLE) { 175 (void) printf(" %s ", 176 shiftmasks[shift].sm_name); 177 printentry(&keyentry[shift]); 178 } 179 break; 180 } 181 } 182 } else { 183 /* 184 * This entry isn't a "hole"; if the Num Lock entry 185 * isn't NONL (i.e, if Num Lock actually does 186 * something) print it, and if the Up entry isn't NOP 187 * (i.e., if up transitions on this key actually do 188 * something) print it. 189 */ 190 for (shift = 0; shift < NSHIFTS; shift++) { 191 switch (shiftmasks[shift].sm_type) { 192 193 case SM_NUMLOCK: 194 if (keyentry[shift].kio_entry 195 != NONL) { 196 (void) printf(" %s ", 197 shiftmasks[shift].sm_name); 198 printentry(&keyentry[shift]); 199 } 200 break; 201 202 case SM_UP: 203 if (keyentry[shift].kio_entry 204 != NOP) { 205 (void) printf(" %s ", 206 shiftmasks[shift].sm_name); 207 printentry(&keyentry[shift]); 208 } 209 break; 210 } 211 } 212 } 213 (void) printf("\n"); 214 } 215 } 216 217 static char *shiftkeys[] = { 218 "capslock", 219 "shiftlock", 220 "leftshift", 221 "rightshift", 222 "leftctrl", 223 "rightctrl", 224 "meta", /* not used */ 225 "top", /* not used */ 226 "cmd", /* reserved */ 227 "altgraph", 228 "alt", 229 "numlock", 230 }; 231 232 #define NSHIFTKEYS (sizeof (shiftkeys) / sizeof (shiftkeys[0])) 233 234 static char *buckybits[] = { 235 "metabit", 236 "systembit", 237 }; 238 239 #define NBUCKYBITS (sizeof (buckybits) / sizeof (buckybits[0])) 240 241 static char *funnies[] = { 242 "nop", 243 "oops", 244 "hole", 245 "reset", 246 "error", 247 "idle", 248 "compose", 249 "nonl", 250 }; 251 252 #define NFUNNIES (sizeof (funnies) / sizeof (funnies[0])) 253 254 static char *fa_class[] = { 255 "fa_umlaut", 256 "fa_cflex", 257 "fa_tilde", 258 "fa_cedilla", 259 "fa_acute", 260 "fa_grave", 261 }; 262 263 #define NFA_CLASS (sizeof (fa_class) / sizeof (fa_class[0])) 264 265 typedef struct { 266 char *string; 267 char *name; 268 } builtin_string_t; 269 270 builtin_string_t builtin_strings[] = { 271 { "\033[H", "homearrow" }, 272 { "\033[A", "uparrow" }, 273 { "\033[B", "downarrow" }, 274 { "\033[D", "leftarrow" }, 275 { "\033[C", "rightarrow" }, 276 }; 277 278 #define NBUILTIN_STRINGS (sizeof (builtin_strings) / \ 279 sizeof (builtin_strings[0])) 280 281 static char *fkeysets[] = { 282 "lf", 283 "rf", 284 "tf", 285 "bf", 286 }; 287 288 #define NFKEYSETS (sizeof (fkeysets) / sizeof (fkeysets[0])) 289 290 static char *padkeys[] = { 291 "padequal", 292 "padslash", 293 "padstar", 294 "padminus", 295 "padsep", 296 "pad7", 297 "pad8", 298 "pad9", 299 "padplus", 300 "pad4", 301 "pad5", 302 "pad6", 303 "pad1", 304 "pad2", 305 "pad3", 306 "pad0", 307 "paddot", 308 "padenter", 309 }; 310 311 #define NPADKEYS (sizeof (padkeys) / sizeof (padkeys[0])) 312 313 static void 314 printentry(kio) 315 register struct kiockeymap *kio; 316 { 317 register int entry = (kio->kio_entry & 0x1F); 318 register int fkeyset; 319 register int i; 320 register int c; 321 322 switch (kio->kio_entry >> 8) { 323 324 case 0x0: 325 if (kio->kio_entry == '"') 326 (void) printf("'\"'"); /* special case */ 327 else if (kio->kio_entry == ' ') 328 (void) printf("' '"); /* special case */ 329 else 330 printchar((int)kio->kio_entry, '\''); 331 break; 332 333 case SHIFTKEYS >> 8: 334 if (entry < NSHIFTKEYS) 335 (void) printf("shiftkeys+%s", shiftkeys[entry]); 336 else 337 (void) printf("%#4x", kio->kio_entry); 338 break; 339 340 case BUCKYBITS >> 8: 341 if (entry < NBUCKYBITS) 342 (void) printf("buckybits+%s", buckybits[entry]); 343 else 344 (void) printf("%#4x", kio->kio_entry); 345 break; 346 347 case FUNNY >> 8: 348 if (entry < NFUNNIES) 349 (void) printf("%s", funnies[entry]); 350 else 351 (void) printf("%#4x", kio->kio_entry); 352 break; 353 354 case FA_CLASS >> 8: 355 if (entry < NFA_CLASS) 356 (void) printf("%s", fa_class[entry]); 357 else 358 (void) printf("%#4x", kio->kio_entry); 359 break; 360 361 case STRING >> 8: 362 if (entry < NBUILTIN_STRINGS && strncmp(kio->kio_string, 363 builtin_strings[entry].string, KTAB_STRLEN) == 0) 364 (void) printf("string+%s", builtin_strings[entry].name); 365 else { 366 (void) printf("\""); 367 for (i = 0; 368 i < KTAB_STRLEN && (c = kio->kio_string[i]) != '\0'; 369 i++) 370 printchar(c, '"'); 371 (void) printf("\""); 372 } 373 break; 374 375 case FUNCKEYS >> 8: 376 fkeyset = (int)(kio->kio_entry & 0xF0) >> 4; 377 if (fkeyset < NFKEYSETS) 378 (void) printf("%s(%d)", fkeysets[fkeyset], 379 (entry&0x0F) + 1); 380 else 381 (void) printf("%#4x", kio->kio_entry); 382 break; 383 384 case PADKEYS >> 8: 385 if (entry < NPADKEYS) 386 (void) printf("%s", padkeys[entry]); 387 else 388 (void) printf("%#4x", kio->kio_entry); 389 break; 390 391 default: 392 (void) printf("%#4x", kio->kio_entry); 393 break; 394 } 395 } 396 397 static void 398 printchar(character, delim) 399 int character; 400 int delim; 401 { 402 switch (character) { 403 404 case '\n': 405 (void) printf("'\\n'"); 406 break; 407 408 case '\t': 409 (void) printf("'\\t'"); 410 break; 411 412 case '\b': 413 (void) printf("'\\b'"); 414 break; 415 416 case '\r': 417 (void) printf("'\\r'"); 418 break; 419 420 case '\v': 421 (void) printf("'\\v'"); 422 break; 423 424 case '\\': 425 (void) printf("'\\\\'"); 426 break; 427 428 default: 429 if (isprint(character)) { 430 if (character == delim) 431 (void) printf("'\\'"); 432 (void) printf("%c", character); 433 } else { 434 if (character < 040) 435 (void) printf("^%c", character + 0100); 436 else 437 (void) printf("'\\%.3o'", character); 438 } 439 break; 440 } 441 } 442