feat: a pseudo shell environment for basic interacting and testing purpose
[lunaix-os.git] / lunaix-os / kernel / lxconsole.c
index 785330a4aa4b5d78b4ea9e06421281b55b48ea2f..77949c897822c699c733fc03ac683b493e48a44f 100644 (file)
@@ -1,5 +1,6 @@
 #include <klibc/string.h>
 #include <lunaix/device.h>
+#include <lunaix/input.h>
 #include <lunaix/keyboard.h>
 #include <lunaix/lxconsole.h>
 #include <lunaix/mm/pmm.h>
@@ -17,32 +18,49 @@ __tty_write(struct device* dev, void* buf, size_t offset, size_t len);
 int
 __tty_read(struct device* dev, void* buf, size_t offset, size_t len);
 
+static waitq_t lx_reader;
+static volatile char key;
+
+int
+__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) {
+            console_view_up();
+        } else if (keycode == KEY_DOWN) {
+            console_view_down();
+        }
+        goto done;
+    }
+    if ((keycode & 0xff00) > KEYPAD) {
+        goto done;
+    }
+
+    key = (char)(keycode & 0x00ff);
+
+    pwake_all(&lx_reader);
+
+done:
+    return INPUT_EVT_NEXT;
+}
+
 void
 lxconsole_init()
 {
     memset(&lx_console, 0, sizeof(lx_console));
-    fifo_init(&lx_console.output, VGA_BUFFER_VADDR + 0x1000, 8192, 0);
+    fifo_init(&lx_console.output, vzalloc(8192), 8192, 0);
     fifo_init(&lx_console.input, valloc(4096), 4096, 0);
 
-    // FIXME use valloc to allocate console buffer.
-    // In doing this, the console buffer can only be accessed from kernel mode
-    //  any direct write to this buffer from user land should be purged!
-
-    // 分配控制台缓存
-    for (size_t i = 0; i < PG_ALIGN(lx_console.output.size); i += PG_SIZE) {
-        uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
-        vmm_set_mapping(PD_REFERENCED,
-                        (uintptr_t)lx_console.output.data + i,
-                        pa,
-                        PG_PREM_URW,
-                        0);
-    }
-
     lx_console.flush_timer = NULL;
 
     struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
     tty_dev->write = __tty_write;
     tty_dev->read = __tty_read;
+
+    waitq_init(&lx_reader);
+    input_add_listener(__lxconsole_listener);
 }
 
 int
@@ -55,7 +73,6 @@ __tty_write(struct device* dev, void* buf, size_t offset, size_t len)
 int
 __tty_read(struct device* dev, void* buf, size_t offset, size_t len)
 {
-    struct kdb_keyinfo_pkt keyevent;
     struct console* console = (struct console*)dev->underlay;
 
     size_t count = fifo_read(&console->input, buf, len);
@@ -64,30 +81,16 @@ __tty_read(struct device* dev, void* buf, size_t offset, size_t len)
     }
 
     while (count < len) {
-        // FIXME RACE!
-        //  Consider two process that is polling the input key simultaneously.
-        //  When a key is arrived, one of the processes will win the race and
-        //  swallow it (advancing the key buffer pointer)
-        if (!kbd_recv_key(&keyevent)) {
-            sched_yieldk();
-            continue;
-        }
-        if (!(keyevent.state & KBD_KEY_FPRESSED)) {
-            continue;
-        }
-        if ((keyevent.keycode & 0xff00) > KEYPAD) {
-            continue;
-        }
+        pwait(&lx_reader);
 
-        char c = (char)(keyevent.keycode & 0x00ff);
-        if (c == 0x08) {
+        if (key == 0x08) {
             if (fifo_backone(&console->input)) {
-                console_write_char(c);
+                console_write_char(key);
             }
             continue;
         }
-        console_write_char(c);
-        if (!fifo_putone(&console->input, c) || c == '\n') {
+        console_write_char(key);
+        if (!fifo_putone(&console->input, key) || key == '\n') {
             break;
         }
     }