#include "type.h"
#include "const.h"
#include "protect.h"
#include "console.h"
#include "tty.h"
#include "proc.h"
#include "proto.h"
#include "string.h"
#include "global.h"
#include "keyboard.h"
#include "keymap.h"
PRIVATE KB_INPUT kb_in;
PRIVATE int code_with_E0;
PRIVATE int shift_l; /* l shift state */
PRIVATE int shift_r; /* r shift state */
PRIVATE int alt_l; /* l alt state */
PRIVATE int alt_r; /* r alt state */
PRIVATE int ctrl_l; /* l ctrl state */
PRIVATE int ctrl_r; /* r ctrl state */
PRIVATE int caps_lock; /* Caps Lock */
PRIVATE int num_lock; /* Num Lock */
PRIVATE int scroll_lock; /* Scroll Lock */
PRIVATE int column;
PRIVATE int caps_lock; /* Caps Lock */
PRIVATE int num_lock; /* Num Lock */
PRIVATE int scroll_lock; /* Scroll Lock */
PRIVATE u8 get_byte_from_kbuf();
PRIVATE void kb_wait();
PRIVATE void kb_ack();
PRIVATE void set_leds();
PUBLIC void keyboard_handler(int irq)
{
u8 scan_code = in_byte(KB_DATA);
if (kb_in.count < KB_IN_BYTES) {
*(kb_in.p_head) = scan_code;
kb_in.p_head++;
if (kb_in.p_head == kb_in.buf + KB_IN_BYTES) {
kb_in.p_head = kb_in.buf;
}
kb_in.count++;
}
}
PUBLIC void init_keyboard()
{
kb_in.count = 0;
kb_in.p_head = kb_in.p_tail = kb_in.buf;
shift_l = shift_r = 0;
alt_l = alt_r = 0;
ctrl_l = ctrl_r = 0;
caps_lock = 0;
num_lock = 1;
scroll_lock = 0;
set_leds();
put_irq_handler(KEYBOARD_IRQ, keyboard_handler); /* 设定键盘中断处理程序 */
enable_irq(KEYBOARD_IRQ); /* 开启键盘中断 */
}
PUBLIC void keyboard_read(TTY* p_tty)
{
u8 scan_code;
int make; /* TURE: make; FALSE: break. */
u32 key = 0; /* 用一个整数来表示一个键。比如:如果 Home 被按下,则 key 值将为定义在 keyboard.h 中的 'HOME' */
u32* keyrow; /* 指向 keymap[] 的某一行 */
if (kb_in.count > 0) {
code_with_E0 = 0;
scan_code = get_byte_from_kbuf();
/* 下面开始解析扫描码 */
if (scan_code == 0xE1) {
int i;
u8 pausebrk_scode[] = {0xE1, 0x1D, 0x45,
0xE1, 0x9D, 0xC5};
int is_pausebreak = 1;
for (i = 1; i < 6; i++) {
if (get_byte_from_kbuf() != pausebrk_scode[i]) {
is_pausebreak = 0;
break;
}
}
if (is_pausebreak) {
key = PAUSEBREAK;
}
} else if (scan_code == 0xE0) {
scan_code = get_byte_from_kbuf();
/* PrintScreen 被按下 */
if (scan_code == 0x2A) {
if (get_byte_from_kbuf() == 0xE0) {
if (get_byte_from_kbuf() == 0x37) {
key = PRINTSCREEN;
make = 1;
}
}
}
/* PrintScreen 被释放 */
if (scan_code == 0xB7) {
if (get_byte_from_kbuf() == 0xE0) {
if (get_byte_from_kbuf() == 0xAA) {
key = PRINTSCREEN;
make = 0;
}
}
}
/* 不是PrintScreen,此时scan_code为0xE0紧跟的那个值 */
if (key == 0) {
code_with_E0 = 1;
}
}
if ((key != PAUSEBREAK) && (key != PRINTSCREEN)) {
/* 首先判断是 Make Code 还是 Break Code */
make = (scan_code & FLAG_BREAK ? FALSE : TRUE);
/* 先定位到 keymap 中的行 */
keyrow = &keymap[(scan_code & 0x7F) * MAP_COLS];
column = 0;
int caps = shift_l || shift_r;
if (caps_lock) {
if ((keyrow[0] >= 'a') && (keyrow[0] <= 'z')) {
caps = !caps;
}
}
if (caps) {
column = 1;
}
if (code_with_E0) {
column = 2;
}
key = keyrow[column];
switch(key) {
case SHIFT_L:
shift_l = make;
break;
case SHIFT_R:
shift_r = make;
break;
case CTRL_L:
ctrl_l = make;
break;
case CTRL_R:
ctrl_r = make;
break;
case ALT_L:
alt_l = make;
break;
case ALT_R:
alt_r = make;
break;
case CAPS_LOCK:
if (make) {
caps_lock = !caps_lock;
set_leds();
}
break;
case NUM_LOCK:
if (make) {
num_lock = !num_lock;
set_leds();
}
break;
case SCROLL_LOCK:
if (make) {
scroll_lock = !scroll_lock;
set_leds();
}
break;
default:
break;
}
if (make) { /* 忽略 Break Code */
int pad = 0;
/* 首先处理小键盘 */
if ((key >= PAD_SLASH) && (key <= PAD_9)) {
pad = 1;
switch(key) {
case PAD_SLASH:
key = '/';
break;
case PAD_STAR:
key = '*';
break;
case PAD_MINUS:
key = '-';
break;
case PAD_PLUS:
key = '+';
break;
case PAD_ENTER:
key = ENTER;
break;
default:
if (num_lock && (key >= PAD_0) && (key <= PAD_9)) {
key = key - PAD_0 + '0';
} else if (num_lock && (key == PAD_DOT)) {
key = '.';
} else {
switch(key) {
case PAD_HOME:
key = HOME;
break;
case PAD_END:
key = END;
break;
case PAD_PAGEUP:
key = PAGEUP;
break;
case PAD_PAGEDOWN:
key = PAGEDOWN;
break;
case PAD_INS:
key = INSERT;
break;
case PAD_UP:
key = UP;
break;
case PAD_DOWN:
key = DOWN;
break;
case PAD_LEFT:
key