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 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Generic keyboard support: translation 31 * 32 * This module is project private. Please see PSARC/1998/176 and 33 * PSARC/1998/026 for references to the kbtrans module. 34 * 35 * It is believed that it is safe to call these functions within debugger mode 36 * except kbtrans_dprintf. Debugger mode is a single threaded mode where most 37 * kernel services are not available, including memory allocation. Debugger 38 * mode is for kmdb and OBP debugging, where the debugger calls back into the 39 * kernel to obtain console input. 40 * 41 * Please be _very_ careful about what external functions you call. 42 */ 43 44 #define KEYMAP_SIZE_VARIABLE 45 46 #include <sys/types.h> 47 #include <sys/cred.h> 48 #include <sys/ddi.h> 49 #include <sys/sunddi.h> 50 #include <sys/kmem.h> 51 #include <sys/kbd.h> 52 #include <sys/cmn_err.h> 53 #include <sys/modctl.h> 54 #include <sys/kbio.h> 55 #include <sys/vuid_event.h> 56 #include <sys/consdev.h> 57 #include <sys/kbtrans.h> 58 #include <sys/errno.h> 59 #include <sys/promif.h> 60 #include <sys/varargs.h> 61 #include "kbtrans_lower.h" 62 63 /* 64 * Internal Function Prototypes 65 */ 66 static boolean_t kbtrans_do_compose(struct kbtrans_lower *, ushort_t, 67 ushort_t, ushort_t *); 68 static void kbtrans_translate(struct kbtrans_lower *, 69 struct keyboard_callback *, kbtrans_key_t, 70 enum keystate); 71 /* 72 * kbtrans_processkey: 73 * 74 * lower - state information used by the calling driver 75 * this parameter is passed back to the callback routines. 76 * key - scancode 77 * state - KEY_PRESSED / KEY_RELEASED 78 * 79 * This routine checks to see if there is a raw callback, and calls it 80 * if it exists. If there is no raw callback, the key is translated. 81 * The raw callback allows the driver that called the translation module 82 * to be passed untranslated scancodes. 83 */ 84 void 85 kbtrans_processkey(struct kbtrans_lower *lower, 86 struct keyboard_callback *cb, 87 kbtrans_key_t key, 88 enum keystate state) 89 { 90 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "kbtrans_processkey: " 91 "newstate=%d key=%d", state, key)); 92 93 /* 94 * If there is a raw routine, then call it and return. 95 */ 96 if (cb->kc_keypressed_raw != NULL) { 97 98 if (state == KEY_PRESSED) { 99 100 cb->kc_keypressed_raw(lower->kbtrans_upper, key); 101 } else { 102 103 cb->kc_keyreleased_raw(lower->kbtrans_upper, key); 104 } 105 106 return; 107 } 108 109 /* 110 * translate the scancode into a key. 111 */ 112 kbtrans_translate(lower, cb, key, state); 113 } 114 115 116 /* 117 * kbtrans_translate: 118 * 119 * lower - state information used by the calling driver 120 * this parameter is passed back to the callback routines. 121 * key - scan code 122 * state - KEY_PRESSED / KEY_RELEASED 123 * 124 * Called to process key events if we are in TR_ASCII or TR_EVENT 125 * (sunview) mode. This routine will call the appropriate translation_callback 126 * for the character when it is done translating it. 127 */ 128 static void 129 kbtrans_translate(struct kbtrans_lower *lower, 130 struct keyboard_callback *cb, 131 kbtrans_key_t key, 132 enum keystate newstate) 133 { 134 unsigned shiftmask; 135 register ushort_t entry; 136 register ushort_t entrytype; 137 ushort_t result_iso; 138 unsigned short *ke; 139 int i; 140 boolean_t good_compose; 141 142 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "KEY TRANSLATE " 143 "newstate=0x%x key=0x%x\n", newstate, key)); 144 145 if (lower->kbtrans_keyboard == NULL) { 146 /* 147 * Nobody has told us about this keyboard yet. 148 */ 149 return; 150 } 151 152 /* 153 * Get the current state of the shiftmask 154 */ 155 shiftmask = lower->kbtrans_shiftmask; 156 157 /* 158 * If the key has been released, then or in the UPMASK flag. 159 */ 160 if (newstate == KEY_RELEASED) 161 shiftmask |= UPMASK; 162 163 /* 164 * Based on the shiftmask, lookup the keymap entry that we should 165 * be using for this scancode. 166 */ 167 ke = kbtrans_find_entry(lower, shiftmask, key); 168 169 if (ke == NULL) { 170 /* 171 * This is a gross error. Cancel the repeat key and exit, 172 * we can not translate this scancode. 173 */ 174 cb->kc_cancel_repeat(lower->kbtrans_upper); 175 176 return; 177 } 178 179 /* 180 * Get the key for this scancode. 181 */ 182 entry = *ke; 183 184 if (entry == NONL) { 185 /* 186 * NONL appears only in the Num Lock table, and indicates that 187 * this key is not affected by Num Lock. This means we should 188 * ask for the table we would have gotten had Num Lock not been 189 * down, and translate using that table. 190 */ 191 ke = kbtrans_find_entry(lower, shiftmask & ~NUMLOCKMASK, 192 key); 193 194 if (ke == NULL) { 195 /* 196 * This is a gross error. Cancel the repeat key and 197 * exit, we can not translate this scancode. 198 */ 199 cb->kc_cancel_repeat(lower->kbtrans_upper); 200 201 return; 202 } 203 204 /* 205 * Get the new key for this scancode. 206 */ 207 entry = *ke; 208 } 209 210 /* 211 * The entrytype indicates what category of key we are processing. 212 * Categories include shift keys, function keys, and numeric keypad 213 * keys. 214 */ 215 entrytype = (ushort_t)(entry & 0xFF00); 216 217 if (entrytype == SHIFTKEYS) { 218 /* 219 * Handle the state of toggle shifts specially. 220 * Ups should be ignored, and downs should be mapped to ups if 221 * that shift is currently on. 222 */ 223 if ((1 << (entry & 0x0F)) & 224 lower->kbtrans_keyboard->k_toggleshifts) { 225 if ((1 << (entry & 0x0F)) & 226 lower->kbtrans_togglemask) { 227 newstate = KEY_RELEASED; /* toggling off */ 228 } else { 229 newstate = KEY_PRESSED; /* toggling on */ 230 } 231 } 232 } else { 233 /* 234 * Handle Compose and floating accent key sequences 235 */ 236 switch (lower->kbtrans_state) { 237 case COMPOSE1: 238 if (newstate == KEY_RELEASED) 239 240 return; 241 242 if (entry < ASCII_SET_SIZE) { 243 if (lower->kbtrans_compose_map[entry] >= 0) { 244 lower->kbtrans_compose_key = entry; 245 lower->kbtrans_state = COMPOSE2; 246 247 return; 248 } 249 } 250 lower->kbtrans_state = NORMAL; 251 lower->kbtrans_led_state &= ~LED_COMPOSE; 252 253 cb->kc_setled(lower->kbtrans_upper); 254 255 return; 256 257 case COMPOSE2: 258 if (newstate == KEY_RELEASED) 259 return; 260 261 /* next state is "normal" */ 262 lower->kbtrans_state = NORMAL; 263 lower->kbtrans_led_state &= ~LED_COMPOSE; 264 265 cb->kc_setled(lower->kbtrans_upper); 266 267 good_compose = kbtrans_do_compose(lower, 268 lower->kbtrans_compose_key, entry, 269 &result_iso); 270 if (good_compose) { 271 if (lower->kbtrans_compat) 272 result_iso += ISO_FIRST; 273 else 274 result_iso += EUC_FIRST; 275 cb->kc_keypressed(lower->kbtrans_upper, 276 entrytype, key, result_iso); 277 } 278 return; 279 280 case FLTACCENT: 281 if (newstate == KEY_RELEASED) 282 283 return; 284 285 /* next state is "normal" */ 286 lower->kbtrans_state = NORMAL; 287 for (i = 0; 288 (lower->kbtrans_fltaccent_table[i].fa_entry 289 != lower->kbtrans_fltaccent_entry) || 290 (lower->kbtrans_fltaccent_table[i].ascii != entry); 291 i++) { 292 if (lower->kbtrans_fltaccent_table[i].fa_entry 293 == 0) { 294 /* Invalid second key: ignore key */ 295 296 return; 297 } 298 } 299 300 cb->kc_keypressed(lower->kbtrans_upper, entrytype, 301 key, (lower->kbtrans_compat ? 302 ISO_FIRST : EUC_FIRST) + 303 lower->kbtrans_fltaccent_table[i].iso); 304 305 return; 306 } 307 } 308 309 /* 310 * If the key is going down, and it's not one of the keys that doesn't 311 * auto-repeat, set up the auto-repeat timeout. 312 * 313 * The keys that don't auto-repeat are the Compose key, 314 * the shift keys, the "bucky bit" keys, the "floating accent" keys, 315 * and the function keys when in TR_EVENT mode. 316 */ 317 if (newstate == KEY_PRESSED && entrytype != SHIFTKEYS && 318 entrytype != BUCKYBITS && entrytype != FUNNY && 319 entrytype != FA_CLASS) { 320 321 if (lower->kbtrans_repeatkey != key) { 322 cb->kc_cancel_repeat(lower->kbtrans_upper); 323 cb->kc_setup_repeat(lower->kbtrans_upper, entrytype, 324 key); 325 } 326 /* key going up */ 327 } else if (key == lower->kbtrans_repeatkey) { 328 329 cb->kc_cancel_repeat(lower->kbtrans_upper); 330 } 331 332 if (newstate == KEY_RELEASED) { 333 cb->kc_keyreleased(lower->kbtrans_upper, key); 334 } 335 336 /* 337 * We assume here that keys other than shift keys and bucky keys have 338 * entries in the "up" table that cause nothing to be done, and thus we 339 * don't have to check for newstate == KEY_RELEASED. 340 */ 341 switch (entrytype) { 342 343 case 0x0: /* regular key */ 344 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, 345 entry | lower->kbtrans_buckybits); 346 break; 347 348 case SHIFTKEYS: { 349 uint_t shiftbit = 1 << (entry & 0x0F); 350 351 /* Modify toggle state (see toggle processing above) */ 352 if (shiftbit & lower->kbtrans_keyboard->k_toggleshifts) { 353 if (newstate == KEY_RELEASED) { 354 if (shiftbit == CAPSMASK) { 355 lower->kbtrans_led_state &= 356 ~LED_CAPS_LOCK; 357 358 cb->kc_setled(lower->kbtrans_upper); 359 360 } else if (shiftbit == NUMLOCKMASK) { 361 lower->kbtrans_led_state &= 362 ~LED_NUM_LOCK; 363 364 cb->kc_setled(lower->kbtrans_upper); 365 } 366 lower->kbtrans_togglemask &= ~shiftbit; 367 } else { 368 if (shiftbit == CAPSMASK) { 369 lower->kbtrans_led_state |= 370 LED_CAPS_LOCK; 371 372 cb->kc_setled(lower->kbtrans_upper); 373 } else if (shiftbit == NUMLOCKMASK) { 374 lower->kbtrans_led_state |= 375 LED_NUM_LOCK; 376 377 cb->kc_setled(lower->kbtrans_upper); 378 } 379 lower->kbtrans_togglemask |= shiftbit; 380 } 381 } 382 383 if (newstate == KEY_RELEASED) 384 lower->kbtrans_shiftmask &= ~shiftbit; 385 else 386 lower->kbtrans_shiftmask |= shiftbit; 387 388 if (newstate == KEY_PRESSED) { 389 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, 390 entry); 391 } 392 393 break; 394 } 395 396 case BUCKYBITS: 397 lower->kbtrans_buckybits ^= 1 << (7 + (entry & 0x0F)); 398 399 if (newstate == KEY_PRESSED) { 400 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, 401 entry); 402 } 403 404 break; 405 406 case FUNNY: 407 switch (entry) { 408 case NOP: 409 break; 410 411 case IDLE: 412 /* Fall thru into RESET code */ 413 /* FALLTHRU */ 414 case RESET: 415 case ERROR: 416 lower->kbtrans_shiftmask &= 417 lower->kbtrans_keyboard->k_idleshifts; 418 419 lower->kbtrans_shiftmask |= 420 lower->kbtrans_togglemask; 421 422 lower->kbtrans_buckybits &= 423 lower->kbtrans_keyboard->k_idlebuckys; 424 425 cb->kc_cancel_repeat(lower->kbtrans_upper); 426 427 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, 428 entry); 429 430 break; 431 432 433 case COMPOSE: 434 lower->kbtrans_state = COMPOSE1; 435 lower->kbtrans_led_state |= LED_COMPOSE; 436 cb->kc_setled(lower->kbtrans_upper); 437 break; 438 /* 439 * Remember when adding new entries that, 440 * if they should NOT auto-repeat, 441 * they should be put into the IF statement 442 * just above this switch block. 443 */ 444 default: 445 /* Ignore it */ 446 break; 447 } 448 break; 449 450 case FA_CLASS: 451 if (lower->kbtrans_state == NORMAL) { 452 lower->kbtrans_fltaccent_entry = entry; 453 lower->kbtrans_state = FLTACCENT; 454 } 455 break; 456 457 case STRING: 458 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry); 459 460 break; 461 462 case FUNCKEYS: 463 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry); 464 465 break; 466 467 /* 468 * Remember when adding new entries that, 469 * if they should NOT auto-repeat, 470 * they should be put into the IF statement 471 * just above this switch block. 472 */ 473 case PADKEYS: 474 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry); 475 476 break; 477 } 478 } 479 480 /* 481 * kbtrans_do_compose: 482 * Given a two key compose sequence, lookup the iso equivalent and put 483 * the result in the result_iso_ptr. 484 */ 485 static boolean_t 486 kbtrans_do_compose(struct kbtrans_lower *lower, 487 ushort_t first_entry, 488 ushort_t second_entry, 489 ushort_t *result_iso_ptr) 490 { 491 struct compose_sequence_t *ptr; 492 ushort_t tmp; 493 494 /* 495 * Validate the second keystroke. 496 */ 497 if (second_entry >= ASCII_SET_SIZE) 498 return (B_FALSE); 499 500 if (lower->kbtrans_compose_map[second_entry] < 0) 501 return (B_FALSE); 502 503 /* 504 * Get them in code order, rather than press order. 505 */ 506 if (first_entry > second_entry) { 507 tmp = first_entry; 508 first_entry = second_entry; 509 second_entry = tmp; 510 } 511 512 ptr = lower->kbtrans_compose_table + 513 lower->kbtrans_compose_map[first_entry]; 514 515 while (ptr->first == first_entry) { 516 if (ptr->second == second_entry) { 517 *result_iso_ptr = ptr->iso; 518 519 return (B_TRUE); 520 } 521 ptr++; 522 } 523 return (B_FALSE); 524 } 525 526 527 /* 528 * kbtrans_find_entry: 529 * This routine finds the entry corresponding to the current shift 530 * state and keycode. 531 */ 532 unsigned short * 533 kbtrans_find_entry(struct kbtrans_lower *lower, 534 register uint_t mask, 535 kbtrans_key_t key_station) 536 { 537 register struct keyboard *kp; 538 keymap_entry_t *km; 539 struct exception_map *ex; 540 541 kp = lower->kbtrans_keyboard; 542 543 if (kp == NULL) 544 return (NULL); 545 546 if (key_station < 0 || key_station >= kp->k_keymap_size) 547 return (NULL); 548 549 ex = kp->k_except; 550 if (ex != NULL) { 551 for (; ex->exc_care != 0; ex++) { 552 if ((mask & ex->exc_care) == ex->exc_mask && 553 key_station == ex->exc_key) 554 return (&ex->exc_entry); 555 } 556 } 557 558 if (mask & UPMASK) 559 km = kp->k_up; 560 else if (mask & NUMLOCKMASK) 561 km = kp->k_numlock; 562 else if (mask & CTRLMASK) 563 km = kp->k_control; 564 else if (mask & ALTGRAPHMASK) 565 km = kp->k_altgraph; 566 else if (mask & SHIFTMASK) 567 km = kp->k_shifted; 568 else if (mask & CAPSMASK) 569 km = kp->k_caps; 570 else km = kp->k_normal; 571 572 return (&km[key_station]); 573 } 574 575 #ifdef DEBUG 576 /*ARGSUSED*/ 577 void 578 kbtrans_dprintf(void *un, const char *fmt, ...) 579 { 580 char buf[256]; 581 va_list ap; 582 583 va_start(ap, fmt); 584 (void) vsprintf(buf, fmt, ap); 585 va_end(ap); 586 587 cmn_err(CE_CONT, "kbtrans: %s", buf); 588 } 589 #endif 590