summaryrefslogtreecommitdiff
path: root/kbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'kbd.c')
-rw-r--r--kbd.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/kbd.c b/kbd.c
new file mode 100644
index 0000000..a4dd381
--- /dev/null
+++ b/kbd.c
@@ -0,0 +1,51 @@
+#include "types.h"
+#include "x86.h"
+#include "defs.h"
+#include "kbd.h"
+
+int
+kbd_getc(void)
+{
+ static uint shift;
+ static uchar *charcode[4] = {
+ normalmap, shiftmap, ctlmap, ctlmap
+ };
+ uint st, data, c;
+
+ st = inb(KBSTATP);
+ if((st & KBS_DIB) == 0)
+ return -1;
+ data = inb(KBDATAP);
+
+ if(data == 0xE0) {
+ shift |= E0ESC;
+ return 0;
+ } else if(data & 0x80) {
+ // Key released
+ data = (shift & E0ESC ? data : data & 0x7F);
+ shift &= ~(shiftcode[data] | E0ESC);
+ return 0;
+ } else if(shift & E0ESC) {
+ // Last character was an E0 escape; or with 0x80
+ data |= 0x80;
+ shift &= ~E0ESC;
+ }
+
+ shift |= shiftcode[data];
+ shift ^= togglecode[data];
+ c = charcode[shift & (CTL | SHIFT)][data];
+ if(shift & CAPSLOCK) {
+ if('a' <= c && c <= 'z')
+ c += 'A' - 'a';
+ else if('A' <= c && c <= 'Z')
+ c += 'a' - 'A';
+ }
+ return c;
+}
+
+void
+kbd_intr(void)
+{
+ console_intr(kbd_getc);
+}
+