键盘模块:
初始化键盘中断
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;
put_irq_handler(KEYBOARD_IRQ, keyboard_handler);/*设定键盘中断处理程序*/
enable_irq(KEYBOARD_IRQ); /*开键盘中断*/
}
其中:
#define KEYBOARD_IRQ 1
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++;
}
}
#define KB_DATA 0x60
#define KB_CMD 0x64;
PUBLIC void keyboard_read()
{
u8 scan_code;
char output[2];
int make; /* 1: make; 0: 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};/*代表:PAUSE*/
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) { /* 0x2A代表:SHIFT_L */
if (get_byte_from_kbuf() == 0xE0) { /* 0xE0代表: */
if (get_byte_from_kbuf() == 0x37) { /* 0x37代表:* */
key = PRINTSCREEN;
make = 1;
}
}
}
/* PrintScreen 被释放 */
if (scan_code == 0xB7) { /* 0xB7代表: */
if (get_byte_from_kbuf() == 0xE0) { /* 0xE0代表: */
if (get_byte_from_kbuf() == 0xAA) { /* 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 ? 0 : 1);
/* 先定位到 keymap 中的行 MAP_COLS=3 */
keyrow = &keymap[(scan_code & 0x7F) * MAP_COLS];
column = 0;
if (shift_l || shift_r) {
column = 1;
}
if (code_with_E0) {
column = 2;
code_with_E0 = 0;
}
/* 取keyrow第几行 */
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_l = make;
break;
default:
break;
}
if (make) { /* 忽略 Break Code */
key |= shift_l ? FLAG_SHIFT_L : 0;
key |= shift_r ? FLAG_SHIFT_R : 0;
key |= ctrl_l ? FLAG_CTRL_L : 0;
key |= ctrl_r ? FLAG_CTRL_R : 0;
key |= alt_l ? FLAG_ALT_L : 0;
key |= alt_r ? FLAG_ALT_R : 0;
in_process(key);
}
}
}
}
PRIVATE u8 get_byte_from_kbuf() /* 从键盘缓冲区中读取下一个字节 */
{
u8 scan_code;
while (kb_in.count <= 0) {} /* 等待下一个字节到来 */
disable_int();
scan_code = *(kb_in.p_tail);
kb_in.p_tail++;
if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) {
kb_in.p_tail = kb_in.buf;
}
kb_in.count--;
enable_int();
return scan_code;
}
PUBLIC void in_process(u32 key)
{
char output[2] = {'\0', '\0'};
if (!(key & FLAG_EXT)) {
output[0] = key & 0xFF;
disp_str(output);
}
}
终端代码说明:
a键按下(make code)为0x1E 释放(break code)为0x9E
break code=make code|0x80
如果A则为(一般用左边shift):0x2A 0x1E 0x9E 0xAA,
对大写A分析:
按下shift键,则shift_l或shift_r变成1,column=1
再按下a键,程序找出keymap中a 那一行
弹起a键,则忽略
弹起shift键,则shift_l或shift_r变成0,column=0
欢迎大家加入我们gentoo技术群!
操作系统设计之终端模块代码分析-键盘部分
2021-11-28服务器相关
简介操作系统设计,终端模块代码分析,键盘部分
郑重声明:
本站所有活动均为互联网所得,如有侵权请联系本站删除处理
随便看看
文章排行
本栏推荐
栏目更新
Copyright 2020 Inc. AllRights Reserved. Design by 操作系统设计之终端模块代码分析-键盘部分