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