| /* |
| * 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 */ |
| } |
| } |