diff --git a/kernel/common/glib.h b/kernel/common/glib.h index a31ae8a2..d64aecb2 100644 --- a/kernel/common/glib.h +++ b/kernel/common/glib.h @@ -522,7 +522,6 @@ long strnlen_user(void *src, unsigned long maxlen) { unsigned long size = strlen(src); - // 地址不合法 if (!verify_area((uint64_t)src, size)) return 0; diff --git a/kernel/driver/keyboard/ps2_keyboard.c b/kernel/driver/keyboard/ps2_keyboard.c index 05c61dc9..591f7b80 100644 --- a/kernel/driver/keyboard/ps2_keyboard.c +++ b/kernel/driver/keyboard/ps2_keyboard.c @@ -5,16 +5,15 @@ #include "../../common/printk.h" #include #include +#include // 键盘输入缓冲区 static struct ps2_keyboard_input_buffer *kb_buf_ptr = NULL; // 缓冲区等待队列 static wait_queue_node_t ps2_keyboard_wait_queue; -// 功能键标志变量 -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; +// 缓冲区读写锁 +static spinlock_t ps2_kb_buf_rw_lock; /** * @brief 重置ps2键盘输入缓冲区 @@ -110,19 +109,25 @@ long ps2_keyboard_read(struct vfs_file_t *filp, char *buf, int64_t count, long * long counter = kb_buf_ptr->count >= count ? count : kb_buf_ptr->count; uint8_t *tail = kb_buf_ptr->ptr_tail; + int64_t tmp = (kb_buf_ptr->buffer + ps2_keyboard_buffer_size - tail); // 要读取的部分没有越过缓冲区末尾 - if (counter <= (kb_buf_ptr->buffer + ps2_keyboard_buffer_size - tail)) + if (counter <= tmp) { copy_to_user(buf, tail, counter); kb_buf_ptr->ptr_tail += counter; + // tail越界,则将其重新放置到起始位置 + if (kb_buf_ptr->ptr_tail == kb_buf_ptr->buffer + ps2_keyboard_buffer_size) + kb_buf_ptr->ptr_tail = kb_buf_ptr->buffer; } else // 要读取的部分越过了缓冲区的末尾,进行循环 { - uint64_t tmp = (kb_buf_ptr->buffer + ps2_keyboard_buffer_size - tail); - copy_to_user(buf, tail, tmp); - copy_to_user(buf, kb_buf_ptr->ptr_head, counter - tmp); - kb_buf_ptr->ptr_tail = kb_buf_ptr->ptr_head + (counter - tmp); + + if (tmp > 0) + copy_to_user(buf, tail, tmp); + if (counter - tmp > 0) + copy_to_user(buf, kb_buf_ptr->buffer, counter - tmp); + kb_buf_ptr->ptr_tail = kb_buf_ptr->buffer + (counter - tmp); } kb_buf_ptr->count -= counter; @@ -164,7 +169,6 @@ struct vfs_file_operations_t ps2_keyboard_fops = */ void ps2_keyboard_handler(ul irq_num, ul param, struct pt_regs *regs) { - // 读取键盘输入的信息 unsigned char x = io_in8(PORT_PS2_KEYBOARD_DATA); // printk_color(ORANGE, BLACK, "key_pressed:%02x\n", x); @@ -229,15 +233,11 @@ void ps2_keyboard_init() for (int i = 0; i < 1000; ++i) for (int j = 0; j < 1000; ++j) nop(); - shift_l = false; - shift_r = false; - ctrl_l = false; - ctrl_r = false; - alt_l = false; - alt_r = false; wait_queue_init(&ps2_keyboard_wait_queue, NULL); - + // 初始化键盘缓冲区的读写锁 + spin_init(&ps2_kb_buf_rw_lock); + // 注册中断处理程序 irq_register(PS2_KEYBOARD_INTR_VECTOR, &entry, &ps2_keyboard_handler, (ul)kb_buf_ptr, &ps2_keyboard_intr_controller, "ps/2 keyboard"); kdebug("kb registered."); @@ -252,256 +252,3 @@ void ps2_keyboard_exit() irq_unregister(PS2_KEYBOARD_INTR_VECTOR); kfree((ul *)kb_buf_ptr); } - -/** - * @brief 解析键盘扫描码 - * - */ -void ps2_keyboard_analyze_keycode() -{ - bool flag_make = false; - - int c = ps2_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 (ps2_keyboard_get_scancode() != pause_break_scan_code[i]) - { - key = 0; - break; - } - } - else if (scancode == 0xE0) // 功能键, 有多个扫描码 - { - // 获取下一个扫描码 - scancode = ps2_keyboard_get_scancode(); - switch (scancode) - { - case 0x2a: // print screen 按键被按下 - if (ps2_keyboard_get_scancode() == 0xe0) - if (ps2_keyboard_get_scancode() == 0x37) - { - key = PRINT_SCREEN; - flag_make = true; - } - break; - case 0xb7: // print screen 按键被松开 - if (ps2_keyboard_get_scancode() == 0xe0) - if (ps2_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, BLACK, "%c", key); - } -} - -/** - * @brief 从缓冲队列中获取键盘扫描码 - * - */ -int ps2_keyboard_get_scancode() -{ - // 缓冲队列为空 - if (kb_buf_ptr->count == 0) - return -1; - - if (kb_buf_ptr->ptr_tail == kb_buf_ptr->buffer + ps2_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/ps2_keyboard.h b/kernel/driver/keyboard/ps2_keyboard.h index 307e3b8c..6695db2a 100644 --- a/kernel/driver/keyboard/ps2_keyboard.h +++ b/kernel/driver/keyboard/ps2_keyboard.h @@ -5,7 +5,7 @@ #define PS2_KEYBOARD_INTR_VECTOR 0x21 // 键盘的中断向量号 // 定义键盘循环队列缓冲区大小为100bytes -#define ps2_keyboard_buffer_size 100 +#define ps2_keyboard_buffer_size 8 #define KEYBOARD_CMD_RESET_BUFFER 1 @@ -38,164 +38,10 @@ struct ps2_keyboard_input_buffer // 等待从键盘控制器读取信息完成 #define wait_ps2_keyboard_read() while (io_in8(PORT_PS2_KEYBOARD_STATUS) & PS2_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 +extern struct vfs_file_operations_t ps2_keyboard_fops; -// 键盘扫描码有三种: -// 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*/ '\b', '\b', //BACKSPACE -/*0x0f*/ '\t', '\t', //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*/ '\n', '\n', //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 初始化键盘驱动程序的函数 diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index 5e862760..2a3376ad 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -28,6 +28,7 @@ struct vfs_superblock_t *vfs_root_sb = NULL; */ #define VFS_ATTR_FILE (1UL << 0) #define VFS_ATTR_DIR (1UL << 1) +#define VFS_ATTR_DEVICE (1UL << 2) struct vfs_super_block_operations_t; struct vfs_inode_operations_t; diff --git a/kernel/main.c b/kernel/main.c index 467f3d76..98bdbbe4 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -148,7 +148,7 @@ void system_initialize() smp_init(); cpu_init(); - // ps2_keyboard_init(); + ps2_keyboard_init(); // ps2_mouse_init(); // ata_init(); pci_init(); diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index d03e66ca..baeb638a 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include // 导出系统调用入口函数,定义在entry.S中 extern void system_call(void); @@ -108,8 +110,9 @@ uint64_t sys_open(struct pt_regs *regs) char *filename = (char *)(regs->r8); int flags = (int)(regs->r9); + kdebug("filename=%s", filename); - long path_len = strnlen_user(filename, PAGE_4K_SIZE); + long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1; if (path_len <= 0) // 地址空间错误 { @@ -130,20 +133,30 @@ uint64_t sys_open(struct pt_regs *regs) // 寻找文件 struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0); - kfree(path); if (dentry != NULL) printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size); else printk_color(ORANGE, BLACK, "Can`t find file\n"); - if (dentry == NULL) + kfree(path); + if (dentry == NULL) return -ENOENT; // 暂时认为目标是目录是一种错误 if (dentry->dir_inode->attribute == VFS_ATTR_DIR) return -EISDIR; + // todo: 引入devfs后删除这段代码 + // 暂时遇到设备文件的话,就将其first clus设置为特定值 + if (path_len >= 5 && filename[0] == '/' && filename[1] == 'd' && filename[2] == 'e' && filename[3] == 'v' && filename[4] == '/') + { + // 对于fat32文件系统上面的设备文件,设置其起始扇区 + ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000; + dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode); + dentry->dir_inode->attribute |= VFS_ATTR_DEVICE; + } + // 创建文件描述符 struct vfs_file_t *file_ptr = (struct vfs_file_t *)kmalloc(sizeof(struct vfs_file_t), 0); memset(file_ptr, 0, sizeof(struct vfs_file_t)); @@ -152,7 +165,15 @@ uint64_t sys_open(struct pt_regs *regs) file_ptr->dEntry = dentry; file_ptr->mode = flags; - file_ptr->file_ops = dentry->dir_inode->file_ops; + + // todo: 接入devfs + // 特判一下是否为键盘文件 + if (dentry->dir_inode->attribute & VFS_ATTR_DEVICE) + { + file_ptr->file_ops = &ps2_keyboard_fops; // 如果是设备文件,暂时认为它是键盘文件 + } + else + file_ptr->file_ops = dentry->dir_inode->file_ops; // 如果文件系统实现了打开文件的函数 if (file_ptr->file_ops && file_ptr->file_ops->open) diff --git a/user/Makefile b/user/Makefile index 6bd0e049..ccfa3966 100644 --- a/user/Makefile +++ b/user/Makefile @@ -24,9 +24,8 @@ all: objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O elf64-x86-64 sys_api_lib $(ROOT_PATH)/bin/user/init.bin sys_api_lib: init.o - - ld -b elf64-x86-64 -z muldefs -o sys_api_lib init.o $(shell find . -name "*.o") + ld -b elf64-x86-64 -z muldefs -o sys_api_lib $(shell find . -name "*.o") #ld -b elf64-x86-64 -z muldefs -o sys_api_lib init.o $(shell find . -name "*.o") -T init.lds init.o: init.c diff --git a/user/init.c b/user/init.c index b392c2aa..5e7a86b7 100644 --- a/user/init.c +++ b/user/init.c @@ -2,16 +2,28 @@ #include #include #include - +#include int main() { - char string[] = "333.txt"; + char string[] = "/333.txt"; uint8_t buf[128] = {0}; char tips_str[] = "The first application 'init.bin' started successfully!\n"; put_string(tips_str, COLOR_GREEN, COLOR_BLACK); printf("test printf: %s size: %d\n", string, sizeof(string)); + + char kb_file_path[] = "/dev/keyboard.dev"; + int kb_fd = open(kb_file_path, 0); + printf("keyboard fd = %d\n", kb_fd); + while (true) + { + int key = keyboard_analyze_keycode(kb_fd); + if(key) + printf("%c", (char)key); + } + + /* int fd = open(string, 0); printf("fd=%d\n", fd); @@ -31,7 +43,7 @@ int main() read(fd, buf, 128); put_string(buf, COLOR_YELLOW, COLOR_BLACK); close(fd); - */ + void *ptr[256] = {0}; for (int k = 0; k < 2; ++k) @@ -57,6 +69,8 @@ int main() } printf("free done!\n"); } + */ + // *p = 'a'; /* diff --git a/user/libs/Makefile b/user/libs/Makefile index 5bf89bbf..2adcc764 100644 --- a/user/libs/Makefile +++ b/user/libs/Makefile @@ -1,5 +1,5 @@ -user_libs_sub_dirs=libc libsystem +user_libs_sub_dirs=libc libsystem libKeyboard all: diff --git a/user/libs/libKeyboard/Makefile b/user/libs/libKeyboard/Makefile new file mode 100644 index 00000000..59d35c64 --- /dev/null +++ b/user/libs/libKeyboard/Makefile @@ -0,0 +1,7 @@ +all: keyboard.o + +CFLAGS += -I . + + +keyboard.o: keyboard.c + gcc $(CFLAGS) -c keyboard.c -o keyboard.o \ No newline at end of file diff --git a/user/libs/libKeyboard/keyboard.c b/user/libs/libKeyboard/keyboard.c new file mode 100644 index 00000000..58a41335 --- /dev/null +++ b/user/libs/libKeyboard/keyboard.c @@ -0,0 +1,530 @@ +#include "keyboard.h" +#include +// 功能键标志变量 +static bool shift_l = 0, shift_r = 0, ctrl_l = 0, ctrl_r = 0, alt_l = 0, alt_r = 0; +static bool gui_l = 0, gui_r = 0, apps = 0, insert = 0, home = 0, pgup = 0, del = 0, end = 0, pgdn = 0, arrow_u = 0, arrow_l = 0, arrow_d = 0, arrow_r = 0; +static bool kp_forward_slash = 0, kp_en = 0; + +// 键盘扫描码有三种: +// 0xE1开头的PauseBreak键 +// 0xE0开头的功能键 +// 1byte的普通按键 + +// pause break键的扫描码,没错,它就是这么长 +unsigned char pause_break_scan_code[] = {0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5}; + +// 第一套键盘扫描码 及其对应的字符 +uint32_t 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*/ '\b', + '\b', // BACKSPACE + /*0x0f*/ '\t', + '\t', // 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*/ '\n', + '\n', // 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 解析键盘扫描码 + * + */ +int keyboard_analyze_keycode(int fd) +{ + bool flag_make = false; + + int c = keyboard_get_scancode(fd); + // 循环队列为空 + if (c == -1) + return 0; + + 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(fd) != pause_break_scan_code[i]) + { + key = 0; + break; + } + } + else if (scancode == 0xE0) // 功能键, 有多个扫描码 + { + // 获取下一个扫描码 + scancode = keyboard_get_scancode(fd); + switch (scancode) + { + case 0x2a: // print screen 按键被按下 + if (keyboard_get_scancode(fd) == 0xe0) + if (keyboard_get_scancode(fd) == 0x37) + { + key = PRINT_SCREEN; + flag_make = true; + } + break; + case 0xb7: // print screen 按键被松开 + if (keyboard_get_scancode(fd) == 0xe0) + if (keyboard_get_scancode(fd) == 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); + + // 计算扫描码位于码表的第几行 + uint32_t *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) + return key; + } + return 0; +} + +/** + * @brief 从键盘设备文件中获取键盘扫描码 + * + */ +int keyboard_get_scancode(int fd) +{ + unsigned int ret = 0; + read(fd, &ret, 1); + return ret; +} \ No newline at end of file diff --git a/user/libs/libKeyboard/keyboard.h b/user/libs/libKeyboard/keyboard.h new file mode 100644 index 00000000..863ade53 --- /dev/null +++ b/user/libs/libKeyboard/keyboard.h @@ -0,0 +1,22 @@ +#pragma once + +// 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 + +/** + * @brief 从键盘设备文件中获取键盘扫描码 + * + */ +int keyboard_get_scancode(int fd); + +/** + * @brief 解析键盘扫描码 + * + */ +int keyboard_analyze_keycode(int fd); \ No newline at end of file diff --git a/user/libs/libc/malloc.c b/user/libs/libc/malloc.c index 280be9a6..040e895a 100644 --- a/user/libs/libc/malloc.c +++ b/user/libs/libc/malloc.c @@ -367,12 +367,13 @@ static void release_brk() * * @param ptr 堆内存的指针 */ -void free(void *ptr) +void free(void *ptr) { // 找到结点(此时prev和next都处于未初始化的状态) malloc_mem_chunk_t *ck = (malloc_mem_chunk_t *)((uint64_t)ptr - sizeof(uint64_t)); // printf("free(): addr = %#018lx\t len=%#018lx\n", (uint64_t)ck, ck->length); count_last_free_size += ck->length; + malloc_insert_free_list(ck); if (count_last_free_size > PAGE_2M_SIZE)