summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/core/kmain.cpp1
-rw-r--r--src/kernel/dev/display.h1
-rw-r--r--src/kernel/dev/keyboard.cpp36
-rw-r--r--src/kernel/dev/keyboard.h7
-rw-r--r--src/kernel/ui/vt.cpp101
-rw-r--r--src/kernel/ui/vt.h16
-rw-r--r--src/kernel/vfs/node.cpp7
-rw-r--r--src/kernel/vfs/node.h3
8 files changed, 146 insertions, 26 deletions
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 <vfs/node.h>
#include <dev/display.h>
+#include <dev/keyboard.h>
+
+#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 <task/task.h>
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();