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