/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/kbd.h>
#include <sys/kbtrans.h>
#include <sys/sunddi.h>
#include <sys/consdev.h>
#include <sys/promif.h>
#include "kb8042.h"
/*
* A note on the use of prom_printf here: Most of these routines can be
* called from "polled mode", where we're servicing I/O requests from kmdb.
* Normal system services are not available from polled mode; cmn_err will
* not work. prom_printf is the only safe output mechanism.
*/
#define KEYBAD 0xff /* should generate an error */
#define KEYIGN 0xfe /* ignore this sequence */
#define KEY(code) (code)
#define INVALID KEYBAD
#define IGNORE KEYIGN
#define NELEM(a) (sizeof (a) / sizeof (a)[0])
/*
* These are the states of our parsing machine:
*/
#define STATE_IDLE 0x00000001 /* Awaiting the start of a sequence */
#define STATE_E0 0x00000002 /* Rec'd an E0 */
#define STATE_E1 0x00000004 /* Rec'd an E1 (Pause key only) */
#define STATE_E1_1D 0x00000008 /* Rec'd an E1 1D (Pause key only) */
#define STATE_E1_14 0x00000010 /* Rec'd an E1 14 (Pause key only) */
#define STATE_E1_14_77 0x00000020
#define STATE_E1_14_77_E1 0x00000040
#define STATE_E1_14_77_E1_F0 0x00000080
#define STATE_E1_14_77_E1_F0_14 0x00000100
#define STATE_E1_14_77_E1_F0_14_F0 0x00000200
static boolean_t KeyboardConvertScan_set1(struct kb8042 *, unsigned char, int *,
enum keystate *, boolean_t *);
static boolean_t KeyboardConvertScan_set2(struct kb8042 *, unsigned char, int *,
enum keystate *, boolean_t *);
static const unsigned char *keytab_base = NULL;
static int keytab_base_length = 0;
static const unsigned char *keytab_e0 = NULL;
static int keytab_e0_length = 0;
static boolean_t (*KeyboardConvertScan_fn)(struct kb8042 *, unsigned char,
int *, enum keystate *, boolean_t *) = NULL;
static const unsigned char keytab_base_set1[] = {
/* scan key number keycap */
/* 00 */ INVALID,
/* 01 */ KEY(110), /* Esc */
/* 02 */ KEY(2), /* 1 */
/* 03 */ KEY(3), /* 2 */
/* 04 */ KEY(4), /* 3 */
/* 05 */ KEY(5), /* 4 */
/* 06 */ KEY(6), /* 5 */
/* 07 */ KEY(7), /* 6 */
/* 08 */ KEY(8), /* 7 */
/* 09 */ KEY(9), /* 8 */
/* 0a */ KEY(10), /* 9 */
/* 0b */ KEY(11), /* 0 */
/* 0c */ KEY(12), /* - */
/* 0d */ KEY(13), /* = */
/* 0e */ KEY(15), /* backspace */
/* 0f */ KEY(16), /* tab */
/* 10 */ KEY(17), /* Q */
/* 11 */ KEY(18), /* W */
/* 12 */ KEY(19), /* E */
/* 13 */ KEY(20), /* R */
/* 14 */ KEY(21), /* T */
/* 15 */ KEY(22), /* Y */
/* 16 */ KEY(23), /* U */
/* 17 */ KEY(24), /* I */
/* 18 */ KEY(25), /* O */
/* 19 */ KEY(26), /* P */
/* 1a */ KEY(27), /* [ */
/* 1b */ KEY(28), /* ] */
/* 1c */ KEY(43), /* Enter (main) */
/* 1d */ KEY(58), /* L Ctrl */
/* 1e */ KEY(31), /* A */
/* 1f */ KEY(32), /* S */
/* 20 */ KEY(33), /* D */
/* 21 */ KEY(34), /* F */
/* 22 */ KEY(35), /* G */
/* 23 */ KEY(36), /* H */
/* 24 */ KEY(37), /* J */
/* 25 */ KEY(38), /* K */
/* 26 */ KEY(39), /* L */
/* 27 */ KEY(40), /* ; */
/* 28 */ KEY(41), /* ' */
/* 29 */ KEY(1), /* ` */
/* 2a */ KEY(44), /* L Shift */
/* 2b */ KEY(29), /* \ */
/* 2c */ KEY(46), /* Z */
/* 2d */ KEY(47), /* X */
/* 2e */ KEY(48), /* C */
/* 2f */ KEY(49), /* V */
/* 30 */ KEY(50), /* B */
/* 31 */ KEY(51), /* N */
/* 32 */ KEY(52), /* M */
/* 33 */ KEY(53), /* , */
/* 34 */ KEY(54), /* . */
/* 35 */ KEY(55), /* / */
/* 36 */ KEY(57), /* R Shift */
/* 37 */ KEY(100), /* * (num) */
/* 38 */ KEY(60), /* L Alt */
/* 39 */ KEY(61), /* Space */
/* 3a */ KEY(30), /* CapsLock */
/* 3b */ KEY(112), /* F1 */
/* 3c */ KEY(113), /* F2 */
/* 3d */ KEY(114), /* F3 */
/* 3e */ KEY(115), /* F4 */
/* 3f */ KEY(116), /* F5 */
/* 40 */ KEY(117), /* F6 */
/* 41 */ KEY(118), /* F7 */
/* 42 */ KEY(119), /* F8 */
/* 43 */ KEY(120), /* F9 */
/* 44 */ KEY(121), /* F10 */
/* 45 */ KEY(90), /* NumLock */
/* 46 */ KEY(125), /* Scroll Lock */
/* 47 */ KEY(91), /* 7 (num) */
/* 48 */ KEY(96), /* 8 (num) */
/* 49 */ KEY(101), /* 9 (num) */
/* 4a */ KEY(105), /* - (num) */
/* 4b */ KEY(92), /* 4 (num) */
/* 4c */ KEY(97), /* 5 (num) */
/* 4d */ KEY(102), /* 6 (num) */
/* 4e */ KEY(106), /* + (num) */
/* 4f */ KEY(93), /* 1 (num) */
/* 50 */ KEY(98), /* 2 (num) */
/* 51 */ KEY(103), /* 3 (num) */
/* 52 */ KEY(99), /* 0 (num) */
/* 53 */ KEY(104), /* . (num) */
/* 54 */ KEY(124), /* PrintScreen (with Alt) */
/* 55 */ INVALID,
/* 56 */ KEY(45), /* not labled (102-key only) */
/* 57 */ KEY(122), /* F11 */
/* 58 */ KEY(123), /* F12 */
/* 59 */ INVALID,
/* 5a */ INVALID,
/* 5b */ INVALID,
/* 5c */ INVALID,
/* 5d */ INVALID,
/* 5e */ INVALID,
/* 5f */ INVALID,
/* 60 */ INVALID,
/* 61 */ INVALID,
/* 62 */ INVALID,
/* 63 */ INVALID,
/* 64 */ INVALID,
/* 65 */ INVALID,
/* 66 */ INVALID,
/* 67 */ INVALID,
/* 68 */ INVALID,
/* 69 */ INVALID,
/* 6a */ INVALID,
/* 6b */ INVALID,
/* 6c */ INVALID,
/* 6d */ INVALID,
/* 6e */ INVALID,
/* 6f */ INVALID,
/* 70 */ KEY(133), /* Japanese 106-key keyboard */
/* 71 */ INVALID,
/* 72 */ INVALID,
/* 73 */ KEY(56), /* Japanese 106-key keyboard */
/* 74 */ INVALID,
/* 75 */ INVALID,
/* 76 */ INVALID,
/* 77 */ INVALID,
/* 78 */ INVALID,
/* 79 */ KEY(132), /* Japanese 106-key keyboard */
/* 7a */ INVALID,
/* 7b */ KEY(131), /* Japanese 106-key keyboard */
/* 7c */ INVALID,
/* 7d */ KEY(14), /* Japanese 106-key keyboard */
/* 7e */ INVALID,
/* 7f */ INVALID,
};
/*
* Parse table after receiving an E0 prefix code.
*
* Generally speaking, keys that were added on the 101-key keyboard are
* represented as an E0 followed by the code for an 84-key key. Software
* ignorant of the 101-key keyboard ignores the E0 and so is handled
* compatibly. Many of these variants involve "fake" shift presses
* and releases for compatibility; these are also prefixed with E0.
* We ignore these fake shifts.
*/
static const unsigned char keytab_e0_set1[] = {
/* 00 */ INVALID,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
/* 04 */ INVALID,
/* 05 */ INVALID,
/* 06 */ INVALID,
/* 07 */ INVALID,
/* 08 */ INVALID,
/* 09 */ INVALID,
/* 0a */ INVALID,
/* 0b */ INVALID,
/* 0c */ INVALID,
/* 0d */ INVALID,
/* 0e */ INVALID,
/* 0f */ INVALID,
/* 10 */ INVALID,
/* 11 */ INVALID,
/* 12 */ INVALID,
/* 13 */ INVALID,
/* 14 */ INVALID,
/* 15 */ INVALID,
/* 16 */ INVALID,
/* 17 */ INVALID,
/* 18 */ INVALID,
/* 19 */ INVALID,
/* 1a */ INVALID,
/* 1b */ INVALID,
/* 1c */ KEY(108), /* Enter (num) */
/* 1d */ KEY(64), /* R Ctrl */
/* 1e */ INVALID,
/* 1f */ INVALID,
/* 20 */ KEY(235), /* Mute */
/* 21 */ INVALID,
/* 22 */ INVALID,
/* 23 */ INVALID,
/* 24 */ INVALID,
/* 25 */ INVALID,
/* 26 */ INVALID,
/* 27 */ INVALID,
/* 28 */ INVALID,
/* 29 */ INVALID,
/* 2a */ INVALID,
/* 2b */ INVALID,
/* 2c */ INVALID,
/* 2d */ INVALID,
/* 2e */ KEY(234), /* Volume Down */
/* 2f */ INVALID,
/* 30 */ KEY(233), /* Volume Up */
/* 31 */ INVALID,
/* 32 */ INVALID,
/* 33 */ INVALID,
/* 34 */ INVALID,
/* 35 */ KEY(95), /* / (num) */
/* 36 */ INVALID,
/* 37 */ KEY(124), /* PrintScreen (no Alt) */
/* 38 */ KEY(62), /* R Alt */
/* 39 */ INVALID,
/* 3a */ INVALID,
/* 3b */ INVALID,
/* 3c */ INVALID,
/* 3d */ INVALID,
/* 3e */ INVALID,
/* 3f */ INVALID,
/* 40 */ INVALID,
/* 41 */ INVALID,
/* 42 */ INVALID,
/* 43 */ INVALID,
/* 44 */ INVALID,
/* 45 */ INVALID,
/* 46 */ KEY(126), /* Pause (with Cntl) */
/* 47 */ KEY(80), /* Home (arrow) */
/* 48 */ KEY(83), /* Up (arrow) */
/* 49 */ KEY(85), /* PgUp (arrow) */
/* 4a */ INVALID,
/* 4b */ KEY(79), /* Left (arrow) */
/* 4c */ INVALID,
/* 4d */ KEY(89), /* Right (arrow) */
/* 4e */ INVALID,
/* 4f */ KEY(81), /* End (arrow) */
/* 50 */ KEY(84), /* Down (arrow) */
/* 51 */ KEY(86), /* PgDn (arrow) */
/* 52 */ KEY(75), /* Insert (arrow) */
/* 53 */ KEY(76), /* Delete (arrow) */
/* 54 */ INVALID,
/* 55 */ INVALID,
/* 56 */ INVALID,
/* 57 */ INVALID,
/* 58 */ INVALID,
/* 59 */ INVALID,
/* 5a */ INVALID,
/* 5b */ KEY(59), /* L Window (104-key) */
/* 5c */ KEY(63), /* R Window (104-key) */
/* 5d */ KEY(65), /* Menu (104-key) */
/* 5e */ INVALID,
/* 5f */ INVALID,
/* 60 */ INVALID,
/* 61 */ INVALID,
/* 62 */ INVALID,
/* 63 */ INVALID,
/* 64 */ INVALID,
/* 65 */ INVALID,
/* 66 */ INVALID,
/* 67 */ INVALID,
/* 68 */ INVALID,
/* 69 */ INVALID,
/* 6a */ INVALID,
/* 6b */ INVALID,
/* 6c */ INVALID,
/* 6d */ INVALID,
/* 6e */ INVALID,
/* 6f */ INVALID,
/* 70 */ INVALID,
/* 71 */ INVALID,
/* 72 */ INVALID,
/* 73 */ INVALID,
/* 74 */ INVALID,
/* 75 */ INVALID,
/* 76 */ INVALID,
/* 77 */ INVALID,
/* 78 */ INVALID,
/* 79 */ INVALID,
/* 7a */ INVALID,
/* 7b */ INVALID,
/* 7c */ INVALID,
/* 7d */ INVALID,
/* 7e */ INVALID,
};
/*
* Parse table for the base keyboard state. The index is the start of
* a new sequence.
*
* Questionable or unusual cases:
* 02 On some SPARC keyboards, this is the scan code for the STOP
* key. The KEY() value was chosen so that it maps to a
* HOLE entry in the keytables in kb8042_keytables.c; therefore,
* the STOP key code is only translated properly when kb8042
* is "emulating" a USB keyboard (which it is by default--
* see conskbd.c).
* 7f Old kd code says this is an 84-key SysReq. Manual says no.
* 87 Old kd code says 1 (num). Manual says no.
* 8c Old kd code says / (num). Manual says no.
* aa POST OK. Handled by code.
* e0 Extend prefix. Handled by code. (switches to E0 table)
* e1 Extend prefix. Handled by code. (Pause key only)
* f0 Break prefix. Handled by code.
* f1 Korean Hangul/Hanja key. Handled by code.
* f2 Korean Hangul key. Handled by code.
* ff Keyboard internal buffer overrun. Handled by code.
*
* Other values past the end of the table are treated as INVALID.
*/
static const unsigned char keytab_base_set2[] = {
/* scan state keycap */
/* 00 */ INVALID,
/* 01 */ KEY(120), /* F9 */
#if defined(__sparc)
/* 02 */ KEY(K8042_STOP), /* STOP */
#else
/* 02 */ INVALID, /* F7? Old code says so but manual doesn't */
#endif
/* 03 */ KEY(116), /* F5 */
/* 04 */ KEY(114), /* F3 */
/* 05 */ KEY(112), /* F1 */
/* 06 */ KEY(113), /* F2 */
/* 07 */ KEY(123), /* F12 */
/* 08 */ INVALID,
/* 09 */ KEY(121), /* F10 */
/* 0a */ KEY(119), /* F8 */
/* 0b */ KEY(117), /* F6 */
/* 0c */ KEY(115), /* F4 */
/* 0d */ KEY(16), /* tab */
/* 0e */ KEY(1), /* ` */
/* 0f */ INVALID,
/* 10 */ INVALID,
/* 11 */ KEY(60), /* L Alt */
/* 12 */ KEY(44), /* L Shift */
/* 13 */ KEY(133), /* Japanese 106-key */
/* 14 */ KEY(58), /* L Ctrl */
/* 15 */ KEY(17), /* Q */
/* 16 */ KEY(2), /* 1 */
/* 17 */ INVALID,
/* 18 */ INVALID,
/* 19 */ INVALID,
/* 1a */ KEY(46), /* Z */
/* 1b */ KEY(32), /* S */
/* 1c */ KEY(31), /* A */
/* 1d */ KEY(18), /* W */
/* 1e */ KEY(3), /* 2 */
/* 1f */ INVALID,
/* 20 */ INVALID,
/* 21 */ KEY(48), /* C */
/* 22 */ KEY(47), /* X */
/* 23 */ KEY(33), /* D */
/* 24 */ KEY(19), /* E */
/* 25 */ KEY(5), /* 4 */
/* 26 */ KEY(4), /* 3 */
/* 27 */ INVALID,
/* 28 */ INVALID,
/* 29 */ KEY(61), /* Space */
/* 2a */ KEY(49), /* V */
/* 2b */ KEY(34), /* F */
/* 2c */ KEY(21), /* T */
/* 2d */ KEY(20), /* R */
/* 2e */ KEY(6), /* 5 */
/* 2f */ INVALID,
/* 30 */ INVALID,
/* 31 */ KEY(51), /* N */
/* 32 */ KEY(50), /* B */
/* 33 */ KEY(36), /* H */
/* 34 */ KEY(35), /* G */
/* 35 */ KEY(22), /* Y */
/* 36 */ KEY(7), /* 6 */
/* 37 */ INVALID,
/* 38 */ INVALID,
/* 39 */ INVALID,
/* 3a */ KEY(52), /* M */
/* 3b */ KEY(37), /* J */
/* 3c */ KEY(23), /* U */
/* 3d */ KEY(8), /* 7 */
/* 3e */ KEY(9), /* 8 */
/* 3f */ INVALID,
/* 40 */ INVALID,
/* 41 */ KEY(53), /* , */
/* 42 */ KEY(38), /* K */
/* 43 */ KEY(24), /* I */
/* 44 */ KEY(25), /* O */
/* 45 */ KEY(11), /* 0 */
/* 46 */ KEY(10), /* 9 */
/* 47 */ INVALID,
/* 48 */ INVALID,
/* 49 */ KEY(54), /* . */
/* 4a */ KEY(55), /* / */
/* 4b */ KEY(39), /* L */
/* 4c */ KEY(40), /* ; */
/* 4d */ KEY(26), /* P */
/* 4e */ KEY(12), /* - */
/* 4f */ INVALID,
/* 50 */ INVALID,
/* 51 */ KEY(56), /* Japanese 106-key */
/* 52 */ KEY(41), /* ' */
/* 53 */ INVALID,
/* 54 */ KEY(27), /* [ */
/* 55 */ KEY(13), /* = */
/* 56 */ INVALID,
/* 57 */ INVALID,
/* 58 */ KEY(30), /* CapsLock */
/* 59 */ KEY(57), /* R Shift */
/* 5a */ KEY(43), /* Enter (main) */
/* 5b */ KEY(28), /* ] */
/* 5c */ INVALID,
/* 5d */ KEY(29), /* \, key 42 for 102-key */
/* 5e */ INVALID,
/* 5f */ INVALID,
/* 60 */ INVALID,
/* 61 */ KEY(45), /* 102-key only, typically </> */
/* 62 */ INVALID,
/* 63 */ INVALID,
/* 64 */ KEY(132), /* Japanese 106-key */
/* 65 */ INVALID,
/* 66 */ KEY(15), /* backspace */
/* 67 */ KEY(131), /* Japanese 106-key */
/* 68 */ INVALID,
/* 69 */ KEY(93), /* 1 (num) */
/* 6a */ KEY(14), /* Japanese 106-key */
/* 6b */ KEY(92), /* 4 (num) */
/* 6c */ KEY(91), /* 7 (num) */
/* 6d */ INVALID,
/* 6e */ INVALID,
/* 6f */ INVALID,
/* 70 */ KEY(99), /* 0 (num) */
/* 71 */ KEY(104), /* . (num) */
/* 72 */ KEY(98), /* 2 (num) */
/* 73 */ KEY(97), /* 5 (num) */
/* 74 */ KEY(102), /* 6 (num) */
/* 75 */ KEY(96), /* 8 (num) */
/* 76 */ KEY(110), /* Esc */
/* 77 */ KEY(90), /* NumLock */
/* 78 */ KEY(122), /* F11 */
/* 79 */ KEY(106), /* + (num) */
/* 7a */ KEY(103), /* 3 (num) */
/* 7b */ KEY(105), /* - (num) */
/* 7c */ KEY(100), /* * (num) */
/* 7d */ KEY(101), /* 9 (num) */
/* 7e */ KEY(125), /* Scroll Lock */
/* 7f */ INVALID, /* 84-key SysReq? Manual says no. */
/* 80 */ INVALID,
/* 81 */ INVALID,
/* 82 */ INVALID,
/* 83 */ KEY(118), /* F7 */
/* 84 */ KEY(124), /* PrintScreen (w/ Alt = SysRq) */
};
/*
* Parse table after receiving an E0 prefix code.
*
* Generally speaking, keys that were added on the 101-key keyboard are
* represented as an E0 followed by the code for an 84-key key. Software
* ignorant of the 101-key keyboard ignores the E0 and so is handled
* compatibly. Many of these variants involve "fake" shift presses
* and releases for compatibility; these are also prefixed with E0.
* We ignore these fake shifts.
*/
static const unsigned char keytab_e0_set2[] = {
/* 00 */ INVALID,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
/* 04 */ INVALID,
/* 05 */ INVALID,
/* 06 */ INVALID,
/* 07 */ INVALID,
/* 08 */ INVALID,
/* 09 */ INVALID,
/* 0a */ INVALID,
/* 0b */ INVALID,
/* 0c */ INVALID,
/* 0d */ INVALID,
/* 0e */ INVALID,
/* 0f */ INVALID,
/* 10 */ INVALID,
/* 11 */ KEY(62), /* R Alt */
/* 12 */ IGNORE, /* Fake L Shift */
/* 13 */ INVALID,
/* 14 */ KEY(64), /* R Ctrl */
/* 15 */ INVALID,
/* 16 */ INVALID,
/* 17 */ INVALID,
/* 18 */ INVALID,
/* 19 */ INVALID,
/* 1a */ INVALID,
/* 1b */ INVALID,
/* 1c */ INVALID,
/* 1d */ INVALID,
/* 1e */ INVALID,
/* 1f */ KEY(59), /* L Window (104-key) */
/* 20 */ INVALID,
/* 21 */ INVALID,
/* 22 */ INVALID,
/* 23 */ INVALID,
/* 24 */ INVALID,
/* 25 */ INVALID,
/* 26 */ INVALID,
/* 27 */ KEY(63), /* R Window (104-key) */
/* 28 */ INVALID,
/* 29 */ INVALID,
/* 2a */ INVALID,
/* 2b */ INVALID,
/* 2c */ INVALID,
/* 2d */ INVALID,
/* 2e */ INVALID,
/* 2f */ KEY(65), /* Menu (104-key) */
/* 30 */ INVALID,
/* 31 */ INVALID,
/* 32 */ INVALID,
/* 33 */ INVALID,
/* 34 */ INVALID,
/* 35 */ INVALID,
/* 36 */ INVALID,
/* 37 */ INVALID,
/* 38 */ INVALID,
/* 39 */ INVALID,
/* 3a */ INVALID,
/* 3b */ INVALID,
/* 3c */ INVALID,
/* 3d */ INVALID,
/* 3e */ INVALID,
/* 3f */ INVALID,
/* 40 */ INVALID,
/* 41 */ INVALID,
/* 42 */ INVALID,
/* 43 */ INVALID,
/* 44 */ INVALID,
/* 45 */ INVALID,
/* 46 */ INVALID,
/* 47 */ INVALID,
/* 48 */ INVALID,
/* 49 */ INVALID,
/* 4a */ KEY(95), /* / (num) */
/* 4b */ INVALID,
/* 4c */ INVALID,
/* 4d */ INVALID,
/* 4e */ INVALID,
/* 4f */ INVALID,
/* 50 */ INVALID,
/* 51 */ INVALID,
/* 52 */ INVALID,
/* 53 */ INVALID,
/* 54 */ INVALID,
/* 55 */ INVALID,
/* 56 */ INVALID,
/* 57 */ INVALID,
/* 58 */ INVALID,
/* 59 */ IGNORE, /* Fake R Shift */
/* 5a */ KEY(108), /* Enter (num) */
/* 5b */ INVALID,
/* 5c */ INVALID,
/* 5d */ INVALID,
/* 5e */ INVALID,
/* 5f */ INVALID,
/* 60 */ INVALID,
/* 61 */ INVALID,
/* 62 */ INVALID,
/* 63 */ INVALID,
/* 64 */ INVALID,
/* 65 */ INVALID,
/* 66 */ INVALID,
/* 67 */ INVALID,
/* 68 */ INVALID,
/* 69 */ KEY(81), /* End (arrow) */
/* 6a */ INVALID,
/* 6b */ KEY(79), /* Left (arrow) */
/* 6c */ KEY(80), /* Home (arrow) */
/* 6d */ INVALID,
/* 6e */ INVALID,
/* 6f */ INVALID,
/* 70 */ KEY(75), /* Insert (arrow) */
/* 71 */ KEY(76), /* Delete (arrow) */
/* 72 */ KEY(84), /* Down (arrow) */
/* 73 */ INVALID,
/* 74 */ KEY(89), /* Right (arrow) */
/* 75 */ KEY(83), /* Up (arrow) */
/* 76 */ INVALID,
/* 77 */ INVALID,
/* 78 */ INVALID,
/* 79 */ INVALID,
/* 7a */ KEY(86), /* PgDn (arrow) */
/* 7b */ INVALID,
/* 7c */ KEY(124), /* PrintScreen (no Alt) */
/* 7d */ KEY(85), /* PgUp (arrow) */
/* 7e */ KEY(126), /* Pause (w/Ctrl = Break) */
};
/*
* Initialize the translation state machine.
*/
int
KeyboardConvertScan_init(struct kb8042 *kb8042, int scanset)
{
kb8042->parse_scan_state = STATE_IDLE;
kb8042->break_received = 0;
if (scanset == 1) {
KeyboardConvertScan_fn = &KeyboardConvertScan_set1;
keytab_base = keytab_base_set1;
keytab_base_length = NELEM(keytab_base_set1);
keytab_e0 = keytab_e0_set1;
keytab_e0_length = NELEM(keytab_e0_set1);
} else if (scanset == 2) {
KeyboardConvertScan_fn = &KeyboardConvertScan_set2;
keytab_base = keytab_base_set2;
keytab_base_length = NELEM(keytab_base_set2);
keytab_e0 = keytab_e0_set2;
keytab_e0_length = NELEM(keytab_e0_set2);
} else {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* KeyboardConvertScan(*kb8042, scan, *keynum, *state
* *synthetic_release_needed)
*
* State machine that takes scan codes from the keyboard and resolves
* them to key numbers using the above tables. Returns B_TRUE if this
* scan code completes a scan code sequence, in which case "keynum",
* "state", and "synthetic_release_needed" will be filled in correctly.
*
* "synthetic_release_needed" is a hack to handle the additional two
* keys on a Korean keyboard. They report press only, so we tell the
* upper layer to synthesize the release.
*/
boolean_t
KeyboardConvertScan(
struct kb8042 *kb8042,
unsigned char scan,
int *keynum,
enum keystate *state,
boolean_t *synthetic_release_needed)
{
ASSERT(KeyboardConvertScan_fn != NULL);
return ((*KeyboardConvertScan_fn)(kb8042, scan, keynum, state,
synthetic_release_needed));
}
boolean_t
KeyboardConvertScan_set1(
struct kb8042 *kb8042,
unsigned char scan,
int *keynum,
enum keystate *state,
boolean_t *synthetic_release_needed)
{
*synthetic_release_needed = B_FALSE;
*state = KEY_PRESSED;
switch (scan) {
/*
* First, handle special cases.
* ACK has already been handled by our caller.
*/
case KB_ERROR:
/*
* Perhaps we should reset state here,
* since we no longer know what's going on.
*/
return (B_FALSE);
case KB_POST_FAIL:
/*
* Perhaps we should reset the LEDs now.
* If so, this check should probably be in the main line.
* Perhaps we should tell the higher layers that the
* keyboard has been reset.
*/
/*
* Reset to idle
*/
kb8042->parse_scan_state = STATE_IDLE;
return (B_FALSE);
case KXT_EXTEND:
case KXT_EXTEND2:
case KXT_HANGUL_HANJA:
case KXT_HANGUL:
/*
* Exclude these keys from the "default" test below.
*/
break;
default:
/*
* See if it was a key release.
*/
if (scan > 0x80) {
*state = KEY_RELEASED;
scan -= 0x80;
}
break;
}
if (kb8042->break_received) {
*state = KEY_RELEASED;
kb8042->break_received = 0;
}
switch (kb8042->parse_scan_state) {
case STATE_IDLE:
switch (scan) {
case KXT_EXTEND:
kb8042->parse_scan_state = STATE_E0;
return (B_FALSE);
case KXT_EXTEND2:
kb8042->parse_scan_state = STATE_E1;
return (B_FALSE);
/*
* We could do the next two in the table, but it would
* require nearly doubling the size of the table.
*
* Also, for some stupid reason these two report presses
* only. We tell the upper layer to synthesize a release.
*/
case KXT_HANGUL_HANJA:
*keynum = KEY(150);
*synthetic_release_needed = B_TRUE;
break;
case KXT_HANGUL:
*keynum = KEY(151);
*synthetic_release_needed = B_TRUE;
break;
default:
/*
* Regular scan code
*/
if (scan < keytab_base_length)
*keynum = keytab_base[scan];
else
*keynum = INVALID;
break;
}
break;
case STATE_E0: /* Mostly 101-key additions */
if (scan < keytab_e0_length)
*keynum = keytab_e0[scan];
else
*keynum = INVALID;
break;
case STATE_E1: /* Pause key only */
switch (scan) {
case 0x1d:
kb8042->parse_scan_state = STATE_E1_1D;
return (B_FALSE);
default:
*keynum = INVALID;
break;
}
break;
case STATE_E1_1D: /* Pause key only */
switch (scan) {
case 0x45:
*keynum = KEY(126); /* Pause */
break;
default:
*keynum = INVALID;
break;
}
break;
}
/*
* The results (*keynum, *state, and *synthetic_release_needed)
* have been filled in, but they are valid only if we return
* B_TRUE which is only done below. If we make it to here, we
* have completed a scan code sequence, so reset parse_scan_state.
*/
kb8042->parse_scan_state = STATE_IDLE;
switch (*keynum) {
case KEYIGN: /* not a key, nor an error */
return (B_FALSE); /* also not a final keycode */
case KEYBAD: /* not part of a legit sequence? */
return (B_FALSE); /* and return not a final keycode */
default:
/*
* If we're here, it's a valid keycode. We've already
* filled in the return values; return success.
*/
return (B_TRUE); /* resolved to a key */
}
}
/*
* KeyboardConvertScan(*kb8042, scan, *keynum, *state
* *synthetic_release_needed)
*
* State machine that takes scan codes from the keyboard and resolves
* them to key numbers using the above tables. Returns B_TRUE if this
* scan code completes a scan code sequence, in which case "keynum",
* "state", and "synthetic_release_needed" will be filled in correctly.
*
* "synthetic_release_needed" is a hack to handle the additional two
* keys on a Korean keyboard. They report press only, so we tell the
* upper layer to synthesize the release.
*/
boolean_t
KeyboardConvertScan_set2(
struct kb8042 *kb8042,
unsigned char scan,
int *keynum,
enum keystate *state,
boolean_t *synthetic_release_needed)
{
*synthetic_release_needed = B_FALSE;
*state = KEY_PRESSED;
switch (scan) {
/*
* First, handle special cases.
* ACK has already been handled by our caller.
*/
/*
* KAT_BREAK is 0xF0. It is the same as the break code for Japanese
* key 133.
* Therefore we don't treat it specially here.
*/
case KAT_BREAK:
/* Switch states so we can recognize the code that follows */
kb8042->break_received = 1;
return (B_FALSE); /* not a final keycode */
case KB_ERROR:
/*
* Perhaps we should reset state here,
* since we no longer know what's going on.
*/
return (B_FALSE);
case KB_POST_OK:
case KB_POST_FAIL:
/*
* Perhaps we should reset the LEDs now.
* If so, this check should probably be in the main line.
* Perhaps we should tell the higher layers that the
* keyboard has been reset.
*/
/*
* Reset to idle
*/
kb8042->parse_scan_state = STATE_IDLE;
return (B_FALSE);
}
if (kb8042->break_received) {
*state = KEY_RELEASED;
kb8042->break_received = 0;
}
switch (kb8042->parse_scan_state) {
case STATE_IDLE:
switch (scan) {
case KXT_EXTEND:
kb8042->parse_scan_state = STATE_E0;
return (B_FALSE);
case KXT_EXTEND2:
kb8042->parse_scan_state = STATE_E1;
return (B_FALSE);
/*
* We could do the next two in the table, but it would
* require nearly doubling the size of the table.
*
* Also, for some stupid reason these two report presses
* only. We tell the upper layer to synthesize a release.
*/
case KXT_HANGUL_HANJA:
*keynum = KEY(150);
*synthetic_release_needed = B_TRUE;
break;
case KXT_HANGUL:
*keynum = KEY(151);
*synthetic_release_needed = B_TRUE;
break;
default:
/*
* Regular scan code
*/
if (scan < keytab_base_length)
*keynum = keytab_base[scan];
else
*keynum = INVALID;
break;
}
break;
case STATE_E0: /* Mostly 101-key additions */
if (scan < keytab_e0_length)
*keynum = keytab_e0[scan];
else
*keynum = INVALID;
break;
case STATE_E1: /* Pause key only */
switch (scan) {
case 0x14:
kb8042->parse_scan_state = STATE_E1_14;
return (B_FALSE);
default:
*keynum = INVALID;
break;
}
break;
case STATE_E1_14: /* Pause key only */
if (scan == 0x77) {
kb8042->parse_scan_state = STATE_E1_14_77;
return (B_FALSE);
} else {
*keynum = INVALID;
}
break;
case STATE_E1_14_77:
if (scan == 0xE1) {
kb8042->parse_scan_state = STATE_E1_14_77_E1;
return (B_FALSE);
} else {
*keynum = INVALID;
}
break;
case STATE_E1_14_77_E1:
if (scan == 0xF0) {
kb8042->parse_scan_state = STATE_E1_14_77_E1_F0;
return (B_FALSE);
} else {
*keynum = INVALID;
}
break;
case STATE_E1_14_77_E1_F0:
if (scan == 0x14) {
kb8042->parse_scan_state = STATE_E1_14_77_E1_F0_14;
return (B_FALSE);
} else {
*keynum = INVALID;
}
break;
case STATE_E1_14_77_E1_F0_14:
if (scan == 0xF0) {
kb8042->parse_scan_state = STATE_E1_14_77_E1_F0_14_F0;
return (B_FALSE);
} else {
*keynum = INVALID;
}
break;
case STATE_E1_14_77_E1_F0_14_F0:
if (scan == 0x77) {
*keynum = KEY(126); /* Pause */
} else {
*keynum = INVALID;
}
break;
}
/*
* The results (*keynum, *state, and *synthetic_release_needed)
* have been filled in, but they are valid only if we return
* B_TRUE which is only done below. If we make it to here, we
* have completed a scan code sequence, so reset parse_scan_state.
*/
if (kb8042->break_received) {
*state = KEY_RELEASED;
kb8042->break_received = 0;
}
kb8042->parse_scan_state = STATE_IDLE;
switch (*keynum) {
case KEYIGN: /* not a key, nor an error */
return (B_FALSE); /* also not a final keycode */
case KEYBAD: /* not part of a legit sequence? */
return (B_FALSE); /* and return not a final keycode */
default:
/*
* If we're here, it's a valid keycode. We've already
* filled in the return values; return success.
*/
return (B_TRUE); /* resolved to a key */
}
}