From f56aa2f7e4b8e6430e123f714507032a33955a09 Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Fri, 18 May 2012 13:09:28 +0200 Subject: The keyboard handling, it's getting better. + Funny screenshot. --- src/include/tce/syscalls.h | 2 +- src/kernel/core/kmain.cpp | 1 + src/kernel/dev/display.h | 1 - src/kernel/dev/keyboard.cpp | 36 +++++++++++++--- src/kernel/dev/keyboard.h | 7 +++ src/kernel/ui/vt.cpp | 101 ++++++++++++++++++++++++++++++++++++++------ src/kernel/ui/vt.h | 16 ++++++- src/kernel/vfs/node.cpp | 7 ++- src/kernel/vfs/node.h | 3 ++ src/user/test/main.c | 26 ++++++++++-- 10 files changed, 170 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/include/tce/syscalls.h b/src/include/tce/syscalls.h index 6c67523..e14768f 100644 --- a/src/include/tce/syscalls.h +++ b/src/include/tce/syscalls.h @@ -28,7 +28,7 @@ // ERRORS -#define E_NOT_IMPLEMENTED -1 +#define E_NOT_IMPLEMENTED -1 // could also mean that your request is nonsense #define E_NOT_FOUND -2 #define E_INVALID_FD -3 #define E_TOO_SHORT -4 // not enough space for data to be copied to diff --git a/src/kernel/core/kmain.cpp b/src/kernel/core/kmain.cpp index f745fdf..314c033 100644 --- a/src/kernel/core/kmain.cpp +++ b/src/kernel/core/kmain.cpp @@ -71,6 +71,7 @@ extern "C" void kmain(multiboot_info_t* mbd, int32_t magic) { // Init devices kbd = new ps2kbd(dot_dev); dot_dev->add_child("ps2kbd", kbd); + kbd->outputTo(ke_vt); // Load modules *ke_vt << "Loading modules :\n"; diff --git a/src/kernel/dev/display.h b/src/kernel/dev/display.h index 04a6d67..6960b7d 100644 --- a/src/kernel/dev/display.h +++ b/src/kernel/dev/display.h @@ -24,7 +24,6 @@ class display : public node { connected_vt = 0; } virtual ~display() {} - virtual display* as_display() { return this; } virtual int text_w() = 0; diff --git a/src/kernel/dev/keyboard.cpp b/src/kernel/dev/keyboard.cpp index 479996d..ce8e77b 100644 --- a/src/kernel/dev/keyboard.cpp +++ b/src/kernel/dev/keyboard.cpp @@ -14,7 +14,7 @@ int ctrlkeys[] = { /* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KB_ENTER, KB_RCTRL, 0, 0, /* 0xA0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 0xB0 */ 0, 0, 0, 0, 0, 0, 0, KB_PRTSCN, KB_ALTGR, 0, 0, 0, 0, 0, 0, 0, +/* 0xB0 */ 0, 0, 0, 0, 0, KB_KPSLASH, 0, KB_PRTSCN, KB_ALTGR, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 */ 0, 0, 0, 0, 0, 0, 0, KB_HOME, KB_UP, KB_PGUP, 0, KB_LEFT, 0, KB_RIGHT, 0, KB_END, /* 0xD0 */ KB_DOWN, KB_PGDOWN, KB_INS, KB_DEL, 0, 0, 0, 0, 0, 0, 0, KB_LSUPER, KB_RSUPER, KB_MENU, 0, 0, /* 0xE0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -90,11 +90,13 @@ void keyboard::handle(int scancode, bool pressed) { kp.scancode = scancode; kp.pressed = pressed; kp.command = ctrlkeys[scancode]; + kp.character = 0; if (kp.command == 0) kp.command = ctrlkeys[scancode & 0x7F]; if (kp.command == 0) { kp.command = (alt ? KB_CMD_ALT : 0) | (ctrl ? KB_CMD_CTRL : 0); - if (shift xor caps) { + scancode = scancode & 0x7F; + if ((shift || caps) && !(shift && caps)) { if (altgr) { kp.character = km->shiftaltgr[scancode]; } else { @@ -126,13 +128,13 @@ void keyboard::handle(int scancode, bool pressed) { ctrl = pressed; } else if (kp.command == KB_LSHIFT || kp.command == KB_RSHIFT) { shift = pressed; - } else if (kp.command == KB_CAPSLOCK) { + } else if (kp.command == KB_CAPSLOCK && kp.pressed) { caps = !caps; updateLeds(); - } else if (kp.command == KB_NUMLOCK) { + } else if (kp.command == KB_NUMLOCK && kp.pressed) { num = !num; updateLeds(); - } else if (kp.command == KB_SCRLLOCK) { + } else if (kp.command == KB_SCRLLOCK && kp.pressed) { scroll = !scroll; updateLeds(); } else if (kp.command == KB_TAB) { @@ -141,10 +143,30 @@ void keyboard::handle(int scancode, bool pressed) { kp.character = '\b'; } else if (kp.command == KB_ENTER) { kp.character = '\n'; + } else if (kp.command == KB_KPSLASH) { + kp.character = '/'; + kp.command = 0; } // process keypress - if (kp.character && kp.pressed) { - ke_vt->put(kp.character); + if (output != 0) { + output->keyboardInput(kp); + } else { + // TODO: enable reading directly keypresses from keyboard device } } + +void keyboard::outputTo(vt *vt) { + output = vt; +} + +int keyboard::link(node* to, int mode) { + if (mode == LM_OUTPUT_TO) { + vt *v = to->as_vt(); + if (v != 0) { + outputTo(v); + return 0; + } + } + return E_NOT_IMPLEMENTED; +} diff --git a/src/kernel/dev/keyboard.h b/src/kernel/dev/keyboard.h index 61fdbe7..4fd0b1d 100644 --- a/src/kernel/dev/keyboard.h +++ b/src/kernel/dev/keyboard.h @@ -58,6 +58,7 @@ #define KB_LSUPER 50 #define KB_RSUPER 51 #define KB_MENU 52 +#define KB_KPSLASH 53 #define KB_CMD_ALT 64 // any command with alt will have this flag #define KB_CMD_CTRL 128 // any command with controll will have this flag @@ -77,9 +78,11 @@ struct keymap { int shiftaltgr[128]; }; +class vt; class keyboard : public node { private: keymap* km; + vt *output; protected: bool num, caps, scroll; @@ -91,8 +94,12 @@ class keyboard : public node { public: keyboard(node* parent); virtual ~keyboard() {} + + void outputTo(vt *vt); void handle(int scancode, bool pressed); + + int link(node* to, int mode); }; #endif diff --git a/src/kernel/ui/vt.cpp b/src/kernel/ui/vt.cpp index cbb29f7..48a2da4 100644 --- a/src/kernel/ui/vt.cpp +++ b/src/kernel/ui/vt.cpp @@ -9,6 +9,9 @@ vt::vt(node* parent, int ww, int hh) : node(parent, FT_TERMINAL) { bgcolor = TC_BLACK; output = 0; cursor_visible = true; + + kbd_buffer_filled = 0; + kbd_waiter = 0; text = 0; if (w != 0 && h != 0) { @@ -27,18 +30,20 @@ void vt::put_at(int l, int c, int ch) { void vt::put(int c) { if (text == 0) return; - if (c == '\b' && csr_c != 0) { + if (c == '\b' && csr_c != 0) { // backspace csr_c--; put_at(csr_l, csr_c, ' '); - } else if (c == '\t') { + } else if (c == '\t') { // tab int csr_nc = (csr_c + 8) & ~(8 - 1); for (int i = csr_c; i < csr_nc && i < w; i++) put_at(csr_l, i, ' '); csr_c = csr_nc; - } else if (c == '\r') { + } else if (c == '\r') { // carriage return csr_c = 0; - } else if (c == '\n') { + } else if (c == '\n') { // new line csr_c = 0; csr_l++; + } else if (c == '\f') { // form feed (new page) + clear(); } else if (c >= ' ') { put_at(csr_l, csr_c, c); csr_c++; @@ -73,12 +78,6 @@ void vt::clear() { csr_c = csr_l = 0; } -void vt::writeStr(char *s) { - while (*s) { - put(*(s++)); - } -} - void vt::writeHex(uint32_t v) { int i; @@ -116,11 +115,11 @@ void vt::writeDec(int v) { } } -// ******* +// *************** INTERACTION -int vt::outputTo(display *display) { +void vt::outputTo(display *display) { output = display; - if (output == 0) return 0; + if (output == 0) return; output->connected_vt = this; if (output->text_w() != w || output->text_h() != h) { @@ -149,15 +148,89 @@ int vt::outputTo(display *display) { } } } - return 0; } +void vt::keyboardInput(keypress kp) { + // convert to sequence of chars + int n = 0; + char b[8]; + + if (kp.character >= 0x80) kp.character = '?'; // todo some day : unicode + + if ((kp.command == 0 || kp.command == KB_ENTER || kp.command == KB_TAB || kp.command == KB_BACKSPACE) + && kp.character != 0 && kp.pressed) { + b[n++] = (char)kp.character; + } else if (kp.command == KB_CMD_ALT && kp.character >= 64 && kp.character <= 126 && kp.pressed) { + b[n++] = 27; + b[n++] = kp.character; + } + if (n == 0) return; + if (kbd_buffer_filled + n > KBD_BUFFER_SIZE) goto wake_up; + for (int i = 0; i < n; i++) { + kbd_buffer[kbd_buffer_filled++] = b[i]; + } + + wake_up: + if (kbd_waiter != 0) { + thread *w = kbd_waiter; + kbd_waiter = 0; + w->wakeUp(); + } +} + +// ********************* SYSCALLS + int vt::write(size_t offset, size_t len, char* buffer) { // ignore offset + // TODO: ANSI escape sequences + // todo some day : unicode for (unsigned i = 0; i < len; i++) put(buffer[i]); return len; } +int vt::read(size_t offset, size_t len, char* buffer) { + // ignore offset + + unsigned c = 0; + while (true) { + bool end = false; + if (kbd_buffer_filled > 0) { + int r = 0; + for (; r < kbd_buffer_filled; r++) { + if (kbd_buffer[r] == '\b') { + if (c > 0) { + c--; + put('\b'); + } + } else { + buffer[c] = kbd_buffer[r]; + put(buffer[c]); + if (buffer[c] == '\n' || buffer[c] == 27) end = true; + c++; + } + if (c == len) break; + } + memcpy(kbd_buffer + r, kbd_buffer, (kbd_buffer_filled - r)); + kbd_buffer_filled -= r; + } + if (end || c == len) return c; + + kbd_waiter = current_thread; + thread_goInactive(); + } +} + size_t vt::get_size() { return ((w << 16) + h); } + +int vt::link(node* to, int mode) { + if (mode == LM_OUTPUT_TO) { + display *d = to->as_display(); + if (d != 0) { + outputTo(d); + return 0; + } + } + return E_NOT_IMPLEMENTED; +} diff --git a/src/kernel/ui/vt.h b/src/kernel/ui/vt.h index ebafe5f..b26e95a 100644 --- a/src/kernel/ui/vt.h +++ b/src/kernel/ui/vt.h @@ -3,6 +3,9 @@ #include #include +#include + +#define KBD_BUFFER_SIZE 256 struct vt_char { int ch; @@ -18,15 +21,21 @@ class vt : public node { void put_at(int l, int c, int ch); bool cursor_visible; + int kbd_buffer_filled; + char kbd_buffer[KBD_BUFFER_SIZE]; + thread *kbd_waiter; + public: uint8_t fgcolor, bgcolor; vt(node* parent, int w, int h); + virtual ~vt() {} + virtual vt* as_vt() { return this; } // internal use void put(int c); void clear(); - void writeStr(char* str); + void writeStr(char* str) { write(0, strlen(str), str); } void writeHex(uint32_t v); void writeDec(int v); // shortcuts @@ -35,10 +44,13 @@ class vt : public node { vt& operator<< (int i) { writeDec(i); return *this; } - int outputTo(display *display); + void outputTo(display *display); + void keyboardInput(keypress kp); virtual int write(size_t offset, size_t len, char* buffer); + virtual int read(size_t offset, size_t len, char* buffer); // get keyboard input virtual size_t get_size(); + virtual int link(node* to, int mode); }; extern vt *ke_vt; diff --git a/src/kernel/vfs/node.cpp b/src/kernel/vfs/node.cpp index e174bd6..08c7817 100644 --- a/src/kernel/vfs/node.cpp +++ b/src/kernel/vfs/node.cpp @@ -2,7 +2,6 @@ #include "vdir.h" int node::open(process *proc, int mode) { - //TODO : permission checks return 0; // ok } @@ -62,6 +61,7 @@ static FILE i_open(node* r, char* filename, int mode) { node* f = vfs_find(r, filename); if (f == 0) return E_NOT_FOUND; //TODO : different actions depending on open mode + //TODO : permission checks int e = f->open(current_process, mode); if (e != 0) return e; return current_process->fd.add(f); @@ -118,5 +118,8 @@ int write(FILE file, size_t offset, size_t len, char* buffer) { } int link(char* from, char* to, int mode) { - return E_NOT_IMPLEMENTED; + node *f1 = vfs_find(root, from); + if (f1 == 0) return E_NOT_FOUND; + node *f2 = (to == 0 ? 0 : vfs_find(root, to)); + return f1->link(f2, mode); } diff --git a/src/kernel/vfs/node.h b/src/kernel/vfs/node.h index 9005d55..b0ade41 100644 --- a/src/kernel/vfs/node.h +++ b/src/kernel/vfs/node.h @@ -7,6 +7,7 @@ #include class display; +class vt; class node { public: @@ -25,9 +26,11 @@ class node { virtual node* get_child(char* name) { return 0; } virtual int add_child(char* name, node *child) { return E_NOT_IMPLEMENTED; } virtual size_t get_size() { return 0; } + virtual int link(node* other, int mode) { return E_NOT_IMPLEMENTED; } // kind of like dynamic_cast'int these things virtual display *as_display() { return 0; } + virtual vt *as_vt() { return 0; } }; void vfs_setup(); diff --git a/src/user/test/main.c b/src/user/test/main.c index a7df667..e7a6b4f 100644 --- a/src/user/test/main.c +++ b/src/user/test/main.c @@ -93,9 +93,29 @@ int main() { close(f); } - printk(" -> Now sleeping, forever and ever...\n"); - while(1) { - thread_sleep(1000); + printk(" -> YOUR SHELL IS STARTING UP, SIR.\n"); + f = open("/.ui/klog", 0); + if (f <= 0) { + printk(" -> Error #"); printk_int(f); printk(" - too bad. Exiting.\n"); + } else { + char *s = "Hello, writing from your opened file!\n"; + write(f, 0, strlen(s), s); + while (1) { + char *s = " > "; + write(f, 0, strlen(s), s); + + char buffer[256]; + int l = read(f, 0, 255, buffer); + buffer[l] = 0; + if (buffer[l-1] == '\n') { + char *s = "You said: "; + write(f, 0, strlen(s), s); + write(f, 0, l, buffer); + } else { + char *s = "oops\n"; + write(f, 0, strlen(s), s); + } + } } return 0; -- cgit v1.2.3