BarryServer : Git

All the code for all my projects
// BarryServer : Git / Orion / commit / 1628fcfdfdf2978ed9ccac96ee7d13bb3dc43a01 / drivers / keyboard

// Related

Orion

Barry Keyboard/Mouse drivers + POSIX names for structs 1628fcf (2 years, 4 months ago)
diff --git a/drivers/keyboard/keyboard.c b/drivers/keyboard/keyboard.c
new file mode 100644
index 0000000..5ef3c6f
--- /dev/null
+++ b/drivers/keyboard/keyboard.c
@@ -0,0 +1,108 @@
+/*
+ * This file implements a keyboard driver.  It generates the /dev/kbd device
+ * file, which can be read and returns a structure of the keyboard data.  This
+ * driver produces raw keyboard data, not parsed text.
+ */
+
+#include <sys/kbd.h>
+#include "../drivers.h"
+#include "../../task/task.h"
+#include "../../proc/proc.h"
+#include "../../io.h"
+
+void tty_keypress(unsigned char key);
+size_t kbd_read(File *file, char *buf, size_t size, off_t offset);
+
+FileOps kbdFileOps = {
+	.read = kbd_read,
+};
+
+Driver kbdDriver = {
+	.major = 10,
+	.ops = &kbdFileOps,
+	.next = NULL,
+};
+
+TaskQueue keyWait;
+
+/* Ring buffer for keys */
+struct KeyBuffer {
+	int start, end;
+	char key[1024];
+} keyBuf;
+
+/* Add a key to the key buffer */
+static void
+add_to_buf(char key)
+{
+	/* No more space in buffer */
+	int start = (keyBuf.start + sizeof(keyBuf.key) - 1)
+	          % sizeof(keyBuf.key);
+	if (keyBuf.end == start)
+		return;
+
+	keyBuf.key[keyBuf.end] = key;
+	keyBuf.end++;
+	keyBuf.end %= sizeof(keyBuf.key);
+}
+
+/* Get a key from the key buffer */
+static char
+get_from_buf(void)
+{
+	/* Nothing to read */
+	if (keyBuf.start == keyBuf.end)
+		return 0x00;
+
+	char key = keyBuf.key[keyBuf.start];
+	keyBuf.start++;
+	keyBuf.start %= sizeof(keyBuf.key);
+	return key;
+}
+
+/* Handle the keyboard interrupt */
+static void
+keyboard_handler(InterruptFrame *frame)
+{
+	unsigned char key;
+	int i;
+	for (i = 0; i < 1000; i++) {
+		if ((inb(0x64) & 1) == 0)
+			continue;
+		key = inb(0x60);
+		break;
+	}
+	if (i == 1000)
+		return;
+	add_to_buf(key);
+	tty_keypress(key);
+
+	for (Task *tmp = keyWait.start; tmp; tmp = tmp->next)
+		unblock_task(pop_from_queue(&keyWait));
+}
+
+/* Initialise the keyboard */
+void
+init_kbd(void)
+{
+	register_driver(&kbdDriver);
+	mknod("/dev/kbd", S_IFCHR | 0666, MKDEV(kbdDriver.major, 0));
+	register_interrupt(1, keyboard_handler);
+}
+
+size_t
+kbd_read(File *file, char *buf, size_t size, off_t offset)
+{
+	char c;
+	size_t count = 0;
+	while (count < size) {
+		c = get_from_buf();
+		if (!c) {
+			add_to_queue(&keyWait, current);
+			block_task(WAITING_FOR_IO);
+		}
+		*(buf + count) = c;
+		count++;
+	}
+	return count;
+}