diff --git a/kernel/driver/acpi/acpi.c b/kernel/driver/acpi/acpi.c index 1cd0119e..79dfeefe 100644 --- a/kernel/driver/acpi/acpi.c +++ b/kernel/driver/acpi/acpi.c @@ -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; } diff --git a/kernel/driver/interrupt/apic/apic.c b/kernel/driver/interrupt/apic/apic.c index 7958fa80..4f018d48 100644 --- a/kernel/driver/interrupt/apic/apic.c +++ b/kernel/driver/interrupt/apic/apic.c @@ -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; diff --git a/kernel/driver/keyboard/keyboard.c b/kernel/driver/keyboard/keyboard.c index 8c9d5828..9f52adb0 100644 --- a/kernel/driver/keyboard/keyboard.c +++ b/kernel/driver/keyboard/keyboard.c @@ -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; +} \ No newline at end of file diff --git a/kernel/driver/keyboard/keyboard.h b/kernel/driver/keyboard/keyboard.h index 5f0deaca..49555f14 100644 --- a/kernel/driver/keyboard/keyboard.h +++ b/kernel/driver/keyboard/keyboard.h @@ -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(); \ No newline at end of file +void keyboard_analyze_keycode(); + +/** + * @brief 从缓冲队列中获取键盘扫描码 + * @return 键盘扫描码 + * 若缓冲队列为空则返回-1 + */ +int keyboard_get_scancode(); \ No newline at end of file diff --git a/kernel/main.c b/kernel/main.c index 0c41dad0..b33fe7ae 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -179,7 +179,7 @@ void Start_Kernel(void) // test_mm(); while (1) - ; + keyboard_analyze_keycode(); } void ignore_int()