🆕 键盘驱动

This commit is contained in:
fslongjin 2022-03-17 00:00:28 +08:00
parent cc1e126959
commit 1333afd703
5 changed files with 446 additions and 16 deletions

View File

@ -58,7 +58,7 @@ bool acpi_get_MADT(const struct acpi_system_description_table_header_t *_iter_da
return false;
//*(struct acpi_Multiple_APIC_Description_Table_t *)_data = *(struct acpi_Multiple_APIC_Description_Table_t *)_iter_data;
// 返回MADT的虚拟地址
*(ul*)_data = _iter_data;
*(ul*)_data = (ul)_iter_data;
return true;
}

View File

@ -55,7 +55,7 @@ void apic_io_apic_init()
apic_ioapic_map.virtual_EOI_addr = (uint *)(APIC_IO_APIC_VIRT_BASE_ADDR + 0x40);
// 填写页表,完成地址映射
mm_map_phys_addr(apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
mm_map_phys_addr((ul)apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
// 设置IO APIC ID 为0x0f000000
*apic_ioapic_map.virtual_index_addr = 0x00;

View File

@ -5,7 +5,12 @@
#include "../../common/printk.h"
static struct keyboard_input_buffer *kb_buf_ptr = NULL;
static int shift_l, shift_r, ctrl_l, ctrl_r, alt_l, alt_r;
// 功能键标志变量
static bool shift_l, shift_r, ctrl_l, ctrl_r, alt_l, alt_r;
static bool gui_l, gui_r, apps, insert, home, pgup, del, end, pgdn, arrow_u, arrow_l, arrow_d, arrow_r;
static bool kp_forward_slash, kp_en;
struct apic_IO_APIC_RTE_entry entry;
hardware_intr_controller keyboard_intr_controller =
@ -29,10 +34,10 @@ void keyboard_handler(ul irq_num, ul param, struct pt_regs *regs)
{
// 读取键盘输入的信息
unsigned x = io_in8(0x60);
printk_color(ORANGE, BLACK, "key_pressed:%02x\n", x);
// printk_color(ORANGE, BLACK, "key_pressed:%02x\n", x);
// 当头指针越过界时,恢复指向数组头部
if (kb_buf_ptr->ptr_head == kb_buf_ptr + keyboard_buffer_size)
if (kb_buf_ptr->ptr_head == kb_buf_ptr->buffer + keyboard_buffer_size)
kb_buf_ptr->ptr_head = kb_buf_ptr->buffer;
if (kb_buf_ptr->count >= keyboard_buffer_size)
@ -56,8 +61,8 @@ void keyboard_init()
// 申请键盘循环队列缓冲区的内存
kb_buf_ptr = (struct keyboard_input_buffer *)kmalloc(sizeof(struct keyboard_input_buffer), 0);
kb_buf_ptr->ptr_head = kb_buf_ptr;
kb_buf_ptr->ptr_tail = kb_buf_ptr;
kb_buf_ptr->ptr_head = kb_buf_ptr->buffer;
kb_buf_ptr->ptr_tail = kb_buf_ptr->buffer;
kb_buf_ptr->count = 0;
memset(kb_buf_ptr->buffer, 0, keyboard_buffer_size);
@ -89,12 +94,12 @@ void keyboard_init()
for (int i = 0; i < 1000; ++i)
for (int j = 0; j < 1000; ++j)
nop();
shift_l = 0;
shift_r = 0;
ctrl_l = 0;
ctrl_r = 0;
alt_l = 0;
alt_r = 0;
shift_l = false;
shift_r = false;
ctrl_l = false;
ctrl_r = false;
alt_l = false;
alt_r = false;
// 注册中断处理程序
irq_register(0x21, &entry, &keyboard_handler, (ul)kb_buf_ptr, &keyboard_intr_controller, "ps/2 keyboard");
@ -109,3 +114,256 @@ void keyboard_exit()
irq_unregister(0x21);
kfree((ul *)kb_buf_ptr);
}
/**
* @brief
*
*/
void keyboard_analyze_keycode()
{
bool flag_make = false;
int c = keyboard_get_scancode();
// 循环队列为空
if (c == -1)
return;
unsigned char scancode = (unsigned char)c;
int key = 0;
if (scancode == 0xE1) // Pause Break
{
key = PAUSE_BREAK;
// 清除缓冲区中剩下的扫描码
for (int i = 1; i < 6; ++i)
if (keyboard_get_scancode() != pause_break_scan_code[i])
{
key = 0;
break;
}
}
else if (scancode == 0xE0) // 功能键, 有多个扫描码
{
// 获取下一个扫描码
scancode = keyboard_get_scancode();
switch (scancode)
{
case 0x2a: // print screen 按键被按下
if (keyboard_get_scancode() == 0xe0)
if (keyboard_get_scancode() == 0x37)
{
key = PRINT_SCREEN;
flag_make = true;
}
break;
case 0xb7: // print screen 按键被松开
if (keyboard_get_scancode() == 0xe0)
if (keyboard_get_scancode() == 0xaa)
{
key = PRINT_SCREEN;
flag_make = false;
}
break;
case 0x1d: // 按下右边的ctrl
ctrl_r = true;
key = OTHER_KEY;
break;
case 0x9d: // 松开右边的ctrl
ctrl_r = false;
key = OTHER_KEY;
break;
case 0x38: // 按下右边的alt
alt_r = true;
key = OTHER_KEY;
break;
case 0xb8: // 松开右边的alt
alt_r = false;
key = OTHER_KEY;
break;
case 0x5b:
gui_l = true;
key = OTHER_KEY;
break;
case 0xdb:
gui_l = false;
key = OTHER_KEY;
break;
case 0x5c:
gui_r = true;
key = OTHER_KEY;
break;
case 0xdc:
gui_r = false;
key = OTHER_KEY;
break;
case 0x5d:
apps = true;
key = OTHER_KEY;
break;
case 0xdd:
apps = false;
key = OTHER_KEY;
break;
case 0x52:
insert = true;
key = OTHER_KEY;
break;
case 0xd2:
insert = false;
key = OTHER_KEY;
break;
case 0x47:
home = true;
key = OTHER_KEY;
break;
case 0xc7:
home = false;
key = OTHER_KEY;
break;
case 0x49:
pgup = true;
key = OTHER_KEY;
break;
case 0xc9:
pgup = false;
key = OTHER_KEY;
break;
case 0x53:
del = true;
key = OTHER_KEY;
break;
case 0xd3:
del = false;
key = OTHER_KEY;
break;
case 0x4f:
end = true;
key = OTHER_KEY;
break;
case 0xcf:
end = false;
key = OTHER_KEY;
break;
case 0x51:
pgdn = true;
key = OTHER_KEY;
break;
case 0xd1:
pgdn = false;
key = OTHER_KEY;
break;
case 0x48:
arrow_u = true;
key = OTHER_KEY;
break;
case 0xc8:
arrow_u = false;
key = OTHER_KEY;
break;
case 0x4b:
arrow_l = true;
key = OTHER_KEY;
break;
case 0xcb:
arrow_l = false;
key = OTHER_KEY;
break;
case 0x50:
arrow_d = true;
key = OTHER_KEY;
break;
case 0xd0:
arrow_d = false;
key = OTHER_KEY;
break;
case 0x4d:
arrow_r = true;
key = OTHER_KEY;
break;
case 0xcd:
arrow_r = false;
key = OTHER_KEY;
break;
case 0x35: // 数字小键盘的 / 符号
kp_forward_slash = true;
key = OTHER_KEY;
break;
case 0xb5:
kp_forward_slash = false;
key = OTHER_KEY;
break;
case 0x1c:
kp_en = true;
key = OTHER_KEY;
break;
case 0x9c:
kp_en = false;
key = OTHER_KEY;
break;
default:
key = OTHER_KEY;
break;
}
}
if (key == 0) // 属于第三类扫描码
{
// 判断按键是被按下还是抬起
flag_make = ((scancode & FLAG_BREAK) ? 0 : 1);
// 计算扫描码位于码表的第几行
uint *key_row = &keycode_map_normal[(scancode & 0x7f) * MAP_COLS];
unsigned char col = 0;
// shift被按下
if (shift_l || shift_r)
col = 1;
key = key_row[col];
switch (scancode & 0x7f)
{
case 0x2a:
shift_l = flag_make;
key = 0;
break;
case 0x36:
shift_r = flag_make;
key = 0;
break;
case 0x1d:
ctrl_l = flag_make;
key = 0;
break;
case 0x38:
ctrl_r = flag_make;
key = 0;
break;
default:
if (!flag_make)
key = 0;
break;
}
if (key)
printk_color(ORANGE, WHITE, "(key:%c)\t", key);
}
}
/**
* @brief
*
*/
int keyboard_get_scancode()
{
// 缓冲队列为空
if (kb_buf_ptr->count == 0)
return -1;
if (kb_buf_ptr->ptr_tail == kb_buf_ptr->buffer + keyboard_buffer_size)
kb_buf_ptr->ptr_tail = kb_buf_ptr->buffer;
int ret = (int)(*(kb_buf_ptr->ptr_tail));
--(kb_buf_ptr->count);
++(kb_buf_ptr->ptr_tail);
return ret;
}

View File

@ -34,14 +34,186 @@ struct keyboard_input_buffer
// 等待从键盘控制器读取信息完成
#define wait_keyboard_read() while (io_in8(PORT_KEYBOARD_STATUS) & KEYBOARD_FLAG_OUTBUF_FULL)
// 128个按键, 每个按键包含普通按键和shift+普通按键两种状态
#define NUM_SCAN_CODES 0x80
#define MAP_COLS 2
#define PAUSE_BREAK 1
#define PRINT_SCREEN 2
#define OTHER_KEY 4 // 除了上面两个按键以外的功能按键(不包括下面的第三类按键)
#define FLAG_BREAK 0X80
// 键盘扫描码有三种:
// 0xE1开头的PauseBreak键
// 0xE0开头的功能键
// 1byte的普通按键
// pause break键的扫描码没错它就是这么长
unsigned char pause_break_scan_code[] = {0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5};
// 第一套键盘扫描码 及其对应的字符
uint keycode_map_normal[NUM_SCAN_CODES*MAP_COLS] =
{
/*scan-code unShift Shift */
/*--------------------------------------------------------------*/
/*0x00*/ 0, 0,
/*0x01*/ 0, 0, //ESC
/*0x02*/ '1', '!',
/*0x03*/ '2', '@',
/*0x04*/ '3', '#',
/*0x05*/ '4', '$',
/*0x06*/ '5', '%',
/*0x07*/ '6', '^',
/*0x08*/ '7', '&',
/*0x09*/ '8', '*',
/*0x0a*/ '9', '(',
/*0x0b*/ '0', ')',
/*0x0c*/ '-', '_',
/*0x0d*/ '=', '+',
/*0x0e*/ 0, 0, //BACKSPACE
/*0x0f*/ 0, 0, //TAB
/*0x10*/ 'q', 'Q',
/*0x11*/ 'w', 'W',
/*0x12*/ 'e', 'E',
/*0x13*/ 'r', 'R',
/*0x14*/ 't', 'T',
/*0x15*/ 'y', 'Y',
/*0x16*/ 'u', 'U',
/*0x17*/ 'i', 'I',
/*0x18*/ 'o', 'O',
/*0x19*/ 'p', 'P',
/*0x1a*/ '[', '{',
/*0x1b*/ ']', '}',
/*0x1c*/ 0, 0, //ENTER
/*0x1d*/ 0x1d, 0x1d, //CTRL Left
/*0x1e*/ 'a', 'A',
/*0x1f*/ 's', 'S',
/*0x20*/ 'd', 'D',
/*0x21*/ 'f', 'F',
/*0x22*/ 'g', 'G',
/*0x23*/ 'h', 'H',
/*0x24*/ 'j', 'J',
/*0x25*/ 'k', 'K',
/*0x26*/ 'l', 'L',
/*0x27*/ ';', ':',
/*0x28*/ '\'', '"',
/*0x29*/ '`', '~',
/*0x2a*/ 0x2a, 0x2a, //SHIFT Left
/*0x2b*/ '\\', '|',
/*0x2c*/ 'z', 'Z',
/*0x2d*/ 'x', 'X',
/*0x2e*/ 'c', 'C',
/*0x2f*/ 'v', 'V',
/*0x30*/ 'b', 'B',
/*0x31*/ 'n', 'N',
/*0x32*/ 'm', 'M',
/*0x33*/ ',', '<',
/*0x34*/ '.', '>',
/*0x35*/ '/', '?',
/*0x36*/ 0x36, 0x36, //SHIFT Right
/*0x37*/ '*', '*',
/*0x38*/ 0x38, 0x38, //ALT Left
/*0x39*/ ' ', ' ',
/*0x3a*/ 0, 0, //CAPS LOCK
/*0x3b*/ 0, 0, //F1
/*0x3c*/ 0, 0, //F2
/*0x3d*/ 0, 0, //F3
/*0x3e*/ 0, 0, //F4
/*0x3f*/ 0, 0, //F5
/*0x40*/ 0, 0, //F6
/*0x41*/ 0, 0, //F7
/*0x42*/ 0, 0, //F8
/*0x43*/ 0, 0, //F9
/*0x44*/ 0, 0, //F10
/*0x45*/ 0, 0, //NUM LOCK
/*0x46*/ 0, 0, //SCROLL LOCK
/*0x47*/ '7', 0, /*PAD HONE*/
/*0x48*/ '8', 0, /*PAD UP*/
/*0x49*/ '9', 0, /*PAD PAGEUP*/
/*0x4a*/ '-', 0, /*PAD MINUS*/
/*0x4b*/ '4', 0, /*PAD LEFT*/
/*0x4c*/ '5', 0, /*PAD MID*/
/*0x4d*/ '6', 0, /*PAD RIGHT*/
/*0x4e*/ '+', 0, /*PAD PLUS*/
/*0x4f*/ '1', 0, /*PAD END*/
/*0x50*/ '2', 0, /*PAD DOWN*/
/*0x51*/ '3', 0, /*PAD PAGEDOWN*/
/*0x52*/ '0', 0, /*PAD INS*/
/*0x53*/ '.', 0, /*PAD DOT*/
/*0x54*/ 0, 0,
/*0x55*/ 0, 0,
/*0x56*/ 0, 0,
/*0x57*/ 0, 0, //F11
/*0x58*/ 0, 0, //F12
/*0x59*/ 0, 0,
/*0x5a*/ 0, 0,
/*0x5b*/ 0, 0,
/*0x5c*/ 0, 0,
/*0x5d*/ 0, 0,
/*0x5e*/ 0, 0,
/*0x5f*/ 0, 0,
/*0x60*/ 0, 0,
/*0x61*/ 0, 0,
/*0x62*/ 0, 0,
/*0x63*/ 0, 0,
/*0x64*/ 0, 0,
/*0x65*/ 0, 0,
/*0x66*/ 0, 0,
/*0x67*/ 0, 0,
/*0x68*/ 0, 0,
/*0x69*/ 0, 0,
/*0x6a*/ 0, 0,
/*0x6b*/ 0, 0,
/*0x6c*/ 0, 0,
/*0x6d*/ 0, 0,
/*0x6e*/ 0, 0,
/*0x6f*/ 0, 0,
/*0x70*/ 0, 0,
/*0x71*/ 0, 0,
/*0x72*/ 0, 0,
/*0x73*/ 0, 0,
/*0x74*/ 0, 0,
/*0x75*/ 0, 0,
/*0x76*/ 0, 0,
/*0x77*/ 0, 0,
/*0x78*/ 0, 0,
/*0x79*/ 0, 0,
/*0x7a*/ 0, 0,
/*0x7b*/ 0, 0,
/*0x7c*/ 0, 0,
/*0x7d*/ 0, 0,
/*0x7e*/ 0, 0,
/*0x7f*/ 0, 0,
};
/**
* @brief
*
*
*/
void keyboard_init();
/**
* @brief
*
*/
void keyboard_exit();
/**
* @brief
*
*/
void keyboard_exit();
void keyboard_analyze_keycode();
/**
* @brief
* @return
* -1
*/
int keyboard_get_scancode();

View File

@ -179,7 +179,7 @@ void Start_Kernel(void)
// test_mm();
while (1)
;
keyboard_analyze_keycode();
}
void ignore_int()