10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
59026SSeth.Goldberg@Sun.COM * Common Development and Distribution License (the "License").
6*9027SSeth.Goldberg@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
229026SSeth.Goldberg@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/stream.h>
280Sstevel@tonic-gate #include <sys/kbd.h>
290Sstevel@tonic-gate #include <sys/kbtrans.h>
300Sstevel@tonic-gate #include <sys/sunddi.h>
310Sstevel@tonic-gate #include <sys/consdev.h>
320Sstevel@tonic-gate #include <sys/promif.h>
330Sstevel@tonic-gate #include "kb8042.h"
340Sstevel@tonic-gate
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate * A note on the use of prom_printf here: Most of these routines can be
370Sstevel@tonic-gate * called from "polled mode", where we're servicing I/O requests from kmdb.
380Sstevel@tonic-gate * Normal system services are not available from polled mode; cmn_err will
390Sstevel@tonic-gate * not work. prom_printf is the only safe output mechanism.
400Sstevel@tonic-gate */
410Sstevel@tonic-gate
420Sstevel@tonic-gate #define KEYBAD 0xff /* should generate an error */
430Sstevel@tonic-gate #define KEYIGN 0xfe /* ignore this sequence */
440Sstevel@tonic-gate
450Sstevel@tonic-gate #define KEY(code) (code)
460Sstevel@tonic-gate #define INVALID KEYBAD
470Sstevel@tonic-gate #define IGNORE KEYIGN
480Sstevel@tonic-gate
49822Ssethg #define NELEM(a) (sizeof (a) / sizeof (a)[0])
50822Ssethg
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate * These are the states of our parsing machine:
530Sstevel@tonic-gate */
54822Ssethg #define STATE_IDLE 0x00000001 /* Awaiting the start of a sequence */
55822Ssethg #define STATE_E0 0x00000002 /* Rec'd an E0 */
56822Ssethg #define STATE_E1 0x00000004 /* Rec'd an E1 (Pause key only) */
57822Ssethg #define STATE_E1_1D 0x00000008 /* Rec'd an E1 1D (Pause key only) */
58822Ssethg #define STATE_E1_14 0x00000010 /* Rec'd an E1 14 (Pause key only) */
59822Ssethg #define STATE_E1_14_77 0x00000020
60822Ssethg #define STATE_E1_14_77_E1 0x00000040
61822Ssethg #define STATE_E1_14_77_E1_F0 0x00000080
62822Ssethg #define STATE_E1_14_77_E1_F0_14 0x00000100
63822Ssethg #define STATE_E1_14_77_E1_F0_14_F0 0x00000200
640Sstevel@tonic-gate
65822Ssethg static boolean_t KeyboardConvertScan_set1(struct kb8042 *, unsigned char, int *,
66822Ssethg enum keystate *, boolean_t *);
67822Ssethg static boolean_t KeyboardConvertScan_set2(struct kb8042 *, unsigned char, int *,
68822Ssethg enum keystate *, boolean_t *);
690Sstevel@tonic-gate
70822Ssethg static const unsigned char *keytab_base = NULL;
71822Ssethg static int keytab_base_length = 0;
72822Ssethg static const unsigned char *keytab_e0 = NULL;
73822Ssethg static int keytab_e0_length = 0;
74822Ssethg static boolean_t (*KeyboardConvertScan_fn)(struct kb8042 *, unsigned char,
75822Ssethg int *, enum keystate *, boolean_t *) = NULL;
76822Ssethg
77822Ssethg static const unsigned char keytab_base_set1[] = {
780Sstevel@tonic-gate /* scan key number keycap */
790Sstevel@tonic-gate /* 00 */ INVALID,
800Sstevel@tonic-gate /* 01 */ KEY(110), /* Esc */
810Sstevel@tonic-gate /* 02 */ KEY(2), /* 1 */
820Sstevel@tonic-gate /* 03 */ KEY(3), /* 2 */
830Sstevel@tonic-gate /* 04 */ KEY(4), /* 3 */
840Sstevel@tonic-gate /* 05 */ KEY(5), /* 4 */
850Sstevel@tonic-gate /* 06 */ KEY(6), /* 5 */
860Sstevel@tonic-gate /* 07 */ KEY(7), /* 6 */
870Sstevel@tonic-gate /* 08 */ KEY(8), /* 7 */
880Sstevel@tonic-gate /* 09 */ KEY(9), /* 8 */
890Sstevel@tonic-gate /* 0a */ KEY(10), /* 9 */
900Sstevel@tonic-gate /* 0b */ KEY(11), /* 0 */
910Sstevel@tonic-gate /* 0c */ KEY(12), /* - */
920Sstevel@tonic-gate /* 0d */ KEY(13), /* = */
930Sstevel@tonic-gate /* 0e */ KEY(15), /* backspace */
940Sstevel@tonic-gate /* 0f */ KEY(16), /* tab */
950Sstevel@tonic-gate
960Sstevel@tonic-gate /* 10 */ KEY(17), /* Q */
970Sstevel@tonic-gate /* 11 */ KEY(18), /* W */
980Sstevel@tonic-gate /* 12 */ KEY(19), /* E */
990Sstevel@tonic-gate /* 13 */ KEY(20), /* R */
1000Sstevel@tonic-gate /* 14 */ KEY(21), /* T */
1010Sstevel@tonic-gate /* 15 */ KEY(22), /* Y */
1020Sstevel@tonic-gate /* 16 */ KEY(23), /* U */
1030Sstevel@tonic-gate /* 17 */ KEY(24), /* I */
1040Sstevel@tonic-gate /* 18 */ KEY(25), /* O */
1050Sstevel@tonic-gate /* 19 */ KEY(26), /* P */
1060Sstevel@tonic-gate /* 1a */ KEY(27), /* [ */
1070Sstevel@tonic-gate /* 1b */ KEY(28), /* ] */
1080Sstevel@tonic-gate /* 1c */ KEY(43), /* Enter (main) */
1090Sstevel@tonic-gate /* 1d */ KEY(58), /* L Ctrl */
1100Sstevel@tonic-gate /* 1e */ KEY(31), /* A */
1110Sstevel@tonic-gate /* 1f */ KEY(32), /* S */
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate /* 20 */ KEY(33), /* D */
1140Sstevel@tonic-gate /* 21 */ KEY(34), /* F */
1150Sstevel@tonic-gate /* 22 */ KEY(35), /* G */
1160Sstevel@tonic-gate /* 23 */ KEY(36), /* H */
1170Sstevel@tonic-gate /* 24 */ KEY(37), /* J */
1180Sstevel@tonic-gate /* 25 */ KEY(38), /* K */
1190Sstevel@tonic-gate /* 26 */ KEY(39), /* L */
1200Sstevel@tonic-gate /* 27 */ KEY(40), /* ; */
1210Sstevel@tonic-gate /* 28 */ KEY(41), /* ' */
1220Sstevel@tonic-gate /* 29 */ KEY(1), /* ` */
1230Sstevel@tonic-gate /* 2a */ KEY(44), /* L Shift */
1240Sstevel@tonic-gate /* 2b */ KEY(29), /* \ */
1250Sstevel@tonic-gate /* 2c */ KEY(46), /* Z */
1260Sstevel@tonic-gate /* 2d */ KEY(47), /* X */
1270Sstevel@tonic-gate /* 2e */ KEY(48), /* C */
1280Sstevel@tonic-gate /* 2f */ KEY(49), /* V */
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate /* 30 */ KEY(50), /* B */
1310Sstevel@tonic-gate /* 31 */ KEY(51), /* N */
1320Sstevel@tonic-gate /* 32 */ KEY(52), /* M */
1330Sstevel@tonic-gate /* 33 */ KEY(53), /* , */
1340Sstevel@tonic-gate /* 34 */ KEY(54), /* . */
1350Sstevel@tonic-gate /* 35 */ KEY(55), /* / */
1360Sstevel@tonic-gate /* 36 */ KEY(57), /* R Shift */
1370Sstevel@tonic-gate /* 37 */ KEY(100), /* * (num) */
1380Sstevel@tonic-gate /* 38 */ KEY(60), /* L Alt */
1390Sstevel@tonic-gate /* 39 */ KEY(61), /* Space */
1400Sstevel@tonic-gate /* 3a */ KEY(30), /* CapsLock */
1410Sstevel@tonic-gate /* 3b */ KEY(112), /* F1 */
1420Sstevel@tonic-gate /* 3c */ KEY(113), /* F2 */
1430Sstevel@tonic-gate /* 3d */ KEY(114), /* F3 */
1440Sstevel@tonic-gate /* 3e */ KEY(115), /* F4 */
1450Sstevel@tonic-gate /* 3f */ KEY(116), /* F5 */
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate /* 40 */ KEY(117), /* F6 */
1480Sstevel@tonic-gate /* 41 */ KEY(118), /* F7 */
1490Sstevel@tonic-gate /* 42 */ KEY(119), /* F8 */
1500Sstevel@tonic-gate /* 43 */ KEY(120), /* F9 */
1510Sstevel@tonic-gate /* 44 */ KEY(121), /* F10 */
1520Sstevel@tonic-gate /* 45 */ KEY(90), /* NumLock */
1530Sstevel@tonic-gate /* 46 */ KEY(125), /* Scroll Lock */
1540Sstevel@tonic-gate /* 47 */ KEY(91), /* 7 (num) */
1550Sstevel@tonic-gate /* 48 */ KEY(96), /* 8 (num) */
1560Sstevel@tonic-gate /* 49 */ KEY(101), /* 9 (num) */
1570Sstevel@tonic-gate /* 4a */ KEY(105), /* - (num) */
1580Sstevel@tonic-gate /* 4b */ KEY(92), /* 4 (num) */
1590Sstevel@tonic-gate /* 4c */ KEY(97), /* 5 (num) */
1600Sstevel@tonic-gate /* 4d */ KEY(102), /* 6 (num) */
1610Sstevel@tonic-gate /* 4e */ KEY(106), /* + (num) */
1620Sstevel@tonic-gate /* 4f */ KEY(93), /* 1 (num) */
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate /* 50 */ KEY(98), /* 2 (num) */
1650Sstevel@tonic-gate /* 51 */ KEY(103), /* 3 (num) */
1660Sstevel@tonic-gate /* 52 */ KEY(99), /* 0 (num) */
1670Sstevel@tonic-gate /* 53 */ KEY(104), /* . (num) */
1680Sstevel@tonic-gate /* 54 */ KEY(124), /* PrintScreen (with Alt) */
1690Sstevel@tonic-gate /* 55 */ INVALID,
1700Sstevel@tonic-gate /* 56 */ KEY(45), /* not labled (102-key only) */
1710Sstevel@tonic-gate /* 57 */ KEY(122), /* F11 */
1720Sstevel@tonic-gate /* 58 */ KEY(123), /* F12 */
1730Sstevel@tonic-gate /* 59 */ INVALID,
1740Sstevel@tonic-gate /* 5a */ INVALID,
1750Sstevel@tonic-gate /* 5b */ INVALID,
1760Sstevel@tonic-gate /* 5c */ INVALID,
1770Sstevel@tonic-gate /* 5d */ INVALID,
1780Sstevel@tonic-gate /* 5e */ INVALID,
1790Sstevel@tonic-gate /* 5f */ INVALID,
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate /* 60 */ INVALID,
1820Sstevel@tonic-gate /* 61 */ INVALID,
1830Sstevel@tonic-gate /* 62 */ INVALID,
1840Sstevel@tonic-gate /* 63 */ INVALID,
1850Sstevel@tonic-gate /* 64 */ INVALID,
1860Sstevel@tonic-gate /* 65 */ INVALID,
1870Sstevel@tonic-gate /* 66 */ INVALID,
1880Sstevel@tonic-gate /* 67 */ INVALID,
1890Sstevel@tonic-gate /* 68 */ INVALID,
1900Sstevel@tonic-gate /* 69 */ INVALID,
1910Sstevel@tonic-gate /* 6a */ INVALID,
1920Sstevel@tonic-gate /* 6b */ INVALID,
1930Sstevel@tonic-gate /* 6c */ INVALID,
1940Sstevel@tonic-gate /* 6d */ INVALID,
1950Sstevel@tonic-gate /* 6e */ INVALID,
1960Sstevel@tonic-gate /* 6f */ INVALID,
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate /* 70 */ KEY(133), /* Japanese 106-key keyboard */
1990Sstevel@tonic-gate /* 71 */ INVALID,
2000Sstevel@tonic-gate /* 72 */ INVALID,
2010Sstevel@tonic-gate /* 73 */ KEY(56), /* Japanese 106-key keyboard */
2020Sstevel@tonic-gate /* 74 */ INVALID,
2030Sstevel@tonic-gate /* 75 */ INVALID,
2040Sstevel@tonic-gate /* 76 */ INVALID,
2050Sstevel@tonic-gate /* 77 */ INVALID,
2060Sstevel@tonic-gate /* 78 */ INVALID,
2070Sstevel@tonic-gate /* 79 */ KEY(132), /* Japanese 106-key keyboard */
2080Sstevel@tonic-gate /* 7a */ INVALID,
2090Sstevel@tonic-gate /* 7b */ KEY(131), /* Japanese 106-key keyboard */
2100Sstevel@tonic-gate /* 7c */ INVALID,
2110Sstevel@tonic-gate /* 7d */ KEY(14), /* Japanese 106-key keyboard */
2120Sstevel@tonic-gate /* 7e */ INVALID,
2130Sstevel@tonic-gate /* 7f */ INVALID,
2140Sstevel@tonic-gate };
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate /*
2170Sstevel@tonic-gate * Parse table after receiving an E0 prefix code.
2180Sstevel@tonic-gate *
2190Sstevel@tonic-gate * Generally speaking, keys that were added on the 101-key keyboard are
2200Sstevel@tonic-gate * represented as an E0 followed by the code for an 84-key key. Software
2210Sstevel@tonic-gate * ignorant of the 101-key keyboard ignores the E0 and so is handled
2220Sstevel@tonic-gate * compatibly. Many of these variants involve "fake" shift presses
2230Sstevel@tonic-gate * and releases for compatibility; these are also prefixed with E0.
2240Sstevel@tonic-gate * We ignore these fake shifts.
2250Sstevel@tonic-gate */
226822Ssethg static const unsigned char keytab_e0_set1[] = {
2270Sstevel@tonic-gate /* 00 */ INVALID,
2280Sstevel@tonic-gate /* 01 */ INVALID,
2290Sstevel@tonic-gate /* 02 */ INVALID,
2300Sstevel@tonic-gate /* 03 */ INVALID,
2310Sstevel@tonic-gate /* 04 */ INVALID,
2320Sstevel@tonic-gate /* 05 */ INVALID,
2330Sstevel@tonic-gate /* 06 */ INVALID,
2340Sstevel@tonic-gate /* 07 */ INVALID,
2350Sstevel@tonic-gate /* 08 */ INVALID,
2360Sstevel@tonic-gate /* 09 */ INVALID,
2370Sstevel@tonic-gate /* 0a */ INVALID,
2380Sstevel@tonic-gate /* 0b */ INVALID,
2390Sstevel@tonic-gate /* 0c */ INVALID,
2400Sstevel@tonic-gate /* 0d */ INVALID,
2410Sstevel@tonic-gate /* 0e */ INVALID,
2420Sstevel@tonic-gate /* 0f */ INVALID,
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate /* 10 */ INVALID,
2450Sstevel@tonic-gate /* 11 */ INVALID,
2460Sstevel@tonic-gate /* 12 */ INVALID,
2470Sstevel@tonic-gate /* 13 */ INVALID,
2480Sstevel@tonic-gate /* 14 */ INVALID,
2490Sstevel@tonic-gate /* 15 */ INVALID,
2500Sstevel@tonic-gate /* 16 */ INVALID,
2510Sstevel@tonic-gate /* 17 */ INVALID,
2520Sstevel@tonic-gate /* 18 */ INVALID,
2530Sstevel@tonic-gate /* 19 */ INVALID,
2540Sstevel@tonic-gate /* 1a */ INVALID,
2550Sstevel@tonic-gate /* 1b */ INVALID,
2560Sstevel@tonic-gate /* 1c */ KEY(108), /* Enter (num) */
2570Sstevel@tonic-gate /* 1d */ KEY(64), /* R Ctrl */
2580Sstevel@tonic-gate /* 1e */ INVALID,
2590Sstevel@tonic-gate /* 1f */ INVALID,
2600Sstevel@tonic-gate
2619026SSeth.Goldberg@Sun.COM /* 20 */ KEY(235), /* Mute */
2620Sstevel@tonic-gate /* 21 */ INVALID,
2630Sstevel@tonic-gate /* 22 */ INVALID,
2640Sstevel@tonic-gate /* 23 */ INVALID,
2650Sstevel@tonic-gate /* 24 */ INVALID,
2660Sstevel@tonic-gate /* 25 */ INVALID,
2670Sstevel@tonic-gate /* 26 */ INVALID,
2680Sstevel@tonic-gate /* 27 */ INVALID,
2690Sstevel@tonic-gate /* 28 */ INVALID,
2700Sstevel@tonic-gate /* 29 */ INVALID,
2710Sstevel@tonic-gate /* 2a */ INVALID,
2720Sstevel@tonic-gate /* 2b */ INVALID,
2730Sstevel@tonic-gate /* 2c */ INVALID,
2740Sstevel@tonic-gate /* 2d */ INVALID,
2759026SSeth.Goldberg@Sun.COM /* 2e */ KEY(234), /* Volume Down */
2760Sstevel@tonic-gate /* 2f */ INVALID,
2770Sstevel@tonic-gate
2789026SSeth.Goldberg@Sun.COM /* 30 */ KEY(233), /* Volume Up */
2790Sstevel@tonic-gate /* 31 */ INVALID,
2800Sstevel@tonic-gate /* 32 */ INVALID,
2810Sstevel@tonic-gate /* 33 */ INVALID,
2820Sstevel@tonic-gate /* 34 */ INVALID,
2830Sstevel@tonic-gate /* 35 */ KEY(95), /* / (num) */
2840Sstevel@tonic-gate /* 36 */ INVALID,
2850Sstevel@tonic-gate /* 37 */ KEY(124), /* PrintScreen (no Alt) */
2860Sstevel@tonic-gate /* 38 */ KEY(62), /* R Alt */
2870Sstevel@tonic-gate /* 39 */ INVALID,
2880Sstevel@tonic-gate /* 3a */ INVALID,
2890Sstevel@tonic-gate /* 3b */ INVALID,
2900Sstevel@tonic-gate /* 3c */ INVALID,
2910Sstevel@tonic-gate /* 3d */ INVALID,
2920Sstevel@tonic-gate /* 3e */ INVALID,
2930Sstevel@tonic-gate /* 3f */ INVALID,
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /* 40 */ INVALID,
2960Sstevel@tonic-gate /* 41 */ INVALID,
2970Sstevel@tonic-gate /* 42 */ INVALID,
2980Sstevel@tonic-gate /* 43 */ INVALID,
2990Sstevel@tonic-gate /* 44 */ INVALID,
3000Sstevel@tonic-gate /* 45 */ INVALID,
3010Sstevel@tonic-gate /* 46 */ KEY(126), /* Pause (with Cntl) */
3020Sstevel@tonic-gate /* 47 */ KEY(80), /* Home (arrow) */
3030Sstevel@tonic-gate /* 48 */ KEY(83), /* Up (arrow) */
3040Sstevel@tonic-gate /* 49 */ KEY(85), /* PgUp (arrow) */
3050Sstevel@tonic-gate /* 4a */ INVALID,
3060Sstevel@tonic-gate /* 4b */ KEY(79), /* Left (arrow) */
3070Sstevel@tonic-gate /* 4c */ INVALID,
3080Sstevel@tonic-gate /* 4d */ KEY(89), /* Right (arrow) */
3090Sstevel@tonic-gate /* 4e */ INVALID,
3100Sstevel@tonic-gate /* 4f */ KEY(81), /* End (arrow) */
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate /* 50 */ KEY(84), /* Down (arrow) */
3130Sstevel@tonic-gate /* 51 */ KEY(86), /* PgDn (arrow) */
3140Sstevel@tonic-gate /* 52 */ KEY(75), /* Insert (arrow) */
3150Sstevel@tonic-gate /* 53 */ KEY(76), /* Delete (arrow) */
3160Sstevel@tonic-gate /* 54 */ INVALID,
3170Sstevel@tonic-gate /* 55 */ INVALID,
3180Sstevel@tonic-gate /* 56 */ INVALID,
3190Sstevel@tonic-gate /* 57 */ INVALID,
3200Sstevel@tonic-gate /* 58 */ INVALID,
3210Sstevel@tonic-gate /* 59 */ INVALID,
3220Sstevel@tonic-gate /* 5a */ INVALID,
3230Sstevel@tonic-gate /* 5b */ KEY(59), /* L Window (104-key) */
3240Sstevel@tonic-gate /* 5c */ KEY(63), /* R Window (104-key) */
3250Sstevel@tonic-gate /* 5d */ KEY(65), /* Menu (104-key) */
3260Sstevel@tonic-gate /* 5e */ INVALID,
3270Sstevel@tonic-gate /* 5f */ INVALID,
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate /* 60 */ INVALID,
3300Sstevel@tonic-gate /* 61 */ INVALID,
3310Sstevel@tonic-gate /* 62 */ INVALID,
3320Sstevel@tonic-gate /* 63 */ INVALID,
3330Sstevel@tonic-gate /* 64 */ INVALID,
3340Sstevel@tonic-gate /* 65 */ INVALID,
3350Sstevel@tonic-gate /* 66 */ INVALID,
3360Sstevel@tonic-gate /* 67 */ INVALID,
3370Sstevel@tonic-gate /* 68 */ INVALID,
3380Sstevel@tonic-gate /* 69 */ INVALID,
3390Sstevel@tonic-gate /* 6a */ INVALID,
3400Sstevel@tonic-gate /* 6b */ INVALID,
3410Sstevel@tonic-gate /* 6c */ INVALID,
3420Sstevel@tonic-gate /* 6d */ INVALID,
3430Sstevel@tonic-gate /* 6e */ INVALID,
3440Sstevel@tonic-gate /* 6f */ INVALID,
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate /* 70 */ INVALID,
3470Sstevel@tonic-gate /* 71 */ INVALID,
3480Sstevel@tonic-gate /* 72 */ INVALID,
3490Sstevel@tonic-gate /* 73 */ INVALID,
3500Sstevel@tonic-gate /* 74 */ INVALID,
3510Sstevel@tonic-gate /* 75 */ INVALID,
3520Sstevel@tonic-gate /* 76 */ INVALID,
3530Sstevel@tonic-gate /* 77 */ INVALID,
3540Sstevel@tonic-gate /* 78 */ INVALID,
3550Sstevel@tonic-gate /* 79 */ INVALID,
3560Sstevel@tonic-gate /* 7a */ INVALID,
3570Sstevel@tonic-gate /* 7b */ INVALID,
3580Sstevel@tonic-gate /* 7c */ INVALID,
3590Sstevel@tonic-gate /* 7d */ INVALID,
3600Sstevel@tonic-gate /* 7e */ INVALID,
3610Sstevel@tonic-gate };
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate /*
3650Sstevel@tonic-gate * Parse table for the base keyboard state. The index is the start of
3660Sstevel@tonic-gate * a new sequence.
3670Sstevel@tonic-gate *
3680Sstevel@tonic-gate * Questionable or unusual cases:
369822Ssethg * 02 On some SPARC keyboards, this is the scan code for the STOP
370822Ssethg * key. The KEY() value was chosen so that it maps to a
371822Ssethg * HOLE entry in the keytables in kb8042_keytables.c; therefore,
372822Ssethg * the STOP key code is only translated properly when kb8042
373822Ssethg * is "emulating" a USB keyboard (which it is by default--
374822Ssethg * see conskbd.c).
3750Sstevel@tonic-gate * 7f Old kd code says this is an 84-key SysReq. Manual says no.
3760Sstevel@tonic-gate * 87 Old kd code says 1 (num). Manual says no.
3770Sstevel@tonic-gate * 8c Old kd code says / (num). Manual says no.
3780Sstevel@tonic-gate * aa POST OK. Handled by code.
3790Sstevel@tonic-gate * e0 Extend prefix. Handled by code. (switches to E0 table)
3800Sstevel@tonic-gate * e1 Extend prefix. Handled by code. (Pause key only)
3810Sstevel@tonic-gate * f0 Break prefix. Handled by code.
3820Sstevel@tonic-gate * f1 Korean Hangul/Hanja key. Handled by code.
3830Sstevel@tonic-gate * f2 Korean Hangul key. Handled by code.
3840Sstevel@tonic-gate * ff Keyboard internal buffer overrun. Handled by code.
3850Sstevel@tonic-gate *
3860Sstevel@tonic-gate * Other values past the end of the table are treated as INVALID.
3870Sstevel@tonic-gate */
3880Sstevel@tonic-gate
389822Ssethg static const unsigned char keytab_base_set2[] = {
3900Sstevel@tonic-gate /* scan state keycap */
3910Sstevel@tonic-gate /* 00 */ INVALID,
3920Sstevel@tonic-gate /* 01 */ KEY(120), /* F9 */
393822Ssethg #if defined(__sparc)
394822Ssethg /* 02 */ KEY(K8042_STOP), /* STOP */
395822Ssethg #else
3960Sstevel@tonic-gate /* 02 */ INVALID, /* F7? Old code says so but manual doesn't */
397822Ssethg #endif
3980Sstevel@tonic-gate /* 03 */ KEY(116), /* F5 */
3990Sstevel@tonic-gate /* 04 */ KEY(114), /* F3 */
4000Sstevel@tonic-gate /* 05 */ KEY(112), /* F1 */
4010Sstevel@tonic-gate /* 06 */ KEY(113), /* F2 */
4020Sstevel@tonic-gate /* 07 */ KEY(123), /* F12 */
4030Sstevel@tonic-gate /* 08 */ INVALID,
4040Sstevel@tonic-gate /* 09 */ KEY(121), /* F10 */
4050Sstevel@tonic-gate /* 0a */ KEY(119), /* F8 */
4060Sstevel@tonic-gate /* 0b */ KEY(117), /* F6 */
4070Sstevel@tonic-gate /* 0c */ KEY(115), /* F4 */
4080Sstevel@tonic-gate /* 0d */ KEY(16), /* tab */
4090Sstevel@tonic-gate /* 0e */ KEY(1), /* ` */
4100Sstevel@tonic-gate /* 0f */ INVALID,
4110Sstevel@tonic-gate /* 10 */ INVALID,
4120Sstevel@tonic-gate /* 11 */ KEY(60), /* L Alt */
4130Sstevel@tonic-gate /* 12 */ KEY(44), /* L Shift */
4140Sstevel@tonic-gate /* 13 */ KEY(133), /* Japanese 106-key */
4150Sstevel@tonic-gate /* 14 */ KEY(58), /* L Ctrl */
4160Sstevel@tonic-gate /* 15 */ KEY(17), /* Q */
4170Sstevel@tonic-gate /* 16 */ KEY(2), /* 1 */
4180Sstevel@tonic-gate /* 17 */ INVALID,
4190Sstevel@tonic-gate /* 18 */ INVALID,
4200Sstevel@tonic-gate /* 19 */ INVALID,
4210Sstevel@tonic-gate /* 1a */ KEY(46), /* Z */
4220Sstevel@tonic-gate /* 1b */ KEY(32), /* S */
4230Sstevel@tonic-gate /* 1c */ KEY(31), /* A */
4240Sstevel@tonic-gate /* 1d */ KEY(18), /* W */
4250Sstevel@tonic-gate /* 1e */ KEY(3), /* 2 */
4260Sstevel@tonic-gate /* 1f */ INVALID,
4270Sstevel@tonic-gate /* 20 */ INVALID,
4280Sstevel@tonic-gate /* 21 */ KEY(48), /* C */
4290Sstevel@tonic-gate /* 22 */ KEY(47), /* X */
4300Sstevel@tonic-gate /* 23 */ KEY(33), /* D */
4310Sstevel@tonic-gate /* 24 */ KEY(19), /* E */
4320Sstevel@tonic-gate /* 25 */ KEY(5), /* 4 */
4330Sstevel@tonic-gate /* 26 */ KEY(4), /* 3 */
4340Sstevel@tonic-gate /* 27 */ INVALID,
4350Sstevel@tonic-gate /* 28 */ INVALID,
4360Sstevel@tonic-gate /* 29 */ KEY(61), /* Space */
4370Sstevel@tonic-gate /* 2a */ KEY(49), /* V */
4380Sstevel@tonic-gate /* 2b */ KEY(34), /* F */
4390Sstevel@tonic-gate /* 2c */ KEY(21), /* T */
4400Sstevel@tonic-gate /* 2d */ KEY(20), /* R */
4410Sstevel@tonic-gate /* 2e */ KEY(6), /* 5 */
4420Sstevel@tonic-gate /* 2f */ INVALID,
4430Sstevel@tonic-gate /* 30 */ INVALID,
4440Sstevel@tonic-gate /* 31 */ KEY(51), /* N */
4450Sstevel@tonic-gate /* 32 */ KEY(50), /* B */
4460Sstevel@tonic-gate /* 33 */ KEY(36), /* H */
4470Sstevel@tonic-gate /* 34 */ KEY(35), /* G */
4480Sstevel@tonic-gate /* 35 */ KEY(22), /* Y */
4490Sstevel@tonic-gate /* 36 */ KEY(7), /* 6 */
4500Sstevel@tonic-gate /* 37 */ INVALID,
4510Sstevel@tonic-gate /* 38 */ INVALID,
4520Sstevel@tonic-gate /* 39 */ INVALID,
4530Sstevel@tonic-gate /* 3a */ KEY(52), /* M */
4540Sstevel@tonic-gate /* 3b */ KEY(37), /* J */
4550Sstevel@tonic-gate /* 3c */ KEY(23), /* U */
4560Sstevel@tonic-gate /* 3d */ KEY(8), /* 7 */
4570Sstevel@tonic-gate /* 3e */ KEY(9), /* 8 */
4580Sstevel@tonic-gate /* 3f */ INVALID,
4590Sstevel@tonic-gate /* 40 */ INVALID,
4600Sstevel@tonic-gate /* 41 */ KEY(53), /* , */
4610Sstevel@tonic-gate /* 42 */ KEY(38), /* K */
4620Sstevel@tonic-gate /* 43 */ KEY(24), /* I */
4630Sstevel@tonic-gate /* 44 */ KEY(25), /* O */
4640Sstevel@tonic-gate /* 45 */ KEY(11), /* 0 */
4650Sstevel@tonic-gate /* 46 */ KEY(10), /* 9 */
4660Sstevel@tonic-gate /* 47 */ INVALID,
4670Sstevel@tonic-gate /* 48 */ INVALID,
4680Sstevel@tonic-gate /* 49 */ KEY(54), /* . */
4690Sstevel@tonic-gate /* 4a */ KEY(55), /* / */
4700Sstevel@tonic-gate /* 4b */ KEY(39), /* L */
4710Sstevel@tonic-gate /* 4c */ KEY(40), /* ; */
4720Sstevel@tonic-gate /* 4d */ KEY(26), /* P */
4730Sstevel@tonic-gate /* 4e */ KEY(12), /* - */
4740Sstevel@tonic-gate /* 4f */ INVALID,
4750Sstevel@tonic-gate /* 50 */ INVALID,
4760Sstevel@tonic-gate /* 51 */ KEY(56), /* Japanese 106-key */
4770Sstevel@tonic-gate /* 52 */ KEY(41), /* ' */
4780Sstevel@tonic-gate /* 53 */ INVALID,
4790Sstevel@tonic-gate /* 54 */ KEY(27), /* [ */
4800Sstevel@tonic-gate /* 55 */ KEY(13), /* = */
4810Sstevel@tonic-gate /* 56 */ INVALID,
4820Sstevel@tonic-gate /* 57 */ INVALID,
4830Sstevel@tonic-gate /* 58 */ KEY(30), /* CapsLock */
4840Sstevel@tonic-gate /* 59 */ KEY(57), /* R Shift */
4850Sstevel@tonic-gate /* 5a */ KEY(43), /* Enter (main) */
4860Sstevel@tonic-gate /* 5b */ KEY(28), /* ] */
4870Sstevel@tonic-gate /* 5c */ INVALID,
4880Sstevel@tonic-gate /* 5d */ KEY(29), /* \, key 42 for 102-key */
4890Sstevel@tonic-gate /* 5e */ INVALID,
4900Sstevel@tonic-gate /* 5f */ INVALID,
4910Sstevel@tonic-gate /* 60 */ INVALID,
4920Sstevel@tonic-gate /* 61 */ KEY(45), /* 102-key only, typically </> */
4930Sstevel@tonic-gate /* 62 */ INVALID,
4940Sstevel@tonic-gate /* 63 */ INVALID,
4950Sstevel@tonic-gate /* 64 */ KEY(132), /* Japanese 106-key */
4960Sstevel@tonic-gate /* 65 */ INVALID,
4970Sstevel@tonic-gate /* 66 */ KEY(15), /* backspace */
4980Sstevel@tonic-gate /* 67 */ KEY(131), /* Japanese 106-key */
4990Sstevel@tonic-gate /* 68 */ INVALID,
5000Sstevel@tonic-gate /* 69 */ KEY(93), /* 1 (num) */
5010Sstevel@tonic-gate /* 6a */ KEY(14), /* Japanese 106-key */
5020Sstevel@tonic-gate /* 6b */ KEY(92), /* 4 (num) */
5030Sstevel@tonic-gate /* 6c */ KEY(91), /* 7 (num) */
5040Sstevel@tonic-gate /* 6d */ INVALID,
5050Sstevel@tonic-gate /* 6e */ INVALID,
5060Sstevel@tonic-gate /* 6f */ INVALID,
5070Sstevel@tonic-gate /* 70 */ KEY(99), /* 0 (num) */
5080Sstevel@tonic-gate /* 71 */ KEY(104), /* . (num) */
5090Sstevel@tonic-gate /* 72 */ KEY(98), /* 2 (num) */
5100Sstevel@tonic-gate /* 73 */ KEY(97), /* 5 (num) */
5110Sstevel@tonic-gate /* 74 */ KEY(102), /* 6 (num) */
5120Sstevel@tonic-gate /* 75 */ KEY(96), /* 8 (num) */
5130Sstevel@tonic-gate /* 76 */ KEY(110), /* Esc */
5140Sstevel@tonic-gate /* 77 */ KEY(90), /* NumLock */
5150Sstevel@tonic-gate /* 78 */ KEY(122), /* F11 */
5160Sstevel@tonic-gate /* 79 */ KEY(106), /* + (num) */
5170Sstevel@tonic-gate /* 7a */ KEY(103), /* 3 (num) */
5180Sstevel@tonic-gate /* 7b */ KEY(105), /* - (num) */
5190Sstevel@tonic-gate /* 7c */ KEY(100), /* * (num) */
5200Sstevel@tonic-gate /* 7d */ KEY(101), /* 9 (num) */
5210Sstevel@tonic-gate /* 7e */ KEY(125), /* Scroll Lock */
5220Sstevel@tonic-gate /* 7f */ INVALID, /* 84-key SysReq? Manual says no. */
5230Sstevel@tonic-gate /* 80 */ INVALID,
5240Sstevel@tonic-gate /* 81 */ INVALID,
5250Sstevel@tonic-gate /* 82 */ INVALID,
5260Sstevel@tonic-gate /* 83 */ KEY(118), /* F7 */
5270Sstevel@tonic-gate /* 84 */ KEY(124), /* PrintScreen (w/ Alt = SysRq) */
5280Sstevel@tonic-gate };
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate /*
5310Sstevel@tonic-gate * Parse table after receiving an E0 prefix code.
5320Sstevel@tonic-gate *
5330Sstevel@tonic-gate * Generally speaking, keys that were added on the 101-key keyboard are
5340Sstevel@tonic-gate * represented as an E0 followed by the code for an 84-key key. Software
5350Sstevel@tonic-gate * ignorant of the 101-key keyboard ignores the E0 and so is handled
5360Sstevel@tonic-gate * compatibly. Many of these variants involve "fake" shift presses
5370Sstevel@tonic-gate * and releases for compatibility; these are also prefixed with E0.
5380Sstevel@tonic-gate * We ignore these fake shifts.
5390Sstevel@tonic-gate */
540822Ssethg static const unsigned char keytab_e0_set2[] = {
5410Sstevel@tonic-gate /* 00 */ INVALID,
5420Sstevel@tonic-gate /* 01 */ INVALID,
5430Sstevel@tonic-gate /* 02 */ INVALID,
5440Sstevel@tonic-gate /* 03 */ INVALID,
5450Sstevel@tonic-gate /* 04 */ INVALID,
5460Sstevel@tonic-gate /* 05 */ INVALID,
5470Sstevel@tonic-gate /* 06 */ INVALID,
5480Sstevel@tonic-gate /* 07 */ INVALID,
5490Sstevel@tonic-gate /* 08 */ INVALID,
5500Sstevel@tonic-gate /* 09 */ INVALID,
5510Sstevel@tonic-gate /* 0a */ INVALID,
5520Sstevel@tonic-gate /* 0b */ INVALID,
5530Sstevel@tonic-gate /* 0c */ INVALID,
5540Sstevel@tonic-gate /* 0d */ INVALID,
5550Sstevel@tonic-gate /* 0e */ INVALID,
5560Sstevel@tonic-gate /* 0f */ INVALID,
5570Sstevel@tonic-gate /* 10 */ INVALID,
5580Sstevel@tonic-gate /* 11 */ KEY(62), /* R Alt */
5590Sstevel@tonic-gate /* 12 */ IGNORE, /* Fake L Shift */
5600Sstevel@tonic-gate /* 13 */ INVALID,
5610Sstevel@tonic-gate /* 14 */ KEY(64), /* R Ctrl */
5620Sstevel@tonic-gate /* 15 */ INVALID,
5630Sstevel@tonic-gate /* 16 */ INVALID,
5640Sstevel@tonic-gate /* 17 */ INVALID,
5650Sstevel@tonic-gate /* 18 */ INVALID,
5660Sstevel@tonic-gate /* 19 */ INVALID,
5670Sstevel@tonic-gate /* 1a */ INVALID,
5680Sstevel@tonic-gate /* 1b */ INVALID,
5690Sstevel@tonic-gate /* 1c */ INVALID,
5700Sstevel@tonic-gate /* 1d */ INVALID,
5710Sstevel@tonic-gate /* 1e */ INVALID,
5720Sstevel@tonic-gate /* 1f */ KEY(59), /* L Window (104-key) */
5730Sstevel@tonic-gate /* 20 */ INVALID,
5740Sstevel@tonic-gate /* 21 */ INVALID,
5750Sstevel@tonic-gate /* 22 */ INVALID,
5760Sstevel@tonic-gate /* 23 */ INVALID,
5770Sstevel@tonic-gate /* 24 */ INVALID,
5780Sstevel@tonic-gate /* 25 */ INVALID,
5790Sstevel@tonic-gate /* 26 */ INVALID,
5800Sstevel@tonic-gate /* 27 */ KEY(63), /* R Window (104-key) */
5810Sstevel@tonic-gate /* 28 */ INVALID,
5820Sstevel@tonic-gate /* 29 */ INVALID,
5830Sstevel@tonic-gate /* 2a */ INVALID,
5840Sstevel@tonic-gate /* 2b */ INVALID,
5850Sstevel@tonic-gate /* 2c */ INVALID,
5860Sstevel@tonic-gate /* 2d */ INVALID,
5870Sstevel@tonic-gate /* 2e */ INVALID,
5880Sstevel@tonic-gate /* 2f */ KEY(65), /* Menu (104-key) */
5890Sstevel@tonic-gate /* 30 */ INVALID,
5900Sstevel@tonic-gate /* 31 */ INVALID,
5910Sstevel@tonic-gate /* 32 */ INVALID,
5920Sstevel@tonic-gate /* 33 */ INVALID,
5930Sstevel@tonic-gate /* 34 */ INVALID,
5940Sstevel@tonic-gate /* 35 */ INVALID,
5950Sstevel@tonic-gate /* 36 */ INVALID,
5960Sstevel@tonic-gate /* 37 */ INVALID,
5970Sstevel@tonic-gate /* 38 */ INVALID,
5980Sstevel@tonic-gate /* 39 */ INVALID,
5990Sstevel@tonic-gate /* 3a */ INVALID,
6000Sstevel@tonic-gate /* 3b */ INVALID,
6010Sstevel@tonic-gate /* 3c */ INVALID,
6020Sstevel@tonic-gate /* 3d */ INVALID,
6030Sstevel@tonic-gate /* 3e */ INVALID,
6040Sstevel@tonic-gate /* 3f */ INVALID,
6050Sstevel@tonic-gate /* 40 */ INVALID,
6060Sstevel@tonic-gate /* 41 */ INVALID,
6070Sstevel@tonic-gate /* 42 */ INVALID,
6080Sstevel@tonic-gate /* 43 */ INVALID,
6090Sstevel@tonic-gate /* 44 */ INVALID,
6100Sstevel@tonic-gate /* 45 */ INVALID,
6110Sstevel@tonic-gate /* 46 */ INVALID,
6120Sstevel@tonic-gate /* 47 */ INVALID,
6130Sstevel@tonic-gate /* 48 */ INVALID,
6140Sstevel@tonic-gate /* 49 */ INVALID,
6150Sstevel@tonic-gate /* 4a */ KEY(95), /* / (num) */
6160Sstevel@tonic-gate /* 4b */ INVALID,
6170Sstevel@tonic-gate /* 4c */ INVALID,
6180Sstevel@tonic-gate /* 4d */ INVALID,
6190Sstevel@tonic-gate /* 4e */ INVALID,
6200Sstevel@tonic-gate /* 4f */ INVALID,
6210Sstevel@tonic-gate /* 50 */ INVALID,
6220Sstevel@tonic-gate /* 51 */ INVALID,
6230Sstevel@tonic-gate /* 52 */ INVALID,
6240Sstevel@tonic-gate /* 53 */ INVALID,
6250Sstevel@tonic-gate /* 54 */ INVALID,
6260Sstevel@tonic-gate /* 55 */ INVALID,
6270Sstevel@tonic-gate /* 56 */ INVALID,
6280Sstevel@tonic-gate /* 57 */ INVALID,
6290Sstevel@tonic-gate /* 58 */ INVALID,
6300Sstevel@tonic-gate /* 59 */ IGNORE, /* Fake R Shift */
6310Sstevel@tonic-gate /* 5a */ KEY(108), /* Enter (num) */
6320Sstevel@tonic-gate /* 5b */ INVALID,
6330Sstevel@tonic-gate /* 5c */ INVALID,
6340Sstevel@tonic-gate /* 5d */ INVALID,
6350Sstevel@tonic-gate /* 5e */ INVALID,
6360Sstevel@tonic-gate /* 5f */ INVALID,
6370Sstevel@tonic-gate /* 60 */ INVALID,
6380Sstevel@tonic-gate /* 61 */ INVALID,
6390Sstevel@tonic-gate /* 62 */ INVALID,
6400Sstevel@tonic-gate /* 63 */ INVALID,
6410Sstevel@tonic-gate /* 64 */ INVALID,
6420Sstevel@tonic-gate /* 65 */ INVALID,
6430Sstevel@tonic-gate /* 66 */ INVALID,
6440Sstevel@tonic-gate /* 67 */ INVALID,
6450Sstevel@tonic-gate /* 68 */ INVALID,
6460Sstevel@tonic-gate /* 69 */ KEY(81), /* End (arrow) */
6470Sstevel@tonic-gate /* 6a */ INVALID,
6480Sstevel@tonic-gate /* 6b */ KEY(79), /* Left (arrow) */
6490Sstevel@tonic-gate /* 6c */ KEY(80), /* Home (arrow) */
6500Sstevel@tonic-gate /* 6d */ INVALID,
6510Sstevel@tonic-gate /* 6e */ INVALID,
6520Sstevel@tonic-gate /* 6f */ INVALID,
6530Sstevel@tonic-gate /* 70 */ KEY(75), /* Insert (arrow) */
6540Sstevel@tonic-gate /* 71 */ KEY(76), /* Delete (arrow) */
6550Sstevel@tonic-gate /* 72 */ KEY(84), /* Down (arrow) */
6560Sstevel@tonic-gate /* 73 */ INVALID,
6570Sstevel@tonic-gate /* 74 */ KEY(89), /* Right (arrow) */
6580Sstevel@tonic-gate /* 75 */ KEY(83), /* Up (arrow) */
6590Sstevel@tonic-gate /* 76 */ INVALID,
6600Sstevel@tonic-gate /* 77 */ INVALID,
6610Sstevel@tonic-gate /* 78 */ INVALID,
6620Sstevel@tonic-gate /* 79 */ INVALID,
6630Sstevel@tonic-gate /* 7a */ KEY(86), /* PgDn (arrow) */
6640Sstevel@tonic-gate /* 7b */ INVALID,
6650Sstevel@tonic-gate /* 7c */ KEY(124), /* PrintScreen (no Alt) */
6660Sstevel@tonic-gate /* 7d */ KEY(85), /* PgUp (arrow) */
6670Sstevel@tonic-gate /* 7e */ KEY(126), /* Pause (w/Ctrl = Break) */
6680Sstevel@tonic-gate };
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate /*
6720Sstevel@tonic-gate * Initialize the translation state machine.
6730Sstevel@tonic-gate */
674822Ssethg int
KeyboardConvertScan_init(struct kb8042 * kb8042,int scanset)675822Ssethg KeyboardConvertScan_init(struct kb8042 *kb8042, int scanset)
6760Sstevel@tonic-gate {
6770Sstevel@tonic-gate kb8042->parse_scan_state = STATE_IDLE;
678822Ssethg kb8042->break_received = 0;
679822Ssethg
680822Ssethg if (scanset == 1) {
681822Ssethg KeyboardConvertScan_fn = &KeyboardConvertScan_set1;
682822Ssethg keytab_base = keytab_base_set1;
683822Ssethg keytab_base_length = NELEM(keytab_base_set1);
684822Ssethg keytab_e0 = keytab_e0_set1;
685822Ssethg keytab_e0_length = NELEM(keytab_e0_set1);
686822Ssethg } else if (scanset == 2) {
687822Ssethg KeyboardConvertScan_fn = &KeyboardConvertScan_set2;
688822Ssethg keytab_base = keytab_base_set2;
689822Ssethg keytab_base_length = NELEM(keytab_base_set2);
690822Ssethg keytab_e0 = keytab_e0_set2;
691822Ssethg keytab_e0_length = NELEM(keytab_e0_set2);
692822Ssethg } else {
693822Ssethg return (DDI_FAILURE);
694822Ssethg }
695822Ssethg
696822Ssethg return (DDI_SUCCESS);
697822Ssethg }
698822Ssethg
6999026SSeth.Goldberg@Sun.COM /*
7009026SSeth.Goldberg@Sun.COM * KeyboardConvertScan(*kb8042, scan, *keynum, *state
7019026SSeth.Goldberg@Sun.COM * *synthetic_release_needed)
7029026SSeth.Goldberg@Sun.COM *
7039026SSeth.Goldberg@Sun.COM * State machine that takes scan codes from the keyboard and resolves
7049026SSeth.Goldberg@Sun.COM * them to key numbers using the above tables. Returns B_TRUE if this
7059026SSeth.Goldberg@Sun.COM * scan code completes a scan code sequence, in which case "keynum",
7069026SSeth.Goldberg@Sun.COM * "state", and "synthetic_release_needed" will be filled in correctly.
7079026SSeth.Goldberg@Sun.COM *
7089026SSeth.Goldberg@Sun.COM * "synthetic_release_needed" is a hack to handle the additional two
7099026SSeth.Goldberg@Sun.COM * keys on a Korean keyboard. They report press only, so we tell the
7109026SSeth.Goldberg@Sun.COM * upper layer to synthesize the release.
7119026SSeth.Goldberg@Sun.COM */
712822Ssethg boolean_t
KeyboardConvertScan(struct kb8042 * kb8042,unsigned char scan,int * keynum,enum keystate * state,boolean_t * synthetic_release_needed)713822Ssethg KeyboardConvertScan(
714822Ssethg struct kb8042 *kb8042,
715822Ssethg unsigned char scan,
716822Ssethg int *keynum,
717822Ssethg enum keystate *state,
718822Ssethg boolean_t *synthetic_release_needed)
719822Ssethg {
720822Ssethg ASSERT(KeyboardConvertScan_fn != NULL);
721822Ssethg
722822Ssethg return ((*KeyboardConvertScan_fn)(kb8042, scan, keynum, state,
723822Ssethg synthetic_release_needed));
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate boolean_t
KeyboardConvertScan_set1(struct kb8042 * kb8042,unsigned char scan,int * keynum,enum keystate * state,boolean_t * synthetic_release_needed)727822Ssethg KeyboardConvertScan_set1(
7280Sstevel@tonic-gate struct kb8042 *kb8042,
7290Sstevel@tonic-gate unsigned char scan,
7300Sstevel@tonic-gate int *keynum,
7310Sstevel@tonic-gate enum keystate *state,
7320Sstevel@tonic-gate boolean_t *synthetic_release_needed)
7330Sstevel@tonic-gate {
7340Sstevel@tonic-gate *synthetic_release_needed = B_FALSE;
7350Sstevel@tonic-gate *state = KEY_PRESSED;
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate switch (scan) {
7380Sstevel@tonic-gate /*
7390Sstevel@tonic-gate * First, handle special cases.
7400Sstevel@tonic-gate * ACK has already been handled by our caller.
7410Sstevel@tonic-gate */
7420Sstevel@tonic-gate case KB_ERROR:
7430Sstevel@tonic-gate /*
7440Sstevel@tonic-gate * Perhaps we should reset state here,
7450Sstevel@tonic-gate * since we no longer know what's going on.
7460Sstevel@tonic-gate */
7470Sstevel@tonic-gate return (B_FALSE);
7480Sstevel@tonic-gate case KB_POST_FAIL:
7490Sstevel@tonic-gate /*
7500Sstevel@tonic-gate * Perhaps we should reset the LEDs now.
7510Sstevel@tonic-gate * If so, this check should probably be in the main line.
7520Sstevel@tonic-gate * Perhaps we should tell the higher layers that the
7530Sstevel@tonic-gate * keyboard has been reset.
7540Sstevel@tonic-gate */
7550Sstevel@tonic-gate /*
7560Sstevel@tonic-gate * Reset to idle
7570Sstevel@tonic-gate */
7580Sstevel@tonic-gate kb8042->parse_scan_state = STATE_IDLE;
7590Sstevel@tonic-gate return (B_FALSE);
7600Sstevel@tonic-gate
7610Sstevel@tonic-gate case KXT_EXTEND:
7620Sstevel@tonic-gate case KXT_EXTEND2:
7630Sstevel@tonic-gate case KXT_HANGUL_HANJA:
7640Sstevel@tonic-gate case KXT_HANGUL:
7650Sstevel@tonic-gate /*
7660Sstevel@tonic-gate * Exclude these keys from the "default" test below.
7670Sstevel@tonic-gate */
7680Sstevel@tonic-gate break;
7690Sstevel@tonic-gate
7700Sstevel@tonic-gate default:
7710Sstevel@tonic-gate /*
7720Sstevel@tonic-gate * See if it was a key release.
7730Sstevel@tonic-gate */
7740Sstevel@tonic-gate if (scan > 0x80) {
7750Sstevel@tonic-gate *state = KEY_RELEASED;
7760Sstevel@tonic-gate scan -= 0x80;
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate break;
7790Sstevel@tonic-gate }
7800Sstevel@tonic-gate
781822Ssethg if (kb8042->break_received) {
782822Ssethg *state = KEY_RELEASED;
783822Ssethg kb8042->break_received = 0;
784822Ssethg }
785822Ssethg
7860Sstevel@tonic-gate switch (kb8042->parse_scan_state) {
7870Sstevel@tonic-gate case STATE_IDLE:
7880Sstevel@tonic-gate switch (scan) {
7890Sstevel@tonic-gate case KXT_EXTEND:
7900Sstevel@tonic-gate kb8042->parse_scan_state = STATE_E0;
7910Sstevel@tonic-gate return (B_FALSE);
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate case KXT_EXTEND2:
7940Sstevel@tonic-gate kb8042->parse_scan_state = STATE_E1;
7950Sstevel@tonic-gate return (B_FALSE);
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate /*
7980Sstevel@tonic-gate * We could do the next two in the table, but it would
7990Sstevel@tonic-gate * require nearly doubling the size of the table.
8000Sstevel@tonic-gate *
8010Sstevel@tonic-gate * Also, for some stupid reason these two report presses
8020Sstevel@tonic-gate * only. We tell the upper layer to synthesize a release.
8030Sstevel@tonic-gate */
8040Sstevel@tonic-gate case KXT_HANGUL_HANJA:
8050Sstevel@tonic-gate *keynum = KEY(150);
8060Sstevel@tonic-gate *synthetic_release_needed = B_TRUE;
8070Sstevel@tonic-gate break;
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate case KXT_HANGUL:
8100Sstevel@tonic-gate *keynum = KEY(151);
8110Sstevel@tonic-gate *synthetic_release_needed = B_TRUE;
8120Sstevel@tonic-gate break;
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate default:
8150Sstevel@tonic-gate /*
8160Sstevel@tonic-gate * Regular scan code
8170Sstevel@tonic-gate */
818822Ssethg if (scan < keytab_base_length)
8190Sstevel@tonic-gate *keynum = keytab_base[scan];
8200Sstevel@tonic-gate else
8210Sstevel@tonic-gate *keynum = INVALID;
8220Sstevel@tonic-gate break;
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate break;
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate case STATE_E0: /* Mostly 101-key additions */
827822Ssethg if (scan < keytab_e0_length)
8280Sstevel@tonic-gate *keynum = keytab_e0[scan];
8290Sstevel@tonic-gate else
8300Sstevel@tonic-gate *keynum = INVALID;
8310Sstevel@tonic-gate break;
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate case STATE_E1: /* Pause key only */
8340Sstevel@tonic-gate switch (scan) {
8350Sstevel@tonic-gate case 0x1d:
8360Sstevel@tonic-gate kb8042->parse_scan_state = STATE_E1_1D;
8370Sstevel@tonic-gate return (B_FALSE);
8380Sstevel@tonic-gate default:
8390Sstevel@tonic-gate *keynum = INVALID;
8400Sstevel@tonic-gate break;
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate break;
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate case STATE_E1_1D: /* Pause key only */
8450Sstevel@tonic-gate switch (scan) {
8460Sstevel@tonic-gate case 0x45:
8470Sstevel@tonic-gate *keynum = KEY(126); /* Pause */
8480Sstevel@tonic-gate break;
8490Sstevel@tonic-gate default:
8500Sstevel@tonic-gate *keynum = INVALID;
8510Sstevel@tonic-gate break;
8520Sstevel@tonic-gate }
8530Sstevel@tonic-gate break;
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate
8560Sstevel@tonic-gate /*
8570Sstevel@tonic-gate * The results (*keynum, *state, and *synthetic_release_needed)
8580Sstevel@tonic-gate * have been filled in, but they are valid only if we return
8590Sstevel@tonic-gate * B_TRUE which is only done below. If we make it to here, we
8600Sstevel@tonic-gate * have completed a scan code sequence, so reset parse_scan_state.
8610Sstevel@tonic-gate */
8620Sstevel@tonic-gate
8630Sstevel@tonic-gate kb8042->parse_scan_state = STATE_IDLE;
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate switch (*keynum) {
8660Sstevel@tonic-gate case KEYIGN: /* not a key, nor an error */
8670Sstevel@tonic-gate return (B_FALSE); /* also not a final keycode */
8680Sstevel@tonic-gate
8690Sstevel@tonic-gate case KEYBAD: /* not part of a legit sequence? */
8700Sstevel@tonic-gate return (B_FALSE); /* and return not a final keycode */
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate default:
8730Sstevel@tonic-gate /*
8740Sstevel@tonic-gate * If we're here, it's a valid keycode. We've already
8750Sstevel@tonic-gate * filled in the return values; return success.
8760Sstevel@tonic-gate */
8770Sstevel@tonic-gate return (B_TRUE); /* resolved to a key */
8780Sstevel@tonic-gate }
8790Sstevel@tonic-gate }
880822Ssethg
881822Ssethg /*
882822Ssethg * KeyboardConvertScan(*kb8042, scan, *keynum, *state
883822Ssethg * *synthetic_release_needed)
884822Ssethg *
885822Ssethg * State machine that takes scan codes from the keyboard and resolves
886822Ssethg * them to key numbers using the above tables. Returns B_TRUE if this
887822Ssethg * scan code completes a scan code sequence, in which case "keynum",
888822Ssethg * "state", and "synthetic_release_needed" will be filled in correctly.
889822Ssethg *
890822Ssethg * "synthetic_release_needed" is a hack to handle the additional two
891822Ssethg * keys on a Korean keyboard. They report press only, so we tell the
892822Ssethg * upper layer to synthesize the release.
893822Ssethg */
894822Ssethg boolean_t
KeyboardConvertScan_set2(struct kb8042 * kb8042,unsigned char scan,int * keynum,enum keystate * state,boolean_t * synthetic_release_needed)895822Ssethg KeyboardConvertScan_set2(
896822Ssethg struct kb8042 *kb8042,
897822Ssethg unsigned char scan,
898822Ssethg int *keynum,
899822Ssethg enum keystate *state,
900822Ssethg boolean_t *synthetic_release_needed)
901822Ssethg {
902822Ssethg *synthetic_release_needed = B_FALSE;
903822Ssethg *state = KEY_PRESSED;
904822Ssethg
905822Ssethg switch (scan) {
906822Ssethg /*
907822Ssethg * First, handle special cases.
908822Ssethg * ACK has already been handled by our caller.
909822Ssethg */
910822Ssethg
911822Ssethg /*
912822Ssethg * KAT_BREAK is 0xF0. It is the same as the break code for Japanese
913822Ssethg * key 133.
914822Ssethg * Therefore we don't treat it specially here.
915822Ssethg */
916822Ssethg case KAT_BREAK:
917822Ssethg /* Switch states so we can recognize the code that follows */
918822Ssethg kb8042->break_received = 1;
919822Ssethg return (B_FALSE); /* not a final keycode */
920822Ssethg
921822Ssethg case KB_ERROR:
922822Ssethg /*
923822Ssethg * Perhaps we should reset state here,
924822Ssethg * since we no longer know what's going on.
925822Ssethg */
926822Ssethg return (B_FALSE);
927822Ssethg
928822Ssethg case KB_POST_OK:
929822Ssethg case KB_POST_FAIL:
930822Ssethg /*
931822Ssethg * Perhaps we should reset the LEDs now.
932822Ssethg * If so, this check should probably be in the main line.
933822Ssethg * Perhaps we should tell the higher layers that the
934822Ssethg * keyboard has been reset.
935822Ssethg */
936822Ssethg /*
937822Ssethg * Reset to idle
938822Ssethg */
939822Ssethg kb8042->parse_scan_state = STATE_IDLE;
940822Ssethg return (B_FALSE);
941822Ssethg }
942822Ssethg
943822Ssethg if (kb8042->break_received) {
944822Ssethg *state = KEY_RELEASED;
945822Ssethg kb8042->break_received = 0;
946822Ssethg }
947822Ssethg
948822Ssethg switch (kb8042->parse_scan_state) {
949822Ssethg case STATE_IDLE:
950822Ssethg switch (scan) {
951822Ssethg case KXT_EXTEND:
952822Ssethg kb8042->parse_scan_state = STATE_E0;
953822Ssethg return (B_FALSE);
954822Ssethg
955822Ssethg case KXT_EXTEND2:
956822Ssethg kb8042->parse_scan_state = STATE_E1;
957822Ssethg return (B_FALSE);
958822Ssethg
959822Ssethg /*
960822Ssethg * We could do the next two in the table, but it would
961822Ssethg * require nearly doubling the size of the table.
962822Ssethg *
963822Ssethg * Also, for some stupid reason these two report presses
964822Ssethg * only. We tell the upper layer to synthesize a release.
965822Ssethg */
966822Ssethg case KXT_HANGUL_HANJA:
967822Ssethg *keynum = KEY(150);
968822Ssethg *synthetic_release_needed = B_TRUE;
969822Ssethg break;
970822Ssethg
971822Ssethg case KXT_HANGUL:
972822Ssethg *keynum = KEY(151);
973822Ssethg *synthetic_release_needed = B_TRUE;
974822Ssethg break;
975822Ssethg
976822Ssethg default:
977822Ssethg /*
978822Ssethg * Regular scan code
979822Ssethg */
980822Ssethg if (scan < keytab_base_length)
981822Ssethg *keynum = keytab_base[scan];
982822Ssethg else
983822Ssethg *keynum = INVALID;
984822Ssethg break;
985822Ssethg }
986822Ssethg break;
987822Ssethg
988822Ssethg case STATE_E0: /* Mostly 101-key additions */
989822Ssethg if (scan < keytab_e0_length)
990822Ssethg *keynum = keytab_e0[scan];
991822Ssethg else
992822Ssethg *keynum = INVALID;
993822Ssethg break;
994822Ssethg
995822Ssethg case STATE_E1: /* Pause key only */
996822Ssethg switch (scan) {
997822Ssethg case 0x14:
998822Ssethg kb8042->parse_scan_state = STATE_E1_14;
999822Ssethg return (B_FALSE);
1000822Ssethg default:
1001822Ssethg *keynum = INVALID;
1002822Ssethg break;
1003822Ssethg }
1004822Ssethg break;
1005822Ssethg
1006822Ssethg case STATE_E1_14: /* Pause key only */
1007822Ssethg if (scan == 0x77) {
1008822Ssethg kb8042->parse_scan_state = STATE_E1_14_77;
1009822Ssethg return (B_FALSE);
1010822Ssethg } else {
1011822Ssethg *keynum = INVALID;
1012822Ssethg }
1013822Ssethg break;
1014822Ssethg
1015822Ssethg case STATE_E1_14_77:
1016822Ssethg if (scan == 0xE1) {
1017822Ssethg kb8042->parse_scan_state = STATE_E1_14_77_E1;
1018822Ssethg return (B_FALSE);
1019822Ssethg } else {
1020822Ssethg *keynum = INVALID;
1021822Ssethg }
1022822Ssethg break;
1023822Ssethg
1024822Ssethg case STATE_E1_14_77_E1:
1025822Ssethg if (scan == 0xF0) {
1026822Ssethg kb8042->parse_scan_state = STATE_E1_14_77_E1_F0;
1027822Ssethg return (B_FALSE);
1028822Ssethg } else {
1029822Ssethg *keynum = INVALID;
1030822Ssethg }
1031822Ssethg break;
1032822Ssethg
1033822Ssethg case STATE_E1_14_77_E1_F0:
1034822Ssethg if (scan == 0x14) {
1035822Ssethg kb8042->parse_scan_state = STATE_E1_14_77_E1_F0_14;
1036822Ssethg return (B_FALSE);
1037822Ssethg } else {
1038822Ssethg *keynum = INVALID;
1039822Ssethg }
1040822Ssethg break;
1041822Ssethg
1042822Ssethg case STATE_E1_14_77_E1_F0_14:
1043822Ssethg if (scan == 0xF0) {
1044822Ssethg kb8042->parse_scan_state = STATE_E1_14_77_E1_F0_14_F0;
1045822Ssethg return (B_FALSE);
1046822Ssethg } else {
1047822Ssethg *keynum = INVALID;
1048822Ssethg }
1049822Ssethg break;
1050822Ssethg
1051822Ssethg case STATE_E1_14_77_E1_F0_14_F0:
1052822Ssethg if (scan == 0x77) {
1053822Ssethg *keynum = KEY(126); /* Pause */
1054822Ssethg } else {
1055822Ssethg *keynum = INVALID;
1056822Ssethg }
1057822Ssethg break;
1058822Ssethg }
1059822Ssethg
1060822Ssethg /*
1061822Ssethg * The results (*keynum, *state, and *synthetic_release_needed)
1062822Ssethg * have been filled in, but they are valid only if we return
1063822Ssethg * B_TRUE which is only done below. If we make it to here, we
1064822Ssethg * have completed a scan code sequence, so reset parse_scan_state.
1065822Ssethg */
1066822Ssethg
1067822Ssethg if (kb8042->break_received) {
1068822Ssethg *state = KEY_RELEASED;
1069822Ssethg kb8042->break_received = 0;
1070822Ssethg }
1071822Ssethg
1072822Ssethg kb8042->parse_scan_state = STATE_IDLE;
1073822Ssethg
1074822Ssethg switch (*keynum) {
1075822Ssethg case KEYIGN: /* not a key, nor an error */
1076822Ssethg return (B_FALSE); /* also not a final keycode */
1077822Ssethg
1078822Ssethg case KEYBAD: /* not part of a legit sequence? */
1079822Ssethg return (B_FALSE); /* and return not a final keycode */
1080822Ssethg
1081822Ssethg default:
1082822Ssethg /*
1083822Ssethg * If we're here, it's a valid keycode. We've already
1084822Ssethg * filled in the return values; return success.
1085822Ssethg */
1086822Ssethg return (B_TRUE); /* resolved to a key */
1087822Ssethg }
1088822Ssethg }
1089