Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / kbtrans / kbtrans.c
blob2091a18162ab015763695db3dbd5d2a387acedb6
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Generic keyboard support: translation
30 * This module is project private. Please see PSARC/1998/176 and
31 * PSARC/1998/026 for references to the kbtrans module.
33 * It is believed that it is safe to call these functions within debugger mode
34 * except kbtrans_dprintf. Debugger mode is a single threaded mode where most
35 * kernel services are not available, including memory allocation. Debugger
36 * mode is for kmdb and OBP debugging, where the debugger calls back into the
37 * kernel to obtain console input.
39 * Please be _very_ careful about what external functions you call.
42 #define KEYMAP_SIZE_VARIABLE
44 #include <sys/types.h>
45 #include <sys/cred.h>
46 #include <sys/ddi.h>
47 #include <sys/sunddi.h>
48 #include <sys/kmem.h>
49 #include <sys/kbd.h>
50 #include <sys/cmn_err.h>
51 #include <sys/modctl.h>
52 #include <sys/kbio.h>
53 #include <sys/vuid_event.h>
54 #include <sys/consdev.h>
55 #include <sys/kbtrans.h>
56 #include <sys/errno.h>
57 #include <sys/promif.h>
58 #include <sys/varargs.h>
59 #include "kbtrans_lower.h"
62 * Internal Function Prototypes
64 static boolean_t kbtrans_do_compose(struct kbtrans_lower *, keymap_entry_t,
65 keymap_entry_t, keymap_entry_t *);
66 static void kbtrans_translate(struct kbtrans_lower *,
67 struct keyboard_callback *, kbtrans_key_t, enum keystate);
70 * kbtrans_processkey:
72 * lower - state information used by the calling driver
73 * this parameter is passed back to the callback routines.
74 * key - scancode
75 * state - KEY_PRESSED / KEY_RELEASED
77 * This routine checks to see if there is a raw callback, and calls it
78 * if it exists. If there is no raw callback, the key is translated.
79 * The raw callback allows the driver that called the translation module
80 * to be passed untranslated scancodes.
82 void
83 kbtrans_processkey(struct kbtrans_lower *lower,
84 struct keyboard_callback *cb, kbtrans_key_t key, enum keystate state)
86 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "kbtrans_processkey: "
87 "newstate=%d key=%d", state, key));
90 * If there is a raw routine, then call it and return.
92 if (cb->kc_keypressed_raw != NULL) {
94 if (state == KEY_PRESSED) {
96 cb->kc_keypressed_raw(lower->kbtrans_upper, key);
97 } else {
99 cb->kc_keyreleased_raw(lower->kbtrans_upper, key);
102 return;
106 * translate the scancode into a key.
108 kbtrans_translate(lower, cb, key, state);
113 * kbtrans_translate:
115 * lower - state information used by the calling driver
116 * this parameter is passed back to the callback routines.
117 * key - scan code
118 * state - KEY_PRESSED / KEY_RELEASED
120 * Called to process key events if we are in TR_ASCII or TR_EVENT
121 * (sunview) mode. This routine will call the appropriate translation_callback
122 * for the character when it is done translating it.
124 static void
125 kbtrans_translate(struct kbtrans_lower *lower, struct keyboard_callback *cb,
126 kbtrans_key_t key, enum keystate newstate)
128 unsigned shiftmask;
129 register keymap_entry_t entry;
130 register unsigned entrytype;
131 keymap_entry_t result;
132 keymap_entry_t *ke;
133 int i;
134 boolean_t good_compose;
136 DPRINTF(PRINT_L0, PRINT_MASK_ALL, (lower, "KEY TRANSLATE "
137 "newstate=0x%x key=0x%x\n", newstate, key));
139 if (lower->kbtrans_keyboard == NULL) {
141 * Nobody has told us about this keyboard yet.
143 return;
147 * Get the current state of the shiftmask
149 shiftmask = lower->kbtrans_shiftmask;
152 * If the key has been released, then or in the UPMASK flag.
154 if (newstate == KEY_RELEASED)
155 shiftmask |= UPMASK;
158 * Based on the shiftmask, lookup the keymap entry that we should
159 * be using for this scancode.
161 ke = kbtrans_find_entry(lower, shiftmask, key);
163 if (ke == NULL) {
165 * This is a gross error. Cancel the repeat key and exit,
166 * we can not translate this scancode.
168 cb->kc_cancel_repeat(lower->kbtrans_upper);
170 return;
174 * Get the key for this scancode.
176 entry = *ke;
178 if (entry == NONL) {
180 * NONL appears only in the Num Lock table, and indicates that
181 * this key is not affected by Num Lock. This means we should
182 * ask for the table we would have gotten had Num Lock not been
183 * down, and translate using that table.
185 ke = kbtrans_find_entry(lower, shiftmask & ~NUMLOCKMASK, key);
187 if (ke == NULL) {
189 * This is a gross error. Cancel the repeat key and
190 * exit, we can not translate this scancode.
192 cb->kc_cancel_repeat(lower->kbtrans_upper);
194 return;
198 * Get the new key for this scancode.
200 entry = *ke;
204 * The entrytype indicates what category of key we are processing.
205 * Categories include shift keys, function keys, and numeric keypad
206 * keys.
208 entrytype = KEYFLAGS(entry);
210 if (entrytype == SHIFTKEYS) {
212 * Handle the state of toggle shifts specially.
213 * Ups should be ignored, and downs should be mapped to ups if
214 * that shift is currently on.
216 if ((1 << (entry & 0x0F)) &
217 lower->kbtrans_keyboard->k_toggleshifts) {
218 if ((1 << (entry & 0x0F)) & lower->kbtrans_togglemask) {
219 newstate = KEY_RELEASED; /* toggling off */
220 } else {
221 newstate = KEY_PRESSED; /* toggling on */
224 } else {
226 * Handle Compose and floating accent key sequences
228 switch (lower->kbtrans_state) {
229 case COMPOSE1:
230 if (newstate == KEY_RELEASED)
231 return;
233 if (entry < ASCII_SET_SIZE) {
234 if (lower->kbtrans_compose_map[entry] >= 0) {
235 lower->kbtrans_compose_key = entry;
236 lower->kbtrans_state = COMPOSE2;
238 return;
241 lower->kbtrans_state = NORMAL;
242 lower->kbtrans_led_state &= ~LED_COMPOSE;
244 cb->kc_setled(lower->kbtrans_upper);
246 return;
248 case COMPOSE2:
249 if (newstate == KEY_RELEASED)
250 return;
252 /* next state is "normal" */
253 lower->kbtrans_state = NORMAL;
254 lower->kbtrans_led_state &= ~LED_COMPOSE;
256 cb->kc_setled(lower->kbtrans_upper);
258 good_compose = kbtrans_do_compose(lower,
259 lower->kbtrans_compose_key, entry, &result);
260 if (good_compose) {
261 cb->kc_keypressed(lower->kbtrans_upper,
262 entrytype, key, result);
264 return;
266 case FLTACCENT:
267 if (newstate == KEY_RELEASED)
268 return;
270 /* next state is "normal" */
271 lower->kbtrans_state = NORMAL;
272 for (i = 0;
273 (lower->kbtrans_fltaccent_table[i].fa_entry !=
274 lower->kbtrans_fltaccent_entry) ||
275 (lower->kbtrans_fltaccent_table[i].ascii != entry);
276 i++) {
277 if (lower->kbtrans_fltaccent_table[i].fa_entry
278 == 0) {
279 /* Invalid second key: ignore key */
281 return;
285 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
286 lower->kbtrans_fltaccent_table[i].utf8);
288 return;
293 * If the key is going down, and it's not one of the keys that doesn't
294 * auto-repeat, set up the auto-repeat timeout.
296 * The keys that don't auto-repeat are the Compose key,
297 * the shift keys, the "bucky bit" keys, the "floating accent" keys,
298 * and the function keys when in TR_EVENT mode.
300 if (newstate == KEY_PRESSED && entrytype != SHIFTKEYS &&
301 entrytype != BUCKYBITS && entrytype != FUNNY &&
302 entrytype != FA_CLASS) {
304 if (lower->kbtrans_repeatkey != key) {
305 cb->kc_cancel_repeat(lower->kbtrans_upper);
306 cb->kc_setup_repeat(lower->kbtrans_upper, entrytype,
307 key);
309 /* key going up */
310 } else if (key == lower->kbtrans_repeatkey) {
312 cb->kc_cancel_repeat(lower->kbtrans_upper);
315 if (newstate == KEY_RELEASED) {
316 cb->kc_keyreleased(lower->kbtrans_upper, key);
320 * We assume here that keys other than shift keys and bucky keys have
321 * entries in the "up" table that cause nothing to be done, and thus we
322 * don't have to check for newstate == KEY_RELEASED.
324 switch (entrytype) {
326 case 0x0: /* regular key */
327 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
328 SPECIAL(lower->kbtrans_buckybits, entry));
329 break;
331 case SHIFTKEYS: {
332 uint_t shiftbit = 1 << (entry & 0x0F);
334 /* Modify toggle state (see toggle processing above) */
335 if (shiftbit & lower->kbtrans_keyboard->k_toggleshifts) {
336 if (newstate == KEY_RELEASED) {
337 if (shiftbit == CAPSMASK) {
338 lower->kbtrans_led_state &=
339 ~LED_CAPS_LOCK;
341 cb->kc_setled(lower->kbtrans_upper);
343 } else if (shiftbit == NUMLOCKMASK) {
344 lower->kbtrans_led_state &=
345 ~LED_NUM_LOCK;
347 cb->kc_setled(lower->kbtrans_upper);
349 lower->kbtrans_togglemask &= ~shiftbit;
350 } else {
351 if (shiftbit == CAPSMASK) {
352 lower->kbtrans_led_state |=
353 LED_CAPS_LOCK;
355 cb->kc_setled(lower->kbtrans_upper);
356 } else if (shiftbit == NUMLOCKMASK) {
357 lower->kbtrans_led_state |=
358 LED_NUM_LOCK;
360 cb->kc_setled(lower->kbtrans_upper);
362 lower->kbtrans_togglemask |= shiftbit;
366 if (newstate == KEY_RELEASED)
367 lower->kbtrans_shiftmask &= ~shiftbit;
368 else
369 lower->kbtrans_shiftmask |= shiftbit;
371 if (newstate == KEY_PRESSED) {
372 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
373 entry);
376 break;
379 case BUCKYBITS:
380 lower->kbtrans_buckybits ^= 1 << (entry & 0x0F);
382 if (newstate == KEY_PRESSED) {
383 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
384 entry);
387 break;
389 case FUNNY:
390 switch (entry) {
391 case NOP:
392 break;
394 case IDLE:
395 /* Fall thru into RESET code */
396 /* FALLTHRU */
397 case RESET:
398 case ERROR:
399 lower->kbtrans_shiftmask &=
400 lower->kbtrans_keyboard->k_idleshifts;
402 lower->kbtrans_shiftmask |=
403 lower->kbtrans_togglemask;
405 lower->kbtrans_buckybits &=
406 lower->kbtrans_keyboard->k_idlebuckys;
408 cb->kc_cancel_repeat(lower->kbtrans_upper);
410 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key,
411 entry);
413 break;
416 case COMPOSE:
417 lower->kbtrans_state = COMPOSE1;
418 lower->kbtrans_led_state |= LED_COMPOSE;
419 cb->kc_setled(lower->kbtrans_upper);
420 break;
422 * Remember when adding new entries that,
423 * if they should NOT auto-repeat,
424 * they should be put into the IF statement
425 * just above this switch block.
427 default:
428 /* Ignore it */
429 break;
431 break;
433 case FA_CLASS:
434 if (lower->kbtrans_state == NORMAL) {
435 lower->kbtrans_fltaccent_entry = entry;
436 lower->kbtrans_state = FLTACCENT;
438 break;
440 case STRING:
441 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
443 break;
445 case FUNCKEYS:
446 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
448 break;
451 * Remember when adding new entries that,
452 * if they should NOT auto-repeat,
453 * they should be put into the IF statement
454 * just above this switch block.
456 case PADKEYS:
457 cb->kc_keypressed(lower->kbtrans_upper, entrytype, key, entry);
459 break;
464 * kbtrans_do_compose:
465 * Given a two key compose sequence, lookup the iso equivalent and put
466 * the result in the result_ptr.
468 static boolean_t
469 kbtrans_do_compose(struct kbtrans_lower *lower, keymap_entry_t first_entry,
470 keymap_entry_t second_entry, keymap_entry_t *result_ptr)
472 struct compose_sequence_t *ptr;
473 keymap_entry_t tmp;
476 * Validate the second keystroke.
478 if (second_entry >= ASCII_SET_SIZE)
479 return (B_FALSE);
481 if (lower->kbtrans_compose_map[second_entry] < 0)
482 return (B_FALSE);
485 * Get them in code order, rather than press order.
487 if (first_entry > second_entry) {
488 tmp = first_entry;
489 first_entry = second_entry;
490 second_entry = tmp;
493 ptr = lower->kbtrans_compose_table +
494 lower->kbtrans_compose_map[first_entry];
496 while (ptr->first == first_entry) {
497 if (ptr->second == second_entry) {
498 *result_ptr = ptr->utf8;
500 return (B_TRUE);
502 ptr++;
504 return (B_FALSE);
509 * kbtrans_find_entry:
510 * This routine finds the entry corresponding to the current shift
511 * state and keycode.
513 keymap_entry_t *
514 kbtrans_find_entry(struct kbtrans_lower *lower, uint_t mask,
515 kbtrans_key_t key_station)
517 register struct keyboard *kp;
518 keymap_entry_t *km;
519 struct exception_map *ex;
521 kp = lower->kbtrans_keyboard;
523 if (kp == NULL)
524 return (NULL);
526 if (key_station < 0 || key_station >= kp->k_keymap_size)
527 return (NULL);
529 ex = kp->k_except;
530 if (ex != NULL) {
531 for (; ex->exc_care != 0; ex++) {
532 if ((mask & ex->exc_care) == ex->exc_mask &&
533 key_station == ex->exc_key)
534 return (&ex->exc_entry);
538 if (mask & UPMASK)
539 km = kp->k_up;
540 else if (mask & NUMLOCKMASK)
541 km = kp->k_numlock;
542 else if (mask & CTRLMASK)
543 km = kp->k_control;
544 else if (mask & ALTGRAPHMASK)
545 km = kp->k_altgraph;
546 else if (mask & SHIFTMASK)
547 km = kp->k_shifted;
548 else if (mask & CAPSMASK)
549 km = kp->k_caps;
550 else km = kp->k_normal;
552 return (&km[key_station]);
555 #ifdef DEBUG
556 /*ARGSUSED*/
557 void
558 kbtrans_dprintf(void *un, const char *fmt, ...)
560 char buf[256];
561 va_list ap;
563 va_start(ap, fmt);
564 (void) vsprintf(buf, fmt, ap);
565 va_end(ap);
567 cmn_err(CE_CONT, "kbtrans: %s", buf);
569 #endif