17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * Generic keyboard support: translation
297c478bd9Sstevel@tonic-gate *
307c478bd9Sstevel@tonic-gate * This module is project private. Please see PSARC/1998/176 and
317c478bd9Sstevel@tonic-gate * PSARC/1998/026 for references to the kbtrans module.
327c478bd9Sstevel@tonic-gate *
337c478bd9Sstevel@tonic-gate * It is believed that it is safe to call these functions within debugger mode
347c478bd9Sstevel@tonic-gate * except kbtrans_dprintf. Debugger mode is a single threaded mode where most
357c478bd9Sstevel@tonic-gate * kernel services are not available, including memory allocation. Debugger
367c478bd9Sstevel@tonic-gate * mode is for kmdb and OBP debugging, where the debugger calls back into the
377c478bd9Sstevel@tonic-gate * kernel to obtain console input.
387c478bd9Sstevel@tonic-gate *
397c478bd9Sstevel@tonic-gate * Please be _very_ careful about what external functions you call.
407c478bd9Sstevel@tonic-gate */
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate #define KEYMAP_SIZE_VARIABLE
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate #include <sys/types.h>
457c478bd9Sstevel@tonic-gate #include <sys/cred.h>
467c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
477c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
487c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
497c478bd9Sstevel@tonic-gate #include <sys/kbd.h>
507c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
517c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
527c478bd9Sstevel@tonic-gate #include <sys/kbio.h>
537c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h>
547c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
557c478bd9Sstevel@tonic-gate #include <sys/kbtrans.h>
567c478bd9Sstevel@tonic-gate #include <sys/errno.h>
577c478bd9Sstevel@tonic-gate #include <sys/promif.h>
587c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
597c478bd9Sstevel@tonic-gate #include "kbtrans_lower.h"
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate * Internal Function Prototypes
637c478bd9Sstevel@tonic-gate */
64*adc2b73dSToomas Soome static boolean_t kbtrans_do_compose(struct kbtrans_lower *, keymap_entry_t,
65*adc2b73dSToomas Soome keymap_entry_t, keymap_entry_t *);
66*adc2b73dSToomas Soome static void kbtrans_translate(struct kbtrans_lower *,
67*adc2b73dSToomas Soome struct keyboard_callback *, kbtrans_key_t, enum keystate);
68*adc2b73dSToomas Soome
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate * kbtrans_processkey:
717c478bd9Sstevel@tonic-gate *
727c478bd9Sstevel@tonic-gate * lower - state information used by the calling driver
737c478bd9Sstevel@tonic-gate * this parameter is passed back to the callback routines.
747c478bd9Sstevel@tonic-gate * key - scancode
757c478bd9Sstevel@tonic-gate * state - KEY_PRESSED / KEY_RELEASED
767c478bd9Sstevel@tonic-gate *
777c478bd9Sstevel@tonic-gate * This routine checks to see if there is a raw callback, and calls it
787c478bd9Sstevel@tonic-gate * if it exists. If there is no raw callback, the key is translated.
797c478bd9Sstevel@tonic-gate * The raw callback allows the driver that called the translation module
807c478bd9Sstevel@tonic-gate * to be passed untranslated scancodes.
817c478bd9Sstevel@tonic-gate */
827c478bd9Sstevel@tonic-gate void
kbtrans_processkey(struct kbtrans_lower * lower,struct keyboard_callback * cb,kbtrans_key_t key,enum keystate state)837c478bd9Sstevel@tonic-gate kbtrans_processkey(struct kbtrans_lower *lower,
84*adc2b73dSToomas Soome struct keyboard_callback *cb, kbtrans_key_t key, enum keystate state)
857c478bd9Sstevel@tonic-gate {
867c478bd9Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "kbtrans_processkey: "
87*adc2b73dSToomas Soome "newstate=%d key=%d", state, key));
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate /*
907c478bd9Sstevel@tonic-gate * If there is a raw routine, then call it and return.
917c478bd9Sstevel@tonic-gate */
927c478bd9Sstevel@tonic-gate if (cb->kc_keypressed_raw != NULL) {
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate if (state == KEY_PRESSED) {
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate cb->kc_keypressed_raw(lower->kbtrans_upper, key);
977c478bd9Sstevel@tonic-gate } else {
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate cb->kc_keyreleased_raw(lower->kbtrans_upper, key);
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate return;
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate * translate the scancode into a key.
1077c478bd9Sstevel@tonic-gate */
1087c478bd9Sstevel@tonic-gate kbtrans_translate(lower, cb, key, state);
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate * kbtrans_translate:
1147c478bd9Sstevel@tonic-gate *
1157c478bd9Sstevel@tonic-gate * lower - state information used by the calling driver
1167c478bd9Sstevel@tonic-gate * this parameter is passed back to the callback routines.
1177c478bd9Sstevel@tonic-gate * key - scan code
1187c478bd9Sstevel@tonic-gate * state - KEY_PRESSED / KEY_RELEASED
1197c478bd9Sstevel@tonic-gate *
1207c478bd9Sstevel@tonic-gate * Called to process key events if we are in TR_ASCII or TR_EVENT
1217c478bd9Sstevel@tonic-gate * (sunview) mode. This routine will call the appropriate translation_callback
1227c478bd9Sstevel@tonic-gate * for the character when it is done translating it.
1237c478bd9Sstevel@tonic-gate */
1247c478bd9Sstevel@tonic-gate static void
kbtrans_translate(struct kbtrans_lower * lower,struct keyboard_callback * cb,kbtrans_key_t key,enum keystate newstate)125*adc2b73dSToomas Soome kbtrans_translate(struct kbtrans_lower *lower, struct keyboard_callback *cb,
126*adc2b73dSToomas Soome kbtrans_key_t key, enum keystate newstate)
1277c478bd9Sstevel@tonic-gate {
1287c478bd9Sstevel@tonic-gate unsigned shiftmask;
129*adc2b73dSToomas Soome register keymap_entry_t entry;
130*adc2b73dSToomas Soome register unsigned entrytype;
131*adc2b73dSToomas Soome keymap_entry_t result;
132*adc2b73dSToomas Soome keymap_entry_t *ke;
1337c478bd9Sstevel@tonic-gate int i;
1347c478bd9Sstevel@tonic-gate boolean_t good_compose;
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "KEY TRANSLATE "
137*adc2b73dSToomas Soome "newstate=0x%x key=0x%x\n", newstate, key));
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate if (lower->kbtrans_keyboard == NULL) {
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate * Nobody has told us about this keyboard yet.
1427c478bd9Sstevel@tonic-gate */
1437c478bd9Sstevel@tonic-gate return;
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate /*
1477c478bd9Sstevel@tonic-gate * Get the current state of the shiftmask
1487c478bd9Sstevel@tonic-gate */
1497c478bd9Sstevel@tonic-gate shiftmask = lower->kbtrans_shiftmask;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * If the key has been released, then or in the UPMASK flag.
1537c478bd9Sstevel@tonic-gate */
1547c478bd9Sstevel@tonic-gate if (newstate == KEY_RELEASED)
1557c478bd9Sstevel@tonic-gate shiftmask |= UPMASK;
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate * Based on the shiftmask, lookup the keymap entry that we should
1597c478bd9Sstevel@tonic-gate * be using for this scancode.
1607c478bd9Sstevel@tonic-gate */
1617c478bd9Sstevel@tonic-gate ke = kbtrans_find_entry(lower, shiftmask, key);
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate if (ke == NULL) {
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate * This is a gross error. Cancel the repeat key and exit,
1667c478bd9Sstevel@tonic-gate * we can not translate this scancode.
1677c478bd9Sstevel@tonic-gate */
1687c478bd9Sstevel@tonic-gate cb->kc_cancel_repeat(lower->kbtrans_upper);
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate return;
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate * Get the key for this scancode.
1757c478bd9Sstevel@tonic-gate */
1767c478bd9Sstevel@tonic-gate entry = *ke;
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate if (entry == NONL) {
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate * NONL appears only in the Num Lock table, and indicates that
1817c478bd9Sstevel@tonic-gate * this key is not affected by Num Lock. This means we should
1827c478bd9Sstevel@tonic-gate * ask for the table we would have gotten had Num Lock not been
1837c478bd9Sstevel@tonic-gate * down, and translate using that table.
1847c478bd9Sstevel@tonic-gate */
185*adc2b73dSToomas Soome ke = kbtrans_find_entry(lower, shiftmask & ~NUMLOCKMASK, key);
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate if (ke == NULL) {
1887c478bd9Sstevel@tonic-gate /*
1897c478bd9Sstevel@tonic-gate * This is a gross error. Cancel the repeat key and
1907c478bd9Sstevel@tonic-gate * exit, we can not translate this scancode.
1917c478bd9Sstevel@tonic-gate */
1927c478bd9Sstevel@tonic-gate cb->kc_cancel_repeat(lower->kbtrans_upper);
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate return;
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate * Get the new key for this scancode.
1997c478bd9Sstevel@tonic-gate */
2007c478bd9Sstevel@tonic-gate entry = *ke;
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate * The entrytype indicates what category of key we are processing.
2057c478bd9Sstevel@tonic-gate * Categories include shift keys, function keys, and numeric keypad
2067c478bd9Sstevel@tonic-gate * keys.
2077c478bd9Sstevel@tonic-gate */
208*adc2b73dSToomas Soome entrytype = KEYFLAGS(entry);
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate if (entrytype == SHIFTKEYS) {
2117c478bd9Sstevel@tonic-gate /*
2127c478bd9Sstevel@tonic-gate * Handle the state of toggle shifts specially.
2137c478bd9Sstevel@tonic-gate * Ups should be ignored, and downs should be mapped to ups if
2147c478bd9Sstevel@tonic-gate * that shift is currently on.
2157c478bd9Sstevel@tonic-gate */
2167c478bd9Sstevel@tonic-gate if ((1 << (entry & 0x0F)) &
2177c478bd9Sstevel@tonic-gate lower->kbtrans_keyboard->k_toggleshifts) {
218*adc2b73dSToomas Soome if ((1 << (entry & 0x0F)) & lower->kbtrans_togglemask) {
2197c478bd9Sstevel@tonic-gate newstate = KEY_RELEASED; /* toggling off */
2207c478bd9Sstevel@tonic-gate } else {
2217c478bd9Sstevel@tonic-gate newstate = KEY_PRESSED; /* toggling on */
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate } else {
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate * Handle Compose and floating accent key sequences
2277c478bd9Sstevel@tonic-gate */
2287c478bd9Sstevel@tonic-gate switch (lower->kbtrans_state) {
2297c478bd9Sstevel@tonic-gate case COMPOSE1:
2307c478bd9Sstevel@tonic-gate if (newstate == KEY_RELEASED)
2317c478bd9Sstevel@tonic-gate return;
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate if (entry < ASCII_SET_SIZE) {
2347c478bd9Sstevel@tonic-gate if (lower->kbtrans_compose_map[entry] >= 0) {
2357c478bd9Sstevel@tonic-gate lower->kbtrans_compose_key = entry;
2367c478bd9Sstevel@tonic-gate lower->kbtrans_state = COMPOSE2;
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate return;
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate lower->kbtrans_state = NORMAL;
2427c478bd9Sstevel@tonic-gate lower->kbtrans_led_state &= ~LED_COMPOSE;
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate cb->kc_setled(lower->kbtrans_upper);
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate return;
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate case COMPOSE2:
2497c478bd9Sstevel@tonic-gate if (newstate == KEY_RELEASED)
2507c478bd9Sstevel@tonic-gate return;
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /* next state is "normal" */
2537c478bd9Sstevel@tonic-gate lower->kbtrans_state = NORMAL;
2547c478bd9Sstevel@tonic-gate lower->kbtrans_led_state &= ~LED_COMPOSE;
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate cb->kc_setled(lower->kbtrans_upper);
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate good_compose = kbtrans_do_compose(lower,
259*adc2b73dSToomas Soome lower->kbtrans_compose_key, entry, &result);
2607c478bd9Sstevel@tonic-gate if (good_compose) {
2617c478bd9Sstevel@tonic-gate cb->kc_keypressed(lower->kbtrans_upper,
262*adc2b73dSToomas Soome entrytype, key, result);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate return;
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate case FLTACCENT:
2677c478bd9Sstevel@tonic-gate if (newstate == KEY_RELEASED)
2687c478bd9Sstevel@tonic-gate return;
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate /* next state is "normal" */
2717c478bd9Sstevel@tonic-gate lower->kbtrans_state = NORMAL;
2727c478bd9Sstevel@tonic-gate for (i = 0;
273*adc2b73dSToomas Soome (lower->kbtrans_fltaccent_table[i].fa_entry !=
274*adc2b73dSToomas Soome lower->kbtrans_fltaccent_entry) ||
2757c478bd9Sstevel@tonic-gate (lower->kbtrans_fltaccent_table[i].ascii != entry);
2767c478bd9Sstevel@tonic-gate i++) {
2777c478bd9Sstevel@tonic-gate if (lower->kbtrans_fltaccent_table[i].fa_entry
2787c478bd9Sstevel@tonic-gate == 0) {
2797c478bd9Sstevel@tonic-gate /* Invalid second key: ignore key */
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate return;
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate
285*adc2b73dSToomas Soome cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
286*adc2b73dSToomas Soome lower->kbtrans_fltaccent_table[i].utf8);
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate return;
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate * If the key is going down, and it's not one of the keys that doesn't
2947c478bd9Sstevel@tonic-gate * auto-repeat, set up the auto-repeat timeout.
2957c478bd9Sstevel@tonic-gate *
2967c478bd9Sstevel@tonic-gate * The keys that don't auto-repeat are the Compose key,
2977c478bd9Sstevel@tonic-gate * the shift keys, the "bucky bit" keys, the "floating accent" keys,
2987c478bd9Sstevel@tonic-gate * and the function keys when in TR_EVENT mode.
2997c478bd9Sstevel@tonic-gate */
3007c478bd9Sstevel@tonic-gate if (newstate == KEY_PRESSED && entrytype != SHIFTKEYS &&
3017c478bd9Sstevel@tonic-gate entrytype != BUCKYBITS && entrytype != FUNNY &&
3027c478bd9Sstevel@tonic-gate entrytype != FA_CLASS) {
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate if (lower->kbtrans_repeatkey != key) {
3057c478bd9Sstevel@tonic-gate cb->kc_cancel_repeat(lower->kbtrans_upper);
3067c478bd9Sstevel@tonic-gate cb->kc_setup_repeat(lower->kbtrans_upper, entrytype,
307*adc2b73dSToomas Soome key);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate /* key going up */
3107c478bd9Sstevel@tonic-gate } else if (key == lower->kbtrans_repeatkey) {
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate cb->kc_cancel_repeat(lower->kbtrans_upper);
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate if (newstate == KEY_RELEASED) {
3167c478bd9Sstevel@tonic-gate cb->kc_keyreleased(lower->kbtrans_upper, key);
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate * We assume here that keys other than shift keys and bucky keys have
3217c478bd9Sstevel@tonic-gate * entries in the "up" table that cause nothing to be done, and thus we
3227c478bd9Sstevel@tonic-gate * don't have to check for newstate == KEY_RELEASED.
3237c478bd9Sstevel@tonic-gate */
3247c478bd9Sstevel@tonic-gate switch (entrytype) {
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate case 0x0: /* regular key */
3277c478bd9Sstevel@tonic-gate cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
328*adc2b73dSToomas Soome SPECIAL(lower->kbtrans_buckybits, entry));
3297c478bd9Sstevel@tonic-gate break;
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate case SHIFTKEYS: {
3327c478bd9Sstevel@tonic-gate uint_t shiftbit = 1 << (entry & 0x0F);
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate /* Modify toggle state (see toggle processing above) */
3357c478bd9Sstevel@tonic-gate if (shiftbit & lower->kbtrans_keyboard->k_toggleshifts) {
3367c478bd9Sstevel@tonic-gate if (newstate == KEY_RELEASED) {
3377c478bd9Sstevel@tonic-gate if (shiftbit == CAPSMASK) {
3387c478bd9Sstevel@tonic-gate lower->kbtrans_led_state &=
339*adc2b73dSToomas Soome ~LED_CAPS_LOCK;
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate cb->kc_setled(lower->kbtrans_upper);
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) {
3447c478bd9Sstevel@tonic-gate lower->kbtrans_led_state &=
345*adc2b73dSToomas Soome ~LED_NUM_LOCK;
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate cb->kc_setled(lower->kbtrans_upper);
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate lower->kbtrans_togglemask &= ~shiftbit;
3507c478bd9Sstevel@tonic-gate } else {
3517c478bd9Sstevel@tonic-gate if (shiftbit == CAPSMASK) {
3527c478bd9Sstevel@tonic-gate lower->kbtrans_led_state |=
353*adc2b73dSToomas Soome LED_CAPS_LOCK;
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate cb->kc_setled(lower->kbtrans_upper);
3567c478bd9Sstevel@tonic-gate } else if (shiftbit == NUMLOCKMASK) {
3577c478bd9Sstevel@tonic-gate lower->kbtrans_led_state |=
358*adc2b73dSToomas Soome LED_NUM_LOCK;
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate cb->kc_setled(lower->kbtrans_upper);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate lower->kbtrans_togglemask |= shiftbit;
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate if (newstate == KEY_RELEASED)
3677c478bd9Sstevel@tonic-gate lower->kbtrans_shiftmask &= ~shiftbit;
3687c478bd9Sstevel@tonic-gate else
3697c478bd9Sstevel@tonic-gate lower->kbtrans_shiftmask |= shiftbit;
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate if (newstate == KEY_PRESSED) {
3727c478bd9Sstevel@tonic-gate cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
373*adc2b73dSToomas Soome entry);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate break;
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate case BUCKYBITS:
380*adc2b73dSToomas Soome lower->kbtrans_buckybits ^= 1 << (entry & 0x0F);
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate if (newstate == KEY_PRESSED) {
3837c478bd9Sstevel@tonic-gate cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
384*adc2b73dSToomas Soome entry);
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate break;
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate case FUNNY:
3907c478bd9Sstevel@tonic-gate switch (entry) {
3917c478bd9Sstevel@tonic-gate case NOP:
3927c478bd9Sstevel@tonic-gate break;
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate case IDLE:
3957c478bd9Sstevel@tonic-gate /* Fall thru into RESET code */
3967c478bd9Sstevel@tonic-gate /* FALLTHRU */
3977c478bd9Sstevel@tonic-gate case RESET:
3987c478bd9Sstevel@tonic-gate case ERROR:
3997c478bd9Sstevel@tonic-gate lower->kbtrans_shiftmask &=
400*adc2b73dSToomas Soome lower->kbtrans_keyboard->k_idleshifts;
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate lower->kbtrans_shiftmask |=
403*adc2b73dSToomas Soome lower->kbtrans_togglemask;
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate lower->kbtrans_buckybits &=
406*adc2b73dSToomas Soome lower->kbtrans_keyboard->k_idlebuckys;
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate cb->kc_cancel_repeat(lower->kbtrans_upper);
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
411*adc2b73dSToomas Soome entry);
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate break;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate case COMPOSE:
4177c478bd9Sstevel@tonic-gate lower->kbtrans_state = COMPOSE1;
4187c478bd9Sstevel@tonic-gate lower->kbtrans_led_state |= LED_COMPOSE;
4197c478bd9Sstevel@tonic-gate cb->kc_setled(lower->kbtrans_upper);
4207c478bd9Sstevel@tonic-gate break;
4217c478bd9Sstevel@tonic-gate /*
4227c478bd9Sstevel@tonic-gate * Remember when adding new entries that,
4237c478bd9Sstevel@tonic-gate * if they should NOT auto-repeat,
4247c478bd9Sstevel@tonic-gate * they should be put into the IF statement
4257c478bd9Sstevel@tonic-gate * just above this switch block.
4267c478bd9Sstevel@tonic-gate */
4277c478bd9Sstevel@tonic-gate default:
4287c478bd9Sstevel@tonic-gate /* Ignore it */
4297c478bd9Sstevel@tonic-gate break;
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate break;
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate case FA_CLASS:
4347c478bd9Sstevel@tonic-gate if (lower->kbtrans_state == NORMAL) {
4357c478bd9Sstevel@tonic-gate lower->kbtrans_fltaccent_entry = entry;
4367c478bd9Sstevel@tonic-gate lower->kbtrans_state = FLTACCENT;
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate break;
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate case STRING:
4417c478bd9Sstevel@tonic-gate cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate break;
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate case FUNCKEYS:
4467c478bd9Sstevel@tonic-gate cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate break;
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate /*
4517c478bd9Sstevel@tonic-gate * Remember when adding new entries that,
4527c478bd9Sstevel@tonic-gate * if they should NOT auto-repeat,
4537c478bd9Sstevel@tonic-gate * they should be put into the IF statement
4547c478bd9Sstevel@tonic-gate * just above this switch block.
4557c478bd9Sstevel@tonic-gate */
4567c478bd9Sstevel@tonic-gate case PADKEYS:
4577c478bd9Sstevel@tonic-gate cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate break;
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate * kbtrans_do_compose:
4657c478bd9Sstevel@tonic-gate * Given a two key compose sequence, lookup the iso equivalent and put
466*adc2b73dSToomas Soome * the result in the result_ptr.
4677c478bd9Sstevel@tonic-gate */
4687c478bd9Sstevel@tonic-gate static boolean_t
kbtrans_do_compose(struct kbtrans_lower * lower,keymap_entry_t first_entry,keymap_entry_t second_entry,keymap_entry_t * result_ptr)469*adc2b73dSToomas Soome kbtrans_do_compose(struct kbtrans_lower *lower, keymap_entry_t first_entry,
470*adc2b73dSToomas Soome keymap_entry_t second_entry, keymap_entry_t *result_ptr)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate struct compose_sequence_t *ptr;
473*adc2b73dSToomas Soome keymap_entry_t tmp;
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate /*
4767c478bd9Sstevel@tonic-gate * Validate the second keystroke.
4777c478bd9Sstevel@tonic-gate */
4787c478bd9Sstevel@tonic-gate if (second_entry >= ASCII_SET_SIZE)
4797c478bd9Sstevel@tonic-gate return (B_FALSE);
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate if (lower->kbtrans_compose_map[second_entry] < 0)
4827c478bd9Sstevel@tonic-gate return (B_FALSE);
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate /*
4857c478bd9Sstevel@tonic-gate * Get them in code order, rather than press order.
4867c478bd9Sstevel@tonic-gate */
4877c478bd9Sstevel@tonic-gate if (first_entry > second_entry) {
4887c478bd9Sstevel@tonic-gate tmp = first_entry;
4897c478bd9Sstevel@tonic-gate first_entry = second_entry;
4907c478bd9Sstevel@tonic-gate second_entry = tmp;
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate ptr = lower->kbtrans_compose_table +
494*adc2b73dSToomas Soome lower->kbtrans_compose_map[first_entry];
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate while (ptr->first == first_entry) {
4977c478bd9Sstevel@tonic-gate if (ptr->second == second_entry) {
498*adc2b73dSToomas Soome *result_ptr = ptr->utf8;
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate return (B_TRUE);
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate ptr++;
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate return (B_FALSE);
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate * kbtrans_find_entry:
5107c478bd9Sstevel@tonic-gate * This routine finds the entry corresponding to the current shift
5117c478bd9Sstevel@tonic-gate * state and keycode.
5127c478bd9Sstevel@tonic-gate */
513*adc2b73dSToomas Soome keymap_entry_t *
kbtrans_find_entry(struct kbtrans_lower * lower,uint_t mask,kbtrans_key_t key_station)514*adc2b73dSToomas Soome kbtrans_find_entry(struct kbtrans_lower *lower, uint_t mask,
515*adc2b73dSToomas Soome kbtrans_key_t key_station)
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate register struct keyboard *kp;
5187c478bd9Sstevel@tonic-gate keymap_entry_t *km;
5197c478bd9Sstevel@tonic-gate struct exception_map *ex;
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate kp = lower->kbtrans_keyboard;
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate if (kp == NULL)
5247c478bd9Sstevel@tonic-gate return (NULL);
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate if (key_station < 0 || key_station >= kp->k_keymap_size)
5277c478bd9Sstevel@tonic-gate return (NULL);
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate ex = kp->k_except;
5307c478bd9Sstevel@tonic-gate if (ex != NULL) {
5317c478bd9Sstevel@tonic-gate for (; ex->exc_care != 0; ex++) {
5327c478bd9Sstevel@tonic-gate if ((mask & ex->exc_care) == ex->exc_mask &&
5337c478bd9Sstevel@tonic-gate key_station == ex->exc_key)
5347c478bd9Sstevel@tonic-gate return (&ex->exc_entry);
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate if (mask & UPMASK)
5397c478bd9Sstevel@tonic-gate km = kp->k_up;
5407c478bd9Sstevel@tonic-gate else if (mask & NUMLOCKMASK)
5417c478bd9Sstevel@tonic-gate km = kp->k_numlock;
5427c478bd9Sstevel@tonic-gate else if (mask & CTRLMASK)
5437c478bd9Sstevel@tonic-gate km = kp->k_control;
5447c478bd9Sstevel@tonic-gate else if (mask & ALTGRAPHMASK)
5457c478bd9Sstevel@tonic-gate km = kp->k_altgraph;
5467c478bd9Sstevel@tonic-gate else if (mask & SHIFTMASK)
5477c478bd9Sstevel@tonic-gate km = kp->k_shifted;
5487c478bd9Sstevel@tonic-gate else if (mask & CAPSMASK)
5497c478bd9Sstevel@tonic-gate km = kp->k_caps;
5507c478bd9Sstevel@tonic-gate else km = kp->k_normal;
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate return (&km[key_station]);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate
5557c478bd9Sstevel@tonic-gate #ifdef DEBUG
5567c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5577c478bd9Sstevel@tonic-gate void
kbtrans_dprintf(void * un,const char * fmt,...)5587c478bd9Sstevel@tonic-gate kbtrans_dprintf(void *un, const char *fmt, ...)
5597c478bd9Sstevel@tonic-gate {
5607c478bd9Sstevel@tonic-gate char buf[256];
5617c478bd9Sstevel@tonic-gate va_list ap;
5627c478bd9Sstevel@tonic-gate
5637c478bd9Sstevel@tonic-gate va_start(ap, fmt);
5647c478bd9Sstevel@tonic-gate (void) vsprintf(buf, fmt, ap);
5657c478bd9Sstevel@tonic-gate va_end(ap);
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "kbtrans: %s", buf);
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate #endif
570