aboutsummaryrefslogtreecommitdiff
path: root/kernel/drivers/ps2/mouse.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers/ps2/mouse.c')
-rw-r--r--kernel/drivers/ps2/mouse.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/kernel/drivers/ps2/mouse.c b/kernel/drivers/ps2/mouse.c
new file mode 100644
index 0000000..9b3fa2e
--- /dev/null
+++ b/kernel/drivers/ps2/mouse.c
@@ -0,0 +1,196 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#include <boot.h>
+#include <cpu.h>
+#include <errno.h>
+#include <fs.h>
+#include <interrupts.h>
+#include <mem.h>
+#include <print.h>
+#include <proc.h>
+#include <ps2.h>
+#include <stack.h>
+#include <str.h>
+#include <sys.h>
+
+PROTECTED static struct stack *queue = NULL;
+PROTECTED static u32 dev_id = 0;
+
+static struct event_mouse *event = NULL;
+static char mouse_cycle = 0;
+static char mouse_byte[3] = { 0 };
+static void mouse_handler(struct regs *r)
+{
+ UNUSED(r);
+ switch (mouse_cycle) {
+ case 0:
+ mouse_byte[0] = ps2_read_data();
+ if (((mouse_byte[0] >> 3) & 1) == 1)
+ mouse_cycle++;
+ else
+ mouse_cycle = 0;
+ break;
+ case 1:
+ mouse_byte[1] = ps2_read_data();
+ mouse_cycle++;
+ break;
+ case 2:
+ mouse_byte[2] = ps2_read_data();
+
+ event = malloc(sizeof(*event));
+ event->magic = MOUSE_MAGIC;
+ event->diff_x = mouse_byte[1];
+ event->diff_y = mouse_byte[2];
+ event->but1 = mouse_byte[0] & 1;
+ event->but2 = (mouse_byte[0] >> 1) & 1;
+ event->but3 = (mouse_byte[0] >> 2) & 1;
+ stack_push_bot(queue, event);
+ mouse_cycle = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+#define MOUSE_WAIT_OUT 0
+#define MOUSE_WAIT_IN 1
+CLEAR static void mouse_serial_wait(u8 in)
+{
+ u32 time_out = 100000;
+ if (in) {
+ while (time_out--)
+ if (ps2_read_status().in_full)
+ return;
+ return;
+ } else {
+ while (time_out--)
+ if (ps2_read_status().out_full)
+ return;
+ return;
+ }
+}
+
+CLEAR static void mouse_serial_write(u8 data)
+{
+ mouse_serial_wait(MOUSE_WAIT_IN);
+ ps2_write_command(0xd4);
+ mouse_serial_wait(MOUSE_WAIT_IN);
+ ps2_write_data(data);
+}
+
+CLEAR static u8 mouse_serial_read(void)
+{
+ mouse_serial_wait(MOUSE_WAIT_OUT);
+ return ps2_read_data();
+}
+
+static res mouse_ready(void)
+{
+ return !stack_empty(queue);
+}
+
+static res mouse_read(void *buf, u32 offset, u32 count, struct vfs_dev *dev)
+{
+ (void)dev;
+ if (stack_empty(queue))
+ return -EINVAL;
+
+ struct event_mouse *e = stack_pop(queue);
+ memcpy_user(buf, (u8 *)e + offset, MIN(count, sizeof(*e)));
+ free(e);
+ return MIN(count, sizeof(*e));
+}
+
+CLEAR void ps2_mouse_install(void)
+{
+ u8 status;
+
+ // Enable auxiliary mouse device
+ mouse_serial_wait(MOUSE_WAIT_IN);
+ ps2_write_command(0xa8);
+
+ // Enable interrupts
+ mouse_serial_wait(MOUSE_WAIT_IN);
+ ps2_write_command(0x20);
+ mouse_serial_wait(MOUSE_WAIT_OUT);
+ status = ps2_read_data() | 3;
+ mouse_serial_wait(MOUSE_WAIT_IN);
+ ps2_write_command(0x60);
+ mouse_serial_wait(MOUSE_WAIT_IN);
+ ps2_write_data(status);
+
+ // Use default settings
+ mouse_serial_write(0xf6);
+ mouse_serial_read();
+
+ // Enable mousewheel
+ mouse_serial_write(0xf2);
+ mouse_serial_read();
+ mouse_serial_read();
+ mouse_serial_write(0xf3);
+ mouse_serial_read();
+ mouse_serial_write(200);
+ mouse_serial_read();
+ mouse_serial_write(0xf3);
+ mouse_serial_read();
+ mouse_serial_write(100);
+ mouse_serial_read();
+ mouse_serial_write(0xf3);
+ mouse_serial_read();
+ mouse_serial_write(80);
+ mouse_serial_read();
+ mouse_serial_write(0xf2);
+ mouse_serial_read();
+ status = (u8)mouse_serial_read();
+ if (status == 3) {
+ }
+ /* printf("Scrollwheel support!\n"); */
+
+ // Activate 4th and 5th mouse buttons
+ mouse_serial_write(0xf2);
+ mouse_serial_read();
+ mouse_serial_read();
+ mouse_serial_write(0xf3);
+ mouse_serial_read();
+ mouse_serial_write(200);
+ mouse_serial_read();
+ mouse_serial_write(0xf3);
+ mouse_serial_read();
+ mouse_serial_write(200);
+ mouse_serial_read();
+ mouse_serial_write(0xf3);
+ mouse_serial_read();
+ mouse_serial_write(80);
+ mouse_serial_read();
+ mouse_serial_write(0xf2);
+ mouse_serial_read();
+ status = (u8)mouse_serial_read();
+ if (status == 4) {
+ }
+ /* printf("4th and 5th mouse button support!\n"); */
+
+ /* TODO: Fix mouse laggyness
+ mouse_serial_write(0xE8);
+ mouse_serial_read();
+ mouse_serial_write(0x03);
+ mouse_serial_read();
+ mouse_serial_write(0xF3);
+ mouse_serial_read();
+ mouse_serial_write(200);
+ mouse_serial_read(); */
+
+ // Enable mouse
+ mouse_serial_write(0xf4);
+ mouse_serial_read();
+
+ // Setup the mouse handler
+ irq_install_handler(12, mouse_handler);
+
+ queue = stack_new();
+ struct vfs_dev *dev = zalloc(sizeof(*dev));
+ dev->name = strdup("mouse");
+ dev->type = DEV_CHAR;
+ dev->read = mouse_read;
+ /* device_add(dev); */
+ dev_id = dev->id;
+}