summaryrefslogtreecommitdiff
path: root/kernel/src/drivers/ps2mouse.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/drivers/ps2mouse.c')
-rw-r--r--kernel/src/drivers/ps2mouse.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/kernel/src/drivers/ps2mouse.c b/kernel/src/drivers/ps2mouse.c
new file mode 100644
index 0000000..01e10cc
--- /dev/null
+++ b/kernel/src/drivers/ps2mouse.c
@@ -0,0 +1,89 @@
+#include <panic.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys.h>
+
+#include "print.h"
+#include "ps2mouse.h"
+#include "drivers/ps2ctrl.h"
+#include "interrupt/pic.h"
+
+static bool is_init = false;
+
+static struct MouseEvent last_event;
+static uint8_t first_b, second_b, third_b;
+
+void ps2mouse_init(void) {
+
+ debugk("Loading PS/2 Mouse");
+
+ is_init = false;
+ pic_mask(12);
+
+ uint8_t result;
+
+ ps2ctrl_set_port2();
+ ps2ctrl_out_data(0xFF);
+ result = ps2ctrl_in();
+ if (result != 0xFA) {
+ errork("Failed to reset PS/2 mouse: expected 0xFA, got 0x%X", result);
+ return;
+ }
+ result = ps2ctrl_in();
+ if (result != 0xAA) {
+ errork("Failed to reset PS/2 mouse: expected 0xAA, got 0x%X", result);
+ return;
+ }
+
+ ps2ctrl_set_port2();
+ ps2ctrl_out_data(0xF4);
+
+ pic_unmask(12);
+ is_init = true;
+
+ succek("PS/2 Mouse has has been loaded");
+}
+
+static uint8_t packet_num = 0;
+void ps2mouse_recv(void) {
+ if (!ps2ctrl_is_init() || !is_init) {
+ inb(0x60);
+ return;
+ }
+
+ uint8_t packet = ps2ctrl_in();
+ switch (packet_num) {
+ case 0:
+ first_b = packet;
+ break;
+ case 1:
+ second_b = packet;
+ break;
+ case 2: {
+ third_b = packet;
+
+ int state, d;
+ state = first_b;
+ d = second_b;
+ last_event.relx = d - ((state << 4) & 0x100);
+ d = third_b;
+ last_event.rely = d - ((state << 3) & 0x100);
+
+ last_event.lmb = first_b & 0x01;
+ last_event.rmb = first_b & 0x02;
+ last_event.mmb = first_b & 0x04;
+ last_event.updated = true;
+ break;
+ }
+ }
+
+ packet_num += 1;
+ packet_num %= 3;
+
+}
+
+struct MouseEvent ps2mouse_get(void) {
+ struct MouseEvent event = last_event;
+ last_event.updated = false;
+ return event;
+}