/*
* 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
* 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 "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 NELEM(a) (sizeof (a) / sizeof (a)[0])
/*
* These are the states of our parsing machine:
*/
static int keytab_base_length = 0;
static int keytab_e0_length = 0;
static const unsigned char keytab_base_set1[] = {
/* scan key number keycap */
/* 00 */ INVALID,
/* 55 */ INVALID,
/* 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,
/* 71 */ INVALID,
/* 72 */ INVALID,
/* 74 */ INVALID,
/* 75 */ INVALID,
/* 76 */ INVALID,
/* 77 */ INVALID,
/* 78 */ INVALID,
/* 7a */ INVALID,
/* 7c */ INVALID,
/* 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,
/* 1e */ INVALID,
/* 1f */ INVALID,
/* 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,
/* 2f */ INVALID,
/* 31 */ INVALID,
/* 32 */ INVALID,
/* 33 */ INVALID,
/* 34 */ INVALID,
/* 36 */ 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,
/* 4a */ INVALID,
/* 4c */ INVALID,
/* 4e */ INVALID,
/* 54 */ INVALID,
/* 55 */ INVALID,
/* 56 */ INVALID,
/* 57 */ INVALID,
/* 58 */ INVALID,
/* 59 */ INVALID,
/* 5a */ 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 */ 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.
* 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,
#if defined(__sparc)
#else
#endif
/* 08 */ INVALID,
/* 0f */ INVALID,
/* 10 */ INVALID,
/* 17 */ INVALID,
/* 18 */ INVALID,
/* 19 */ INVALID,
/* 1f */ INVALID,
/* 20 */ INVALID,
/* 27 */ INVALID,
/* 28 */ INVALID,
/* 2f */ INVALID,
/* 30 */ INVALID,
/* 37 */ INVALID,
/* 38 */ INVALID,
/* 39 */ INVALID,
/* 3f */ INVALID,
/* 40 */ INVALID,
/* 47 */ INVALID,
/* 48 */ INVALID,
/* 4f */ INVALID,
/* 50 */ INVALID,
/* 53 */ INVALID,
/* 56 */ INVALID,
/* 57 */ INVALID,
/* 5c */ INVALID,
/* 5e */ INVALID,
/* 5f */ INVALID,
/* 60 */ INVALID,
/* 62 */ INVALID,
/* 63 */ INVALID,
/* 65 */ INVALID,
/* 68 */ INVALID,
/* 6d */ INVALID,
/* 6e */ INVALID,
/* 6f */ INVALID,
/* 80 */ INVALID,
/* 81 */ INVALID,
/* 82 */ 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_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,
/* 13 */ INVALID,
/* 15 */ INVALID,
/* 16 */ INVALID,
/* 17 */ INVALID,
/* 18 */ INVALID,
/* 19 */ INVALID,
/* 1a */ INVALID,
/* 1b */ INVALID,
/* 1c */ INVALID,
/* 1d */ INVALID,
/* 1e */ INVALID,
/* 20 */ INVALID,
/* 21 */ INVALID,
/* 22 */ INVALID,
/* 23 */ INVALID,
/* 24 */ INVALID,
/* 25 */ INVALID,
/* 26 */ INVALID,
/* 28 */ INVALID,
/* 29 */ INVALID,
/* 2a */ INVALID,
/* 2b */ INVALID,
/* 2c */ INVALID,
/* 2d */ INVALID,
/* 2e */ INVALID,
/* 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,
/* 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,
/* 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,
/* 6a */ INVALID,
/* 6d */ INVALID,
/* 6e */ INVALID,
/* 6f */ INVALID,
/* 73 */ INVALID,
/* 76 */ INVALID,
/* 77 */ INVALID,
/* 78 */ INVALID,
/* 79 */ INVALID,
/* 7b */ INVALID,
};
/*
* Initialize the translation state machine.
*/
int
{
kb8042->break_received = 0;
if (scanset == 1) {
} else if (scanset == 2) {
} 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.
*/
unsigned char scan,
int *keynum,
{
}
unsigned char scan,
int *keynum,
{
*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
*/
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:
return (B_FALSE);
case KXT_EXTEND2:
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:
break;
case KXT_HANGUL:
break;
default:
/*
* Regular scan code
*/
if (scan < keytab_base_length)
else
break;
}
break;
case STATE_E0: /* Mostly 101-key additions */
if (scan < keytab_e0_length)
else
break;
case STATE_E1: /* Pause key only */
switch (scan) {
case 0x1d:
return (B_FALSE);
default:
break;
}
break;
case STATE_E1_1D: /* Pause key only */
switch (scan) {
case 0x45:
break;
default:
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.
*/
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.
*/
unsigned char scan,
int *keynum,
{
*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 */
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
*/
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:
return (B_FALSE);
case KXT_EXTEND2:
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:
break;
case KXT_HANGUL:
break;
default:
/*
* Regular scan code
*/
if (scan < keytab_base_length)
else
break;
}
break;
case STATE_E0: /* Mostly 101-key additions */
if (scan < keytab_e0_length)
else
break;
case STATE_E1: /* Pause key only */
switch (scan) {
case 0x14:
return (B_FALSE);
default:
break;
}
break;
case STATE_E1_14: /* Pause key only */
if (scan == 0x77) {
return (B_FALSE);
} else {
}
break;
case STATE_E1_14_77:
if (scan == 0xE1) {
return (B_FALSE);
} else {
}
break;
case STATE_E1_14_77_E1:
if (scan == 0xF0) {
return (B_FALSE);
} else {
}
break;
case STATE_E1_14_77_E1_F0:
if (scan == 0x14) {
return (B_FALSE);
} else {
}
break;
case STATE_E1_14_77_E1_F0_14:
if (scan == 0xF0) {
return (B_FALSE);
} else {
}
break;
if (scan == 0x77) {
} else {
}
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;
}
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 */
}
}