reactos/ntoskrnl/kdbg/kdb_keyboard.c
Art Yerkes c501d8112c Create a branch for network fixes.
svn path=/branches/aicom-network-fixes/; revision=34994
2008-08-01 11:32:26 +00:00

352 lines
10 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/dbg/kdb_keyboard.c
* PURPOSE: Keyboard driver
*
* PROGRAMMERS: Victor Kirhenshtein (sauros@iname.com)
* Jason Filby (jasonfilby@yahoo.com)
*/
/* INCLUDES ****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#if 1
#define KBD_STATUS_REG 0x64
#define KBD_CNTL_REG 0x64
#define KBD_DATA_REG 0x60
#define KBD_DISABLE_MOUSE 0xA7
#define KBD_ENABLE_MOUSE 0xA8
#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
#define kbd_write_command(cmd) WRITE_PORT_UCHAR((PUCHAR)KBD_STATUS_REG,cmd)
#define kbd_read_input() READ_PORT_UCHAR((PUCHAR)KBD_DATA_REG)
#define kbd_read_status() READ_PORT_UCHAR((PUCHAR)KBD_STATUS_REG)
static unsigned char keyb_layout[2][128] =
{
"\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
"qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
"dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
"bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
"\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
"\r\000/" /* 0x60 - 0x6f */
,
"\000\033!@#$%^&*()_+\177\t" /* 0x00 - 0x0f */
"QWERTYUIOP{}\r\000AS" /* 0x10 - 0x1f */
"DFGHJKL:\"`\000\\ZXCV" /* 0x20 - 0x2f */
"BNM<>?\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
"\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
"\r\000/" /* 0x60 - 0x6f */
};
typedef UCHAR byte_t;
VOID KbdEnableMouse()
{
kbd_write_command(KBD_ENABLE_MOUSE);
}
VOID KbdDisableMouse()
{
kbd_write_command(KBD_DISABLE_MOUSE);
}
CHAR
KdbpTryGetCharKeyboard(PULONG ScanCode, ULONG Retry)
{
static byte_t last_key = 0;
static byte_t shift = 0;
char c;
BOOLEAN KeepRetrying = (Retry == 0);
while (KeepRetrying || Retry-- > 0) {
unsigned char status = kbd_read_status();
while (status & KBD_STAT_OBF) {
byte_t scancode;
scancode = kbd_read_input();
/* check for SHIFT-keys */
if (((scancode & 0x7F) == 42) || ((scancode & 0x7F) == 54))
{
shift = !(scancode & 0x80);
continue;
}
/* ignore all other RELEASED-codes */
if (scancode & 0x80)
last_key = 0;
else if (last_key != scancode)
{
//printf("kbd: %d, %d, %c\n", scancode, last_key, keyb_layout[shift][scancode]);
last_key = scancode;
c = keyb_layout[shift][scancode];
*ScanCode = scancode;
if (c > 0) return c;
}
}
}
return -1;
}
#endif
#if 0
/* GLOBALS *******************************************************************/
/*
* Keyboard I/O ports.
*/
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
#define K_STATUS 0x64 /* keybd status (read-only) */
#define K_CMD 0x64 /* keybd ctlr command (write-only) */
/*
* Bit definitions for K_STATUS port.
*/
#define K_OBUF_FUL 0x01 /* output (from keybd) buffer full */
#define K_IBUF_FUL 0x02 /* input (to keybd) buffer full */
#define K_SYSFLAG 0x04 /* "System Flag" */
#define K_CMD_DATA 0x08 /* 1 = input buf has cmd, 0 = data */
#define K_KBD_INHIBIT 0x10 /* 0 if keyboard inhibited */
#define K_AUX_OBUF_FUL 0x20 /* 1 = obuf holds aux device data */
#define K_TIMEOUT 0x40 /* timout error flag */
#define K_PARITY_ERROR 0x80 /* parity error flag */
/*
* Keyboard controller commands (sent to K_CMD port).
*/
#define KC_CMD_READ 0x20 /* read controller command byte */
#define KC_CMD_WRITE 0x60 /* write controller command byte */
#define KC_CMD_DIS_AUX 0xa7 /* disable auxiliary device */
#define KC_CMD_ENB_AUX 0xa8 /* enable auxiliary device */
#define KC_CMD_TEST_AUX 0xa9 /* test auxiliary device interface */
#define KC_CMD_SELFTEST 0xaa /* keyboard controller self-test */
#define KC_CMD_TEST 0xab /* test keyboard interface */
#define KC_CMD_DUMP 0xac /* diagnostic dump */
#define KC_CMD_DISABLE 0xad /* disable keyboard */
#define KC_CMD_ENABLE 0xae /* enable keyboard */
#define KC_CMD_RDKBD 0xc4 /* read keyboard ID */
#define KC_CMD_WIN 0xd0 /* read output port */
#define KC_CMD_WOUT 0xd1 /* write output port */
#define KC_CMD_ECHO 0xee /* used for diagnostic testing */
#define KC_CMD_PULSE 0xff /* pulse bits 3-0 based on low nybble */
/*
* Keyboard commands (send to K_RDWR).
*/
#define K_CMD_LEDS 0xed /* set status LEDs (caps lock, etc.) */
#define K_CMD_TYPEMATIC 0xf3 /* set key repeat and delay */
/*
* Bit definitions for controller command byte (sent following
* KC_CMD_WRITE command).
*
* Bits 0x02 and 0x80 unused, always set to 0.
*/
#define K_CB_ENBLIRQ 0x01 /* enable data-ready intrpt */
#define K_CB_SETSYSF 0x04 /* Set System Flag */
#define K_CB_INHBOVR 0x08 /* Inhibit Override */
#define K_CB_DISBLE 0x10 /* disable keyboard */
#define K_CB_IGNPARITY 0x20 /* ignore parity from keyboard */
#define K_CB_SCAN 0x40 /* standard scan conversion */
/*
* Bit definitions for "Indicator Status Byte" (sent after a
* K_CMD_LEDS command). If the bit is on, the LED is on. Undefined
* bit positions must be 0.
*/
#define K_LED_SCRLLK 0x1 /* scroll lock */
#define K_LED_NUMLK 0x2 /* num lock */
#define K_LED_CAPSLK 0x4 /* caps lock */
/*
* Bit definitions for "Miscellaneous port B" (K_PORTB).
*/
/* read/write */
#define K_ENABLETMR2 0x01 /* enable output from timer 2 */
#define K_SPKRDATA 0x02 /* direct input to speaker */
#define K_ENABLEPRTB 0x04 /* "enable" port B */
#define K_EIOPRTB 0x08 /* enable NMI on parity error */
/* read-only */
#define K_REFRESHB 0x10 /* refresh flag from INLTCONT PAL */
#define K_OUT2B 0x20 /* timer 2 output */
#define K_ICKB 0x40 /* I/O channel check (parity error) */
/*
* Bit definitions for the keyboard controller's output port.
*/
#define KO_SYSRESET 0x01 /* processor reset */
#define KO_GATE20 0x02 /* A20 address line enable */
#define KO_AUX_DATA_OUT 0x04 /* output data to auxiliary device */
#define KO_AUX_CLOCK 0x08 /* auxiliary device clock */
#define KO_OBUF_FUL 0x10 /* keyboard output buffer full */
#define KO_AUX_OBUF_FUL 0x20 /* aux device output buffer full */
#define KO_CLOCK 0x40 /* keyboard clock */
#define KO_DATA_OUT 0x80 /* output data to keyboard */
/*
* Keyboard return codes.
*/
#define K_RET_RESET_DONE 0xaa /* BAT complete */
#define K_RET_ECHO 0xee /* echo after echo command */
#define K_RET_ACK 0xfa /* ack */
#define K_RET_RESET_FAIL 0xfc /* BAT error */
#define K_RET_RESEND 0xfe /* resend request */
#define SHIFT -1
#define CTRL -2
#define META -3
static char keymap[128][2] = {
{0}, /* 0 */
{27, 27}, /* 1 - ESC */
{'1', '!'}, /* 2 */
{'2', '@'},
{'3', '#'},
{'4', '$'},
{'5', '%'},
{'6', '^'},
{'7', '&'},
{'8', '*'},
{'9', '('},
{'0', ')'},
{'-', '_'},
{'=', '+'},
{8, 8}, /* 14 - Backspace */
{'\t', '\t'}, /* 15 */
{'q', 'Q'},
{'w', 'W'},
{'e', 'E'},
{'r', 'R'},
{'t', 'T'},
{'y', 'Y'},
{'u', 'U'},
{'i', 'I'},
{'o', 'O'},
{'p', 'P'},
{'[', '{'},
{']', '}'}, /* 27 */
{'\r', '\r'}, /* 28 - Enter */
{CTRL, CTRL}, /* 29 - Ctrl */
{'a', 'A'}, /* 30 */
{'s', 'S'},
{'d', 'D'},
{'f', 'F'},
{'g', 'G'},
{'h', 'H'},
{'j', 'J'},
{'k', 'K'},
{'l', 'L'},
{';', ':'},
{'\'', '"'}, /* 40 */
{'`', '~'}, /* 41 */
{SHIFT, SHIFT}, /* 42 - Left Shift */
{'\\', '|'}, /* 43 */
{'z', 'Z'}, /* 44 */
{'x', 'X'},
{'c', 'C'},
{'v', 'V'},
{'b', 'B'},
{'n', 'N'},
{'m', 'M'},
{',', '<'},
{'.', '>'},
{'/', '?'}, /* 53 */
{SHIFT, SHIFT}, /* 54 - Right Shift */
{0, 0}, /* 55 - Print Screen */
{META, META}, /* 56 - Alt */
{' ', ' '}, /* 57 - Space bar */
{0, 0}, /* 58 - Caps Lock */
{0, 0}, /* 59 - F1 */
{0, 0}, /* 60 - F2 */
{0, 0}, /* 61 - F3 */
{0, 0}, /* 62 - F4 */
{0, 0}, /* 63 - F5 */
{0, 0}, /* 64 - F6 */
{0, 0}, /* 65 - F7 */
{0, 0}, /* 66 - F8 */
{0, 0}, /* 67 - F9 */
{0, 0}, /* 68 - F10 */
{0, 0}, /* 69 - Num Lock */
{0, 0}, /* 70 - Scroll Lock */
{'7', '7'}, /* 71 - Numeric keypad 7 */
{'8', '8'}, /* 72 - Numeric keypad 8 */
{'9', '9'}, /* 73 - Numeric keypad 9 */
{'-', '-'}, /* 74 - Numeric keypad '-' */
{'4', '4'}, /* 75 - Numeric keypad 4 */
{'5', '5'}, /* 76 - Numeric keypad 5 */
{'6', '6'}, /* 77 - Numeric keypad 6 */
{'+', '+'}, /* 78 - Numeric keypad '+' */
{'1', '1'}, /* 79 - Numeric keypad 1 */
{'2', '2'}, /* 80 - Numeric keypad 2 */
{'3', '3'}, /* 81 - Numeric keypad 3 */
{'0', '0'}, /* 82 - Numeric keypad 0 */
{'.', '.'}, /* 83 - Numeric keypad '.' */
};
/* FUNCTIONS *****************************************************************/
/*
* Quick poll for a pending input character.
* Returns a character if available, -1 otherwise. This routine can return
* false negatives in the following cases:
*
* - a valid character is in transit from the keyboard when called
* - a key release is received (from a previous key press)
* - a SHIFT key press is received (shift state is recorded however)
* - a key press for a multi-character sequence is received
*
* Yes, this is horrible.
*/
ULONG
KdbpTryGetCharKeyboard(VOID)
{
static unsigned shift_state, ctrl_state, meta_state;
unsigned scan_code, ch;
/* See if a scan code is ready, returning if none. */
if ((READ_PORT_UCHAR((PUCHAR)K_STATUS) & K_OBUF_FUL) == 0) {
return -1;
}
scan_code = READ_PORT_UCHAR((PUCHAR)K_RDWR);
/* Handle key releases - only release of SHIFT is important. */
if (scan_code & 0x80) {
scan_code &= 0x7f;
if (keymap[scan_code][0] == SHIFT)
shift_state = 0;
else if (keymap[scan_code][0] == CTRL)
ctrl_state = 0;
else if (keymap[scan_code][0] == META)
meta_state = 0;
ch = -1;
} else {
/* Translate the character through the keymap. */
ch = keymap[scan_code][shift_state] | meta_state;
if (ch == SHIFT) {
shift_state = 1;
ch = -1;
} else if (ch == CTRL) {
ctrl_state = 1;
ch = -1;
} else if (ch == META) {
meta_state = 0200;
ch = -1;
} else if (ch == 0)
ch = -1;
else if (ctrl_state)
ch = (keymap[scan_code][1] - '@') | meta_state;
}
return ch;
}
#endif