From: Minep Date: Wed, 24 Aug 2022 16:18:24 +0000 (+0100) Subject: refactor: improve on scrolling experience in lunaix console X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/c4510182f3c02e390184bee518940e325f064b20?hp=b3b42765712afed5a35c9be5c832f4a06bd85e7a refactor: improve on scrolling experience in lunaix console fix: handle the strange scan code sequence on Virtualbox's PS/2 keyboard. fix: incompatible pointer type passing in devfs. chore: refactoring and clean up. --- diff --git a/README.md b/README.md index 1a71e57..35db086 100644 --- a/README.md +++ b/README.md @@ -98,10 +98,6 @@ qemu-img create -f vdi machine/disk0.vdi 128M 正常,**因为Bochs不支持SATA**。请使用QEMU或VirtualBox。 -#### 问题#4:键盘的上下方向键(用于滚屏)在VirtualBox下有时不好使 - -可以试试`Shift+<方向键>`,这个问题的解决需要重写键盘驱动的状态机。我会找时间去做,毕竟这不是燃眉之急。 - ## 参考教程 **没有!!** 本教程以及该操作系统均为原创,没有基于任何市面上现行的操作系统开发教程,且并非是基于任何的开源内核的二次开发。 diff --git a/lunaix-os/includes/lunaix/device.h b/lunaix-os/includes/lunaix/device.h index 8171600..be6dc26 100644 --- a/lunaix-os/includes/lunaix/device.h +++ b/lunaix-os/includes/lunaix/device.h @@ -52,12 +52,12 @@ struct device* device_getbyid(struct llist_header* devlist, dev_t id); struct device* -device_getbyhname(struct llist_header* devlist, struct hstr* name); +device_getbyhname(struct device* root_dev, struct hstr* name); struct device* -device_getbyname(struct llist_header* devlist, const char* name, size_t len); +device_getbyname(struct device* root_dev, const char* name, size_t len); struct device* -device_getbyoffset(struct llist_header* devlist, int pos); +device_getbyoffset(struct device* root_dev, int pos); #endif /* __LUNAIX_DEVICE_H */ diff --git a/lunaix-os/includes/lunaix/ds/fifo.h b/lunaix-os/includes/lunaix/ds/fifo.h index 3a21824..a7ac90b 100644 --- a/lunaix-os/includes/lunaix/ds/fifo.h +++ b/lunaix-os/includes/lunaix/ds/fifo.h @@ -23,6 +23,15 @@ fifo_backone(struct fifo_buf* fbuf); size_t fifo_putone(struct fifo_buf* fbuf, uint8_t data); +size_t +fifo_readone_async(struct fifo_buf* fbuf, uint8_t* data); + +void +fifo_set_rdptr(struct fifo_buf* fbuf, size_t rdptr); + +void +fifo_set_wrptr(struct fifo_buf* fbuf, size_t wrptr); + void fifo_init(struct fifo_buf* buf, void* data_buffer, size_t buf_size, int flags); diff --git a/lunaix-os/includes/lunaix/tty/console.h b/lunaix-os/includes/lunaix/tty/console.h index e5eaa34..24d088f 100644 --- a/lunaix-os/includes/lunaix/tty/console.h +++ b/lunaix-os/includes/lunaix/tty/console.h @@ -9,8 +9,8 @@ struct console struct lx_timer* flush_timer; struct fifo_buf output; struct fifo_buf input; - unsigned int erd_pos; - unsigned int lines; + size_t wnd_start; + size_t lines; }; #endif /* __LUNAIX_CONSOLE_H */ diff --git a/lunaix-os/includes/lunaix/tty/tty.h b/lunaix-os/includes/lunaix/tty/tty.h index 518d376..96fe485 100644 --- a/lunaix-os/includes/lunaix/tty/tty.h +++ b/lunaix-os/includes/lunaix/tty/tty.h @@ -1,5 +1,8 @@ #ifndef __LUNAIX_TTY_H #define __LUNAIX_TTY_H + +#include + typedef unsigned short vga_attribute; #define VGA_COLOR_BLACK 0 @@ -31,8 +34,8 @@ tty_set_theme(vga_attribute fg, vga_attribute bg); vga_attribute tty_get_theme(); -size_t -tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size); +void +tty_flush_buffer(struct fifo_buf* buf); void tty_clear_line(int line_num); diff --git a/lunaix-os/kernel/demos/input_test.c b/lunaix-os/kernel/demos/input_test.c index b85f851..5f2a904 100644 --- a/lunaix-os/kernel/demos/input_test.c +++ b/lunaix-os/kernel/demos/input_test.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #define STDIN 1 @@ -13,7 +14,7 @@ input_test() int fd = open("/dev/input/i8042-kbd", 0); if (fd < 0) { - printf("fail to open (%d)", fd); + printf("fail to open (%d)", geterrno()); return; } @@ -27,7 +28,7 @@ input_test() action = "release"; } - printf("%u: %s '%c', class=0x%x, scan=%d\n", + printf("%u: %s '%c', class=0x%x, scan=%x\n", event.timestamp, action, event.sys_code & 0xff, diff --git a/lunaix-os/kernel/demos/simple_sh.c b/lunaix-os/kernel/demos/simple_sh.c index 036550a..8243ae1 100644 --- a/lunaix-os/kernel/demos/simple_sh.c +++ b/lunaix-os/kernel/demos/simple_sh.c @@ -67,9 +67,11 @@ sh_main() char buf[512]; char *cmd, *argpart; + printf("\n Simple shell. Use or to scroll.\n\n"); + while (1) { getcwd(pwd, 512); - printf("%s> ", pwd); + printf("%s$ ", pwd); size_t sz = read(stdin, buf, 512); if (sz < 0) { printf("fail to read user input (%d)\n", geterrno()); @@ -77,6 +79,9 @@ sh_main() } buf[sz - 1] = '\0'; parse_cmdline(buf, &cmd, &argpart); + if (cmd[0] == 0) { + goto cont; + } if (streq(cmd, "cd")) { if (chdir(argpart) < 0) { sh_printerr(); @@ -100,6 +105,7 @@ sh_main() } else { printf("unknow command"); } + cont: printf("\n"); } } \ No newline at end of file diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c index ac674b4..af2a5f7 100644 --- a/lunaix-os/kernel/device/devfs.c +++ b/lunaix-os/kernel/device/devfs.c @@ -74,7 +74,8 @@ devfs_mknod(struct v_dnode* dnode, struct device* dev) int devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode) { - struct device* dev = device_getbyhname(this->data, &dnode->name); + struct device* dev = + device_getbyhname((struct device*)this->data, &dnode->name); if (!dev) { return ENOENT; } @@ -84,9 +85,8 @@ devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode) int devfs_readdir(struct v_file* file, struct dir_context* dctx) { - struct device* holder = (struct device*)(file->inode->data); struct device* dev = - device_getbyoffset(holder ? &holder->children : NULL, dctx->index); + device_getbyoffset((struct device*)(file->inode->data), dctx->index); if (!dev) { return 0; } diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index 282f44d..beb1f18 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -93,9 +93,9 @@ device_getbyid(struct llist_header* devlist, dev_t id) } struct device* -device_getbyhname(struct llist_header* devlist, struct hstr* name) +device_getbyhname(struct device* root_dev, struct hstr* name) { - devlist = devlist ? devlist : &root_list; + struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; struct device *pos, *n; llist_for_each(pos, n, devlist, siblings) { @@ -108,12 +108,12 @@ device_getbyhname(struct llist_header* devlist, struct hstr* name) } struct device* -device_getbyname(struct llist_header* devlist, const char* name, size_t len) +device_getbyname(struct device* root_dev, const char* name, size_t len) { struct hstr hname = HSTR(name, len); hstr_rehash(&hname, HSTR_FULL_HASH); - return device_getbyhname(devlist, &hname); + return device_getbyhname(root_dev, &hname); } void @@ -124,9 +124,9 @@ device_remove(struct device* dev) } struct device* -device_getbyoffset(struct llist_header* devlist, int offset) +device_getbyoffset(struct device* root_dev, int offset) { - devlist = devlist ? devlist : &root_list; + struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; struct device *pos, *n; int off = 0; llist_for_each(pos, n, devlist, siblings) diff --git a/lunaix-os/kernel/ds/fifo.c b/lunaix-os/kernel/ds/fifo.c index 1e72e8d..7f34bf6 100644 --- a/lunaix-os/kernel/ds/fifo.c +++ b/lunaix-os/kernel/ds/fifo.c @@ -53,6 +53,43 @@ fifo_putone(struct fifo_buf* fbuf, uint8_t data) return 1; } +size_t +fifo_readone_async(struct fifo_buf* fbuf, uint8_t* data) +{ + if (fbuf->free_len == fbuf->size) { + return 0; + } + + uint8_t* dest = fbuf->data; + *data = dest[fbuf->rd_pos]; + fbuf->rd_pos = (fbuf->rd_pos + 1) % fbuf->size; + fbuf->free_len++; + + return 1; +} + +void +fifo_set_rdptr(struct fifo_buf* fbuf, size_t rdptr) +{ + fbuf->rd_pos = rdptr; + if (rdptr <= fbuf->wr_pos) { + fbuf->free_len = fbuf->size - fbuf->wr_pos + rdptr; + } else { + fbuf->free_len = rdptr - fbuf->wr_pos; + } +} + +void +fifo_set_wrptr(struct fifo_buf* fbuf, size_t wrptr) +{ + fbuf->wr_pos = wrptr; + if (wrptr <= fbuf->rd_pos) { + fbuf->free_len = fbuf->size - fbuf->rd_pos + wrptr; + } else { + fbuf->free_len = wrptr - fbuf->rd_pos; + } +} + size_t fifo_write(struct fifo_buf* fbuf, void* data, size_t count) { diff --git a/lunaix-os/kernel/peripheral/ps2kbd.c b/lunaix-os/kernel/peripheral/ps2kbd.c index 5065ef6..04debc8 100644 --- a/lunaix-os/kernel/peripheral/ps2kbd.c +++ b/lunaix-os/kernel/peripheral/ps2kbd.c @@ -74,9 +74,12 @@ static struct input_device* kbd_idev; #define KBD_STATE_KWAIT 0x00 #define KBD_STATE_KSPECIAL 0x01 #define KBD_STATE_KRELEASED 0x02 +#define KBD_STATE_E012 0x03 +#define KBD_STATE_KRELEASED_E0 0x04 #define KBD_STATE_CMDPROCS 0x40 -#define KBD_ENABLE_SPIRQ_FIX +// #define KBD_ENABLE_SPIRQ_FIX +#define KBD_ENABLE_SPIRQ_FIX2 // #define KBD_DBGLOG void @@ -336,6 +339,12 @@ intr_ps2_kbd_handler(const isr_param* param) } #endif +#ifdef KBD_ENABLE_SPIRQ_FIX2 + if (scancode == PS2_RESULT_ACK || scancode == PS2_RESULT_NAK) { + return; + } +#endif + #ifdef KBD_DBGLOG kprintf(KDEBUG "%x\n", scancode & 0xff); #endif @@ -353,8 +362,10 @@ intr_ps2_kbd_handler(const isr_param* param) } break; case KBD_STATE_KSPECIAL: - if (scancode == 0xf0) { // release code - kbd_state.state = KBD_STATE_KRELEASED; + if (scancode == 0x12) { + kbd_state.state = KBD_STATE_E012; + } else if (scancode == 0xf0) { // release code + kbd_state.state = KBD_STATE_KRELEASED_E0; } else { key = kbd_state.translation_table[scancode]; kbd_buffer_key_event(key, scancode, KBD_KEY_FPRESSED); @@ -363,10 +374,23 @@ intr_ps2_kbd_handler(const isr_param* param) kbd_state.translation_table = scancode_set2; } break; + // handle the '0xE0, 0x12, 0xE0, xx' sequence + case KBD_STATE_E012: + if (scancode == 0xe0) { + kbd_state.state = KBD_STATE_KSPECIAL; + kbd_state.translation_table = scancode_set2_ex; + } + break; + case KBD_STATE_KRELEASED_E0: + if (scancode == 0x12) { + goto escape_release; + } + // fall through case KBD_STATE_KRELEASED: key = kbd_state.translation_table[scancode]; kbd_buffer_key_event(key, scancode, KBD_KEY_FRELEASED); + escape_release: // reset the translation table to scancode_set2 kbd_state.state = KBD_STATE_KWAIT; kbd_state.translation_table = scancode_set2; diff --git a/lunaix-os/kernel/lxconsole.c b/lunaix-os/kernel/tty/lxconsole.c similarity index 68% rename from lunaix-os/kernel/lxconsole.c rename to lunaix-os/kernel/tty/lxconsole.c index 77949c8..92deb49 100644 --- a/lunaix-os/kernel/lxconsole.c +++ b/lunaix-os/kernel/tty/lxconsole.c @@ -27,9 +27,9 @@ __lxconsole_listener(struct input_device* dev) uint32_t keycode = dev->current_pkt.sys_code; uint32_t type = dev->current_pkt.pkt_type; if (type == PKT_PRESS) { - if (keycode == KEY_UP) { + if (keycode == KEY_PG_UP) { console_view_up(); - } else if (keycode == KEY_DOWN) { + } else if (keycode == KEY_PG_DOWN) { console_view_down(); } goto done; @@ -50,7 +50,7 @@ void lxconsole_init() { memset(&lx_console, 0, sizeof(lx_console)); - fifo_init(&lx_console.output, vzalloc(8192), 8192, 0); + fifo_init(&lx_console.output, valloc(8192), 8192, 0); fifo_init(&lx_console.input, valloc(4096), 4096, 0); lx_console.flush_timer = NULL; @@ -103,36 +103,43 @@ console_schedule_flush() // TODO make the flush on-demand rather than periodic } -void -console_view_up() +size_t +__find_next_line(size_t start) { + size_t p = start - 1; struct fifo_buf* buffer = &lx_console.output; - mutex_lock(&buffer->lock); - size_t p = lx_console.erd_pos - 2; - while (p < lx_console.erd_pos && p != buffer->wr_pos && - ((char*)buffer->data)[p] != '\n') { + do { + p = (p + 1) % buffer->size; + } while (p != buffer->wr_pos && ((char*)buffer->data)[p] != '\n'); + return p + (((char*)buffer->data)[p] == '\n'); +} + +size_t +__find_prev_line(size_t start) +{ + size_t p = start - 1; + struct fifo_buf* buffer = &lx_console.output; + do { p--; - } - p++; + } while (p < lx_console.wnd_start && p != buffer->wr_pos && + ((char*)buffer->data)[p] != '\n'); - if (p > lx_console.erd_pos) { - p = 0; + if (p > lx_console.wnd_start) { + return 0; } + return p + 1; +} +void +console_view_up() +{ + struct fifo_buf* buffer = &lx_console.output; + mutex_lock(&buffer->lock); + fifo_set_rdptr(buffer, __find_prev_line(buffer->rd_pos)); buffer->flags |= FIFO_DIRTY; - lx_console.erd_pos = p; mutex_unlock(&buffer->lock); -} -size_t -__find_next_line(size_t start) -{ - size_t p = start; - while (p != lx_console.output.wr_pos && - ((char*)lx_console.output.data)[p] != '\n') { - p = (p + 1) % lx_console.output.size; - } - return p + 1; + console_flush(); } void @@ -141,9 +148,13 @@ console_view_down() struct fifo_buf* buffer = &lx_console.output; mutex_lock(&buffer->lock); - lx_console.erd_pos = __find_next_line(lx_console.erd_pos); + size_t wnd = lx_console.wnd_start; + size_t p = __find_next_line(buffer->rd_pos); + fifo_set_rdptr(buffer, p > wnd ? wnd : p); buffer->flags |= FIFO_DIRTY; mutex_unlock(&buffer->lock); + + console_flush(); } void @@ -156,52 +167,49 @@ console_flush() return; } - tty_flush_buffer(lx_console.output.data, - lx_console.erd_pos, - lx_console.output.wr_pos, - lx_console.output.size); + size_t rdpos_save = lx_console.output.rd_pos; + tty_flush_buffer(&lx_console.output); + fifo_set_rdptr(&lx_console.output, rdpos_save); + lx_console.output.flags &= ~FIFO_DIRTY; } void console_write(struct console* console, uint8_t* data, size_t size) { + struct fifo_buf* fbuf = &console->output; mutex_lock(&console->output.lock); - uint8_t* buffer = console->output.data; - uintptr_t ptr = console->output.wr_pos; - uintptr_t rd_ptr = console->output.rd_pos; + fifo_set_rdptr(fbuf, console->wnd_start); + + uint8_t* buffer = fbuf->data; + uintptr_t ptr = fbuf->wr_pos; + uintptr_t rd_ptr = fbuf->rd_pos; char c; - int lines = 0; int j = 0; for (size_t i = 0; i < size; i++) { c = data[i]; if (!c) { continue; } - buffer[(ptr + j) % console->output.size] = c; - lines += (c == '\n'); + if (c == '\n') { + console->lines++; + } + buffer[(ptr + j) % fbuf->size] = c; j++; } - size = j; - - uintptr_t new_ptr = (ptr + size) % console->output.size; - console->output.wr_pos = new_ptr; - - if (console->lines > TTY_HEIGHT && lines > 0) { - console->output.rd_pos = - __find_next_line((size + rd_ptr) % console->output.size); - } + fifo_set_wrptr(fbuf, (ptr + j) % fbuf->size); - if (new_ptr < ptr + size && new_ptr > rd_ptr) { - console->output.rd_pos = new_ptr; + while (console->lines >= TTY_HEIGHT) { + rd_ptr = __find_next_line(rd_ptr); + console->lines--; } - console->lines += lines; - console->erd_pos = console->output.rd_pos; - console->output.flags |= FIFO_DIRTY; - mutex_unlock(&console->output.lock); + fifo_set_rdptr(&lx_console.output, rd_ptr); + console->wnd_start = rd_ptr; + fbuf->flags |= FIFO_DIRTY; + mutex_unlock(&fbuf->lock); } void diff --git a/lunaix-os/kernel/tty/tty.c b/lunaix-os/kernel/tty/tty.c index d4ac8d0..6db2417 100644 --- a/lunaix-os/kernel/tty/tty.c +++ b/lunaix-os/kernel/tty/tty.c @@ -10,18 +10,21 @@ vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR; vga_attribute tty_theme_color = VGA_COLOR_BLACK; -#define TTY_CLEAR \ - asm volatile("rep stosw" ::"D"(tty_vga_buffer), \ - "c"(TTY_HEIGHT * TTY_WIDTH), \ - "a"(tty_theme_color) \ +inline void +tty_clear() +{ + asm volatile("rep stosw" ::"D"(tty_vga_buffer), + "c"(TTY_HEIGHT * TTY_WIDTH), + "a"(tty_theme_color) : "memory"); +} void tty_init(void* vga_buf) { tty_vga_buffer = (vga_attribute*)vga_buf; - TTY_CLEAR + tty_clear(); io_outb(0x3D4, 0x0A); io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13); @@ -36,23 +39,19 @@ tty_set_theme(vga_attribute fg, vga_attribute bg) tty_theme_color = (bg << 4 | fg) << 8; } -size_t -tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size) +void +tty_flush_buffer(struct fifo_buf* buf) { int x = 0, y = 0; // Clear screen - TTY_CLEAR + tty_clear(); + char chr; int state = 0; int g[2] = { 0, 0 }; vga_attribute current_theme = tty_theme_color; - while (1) { - size_t ptr = pos % buf_size; - if (pos == limit) { - break; - } - char chr = data[pos]; + while (fifo_readone_async(buf, &chr)) { if (state == 0 && chr == '\033') { state = 1; } else if (state == 1 && chr == '[') { @@ -105,10 +104,8 @@ tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size) break; } } - pos++; } tty_set_cursor(x, y); - return pos; } void