summaryrefslogtreecommitdiff
path: root/kernel/drivers/mouse.c
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-30 22:12:14 +0100
committerAnton Kling <anton@kling.gg>2023-10-31 00:18:38 +0100
commit8a9208612eec8ddae4c418485d848ecfa0613699 (patch)
tree2f4b29200c2f0c19ae52f45bdb9b38a41b356e30 /kernel/drivers/mouse.c
parentca76600acc8bf7a02346efa5bd8f17072210ec01 (diff)
Meta: Move kernel and userland to their own folders.
This is to allow both the kernel and the userland to share certain header files and to make the folder structure a bit more clear.
Diffstat (limited to 'kernel/drivers/mouse.c')
-rw-r--r--kernel/drivers/mouse.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c
new file mode 100644
index 0000000..23619a0
--- /dev/null
+++ b/kernel/drivers/mouse.c
@@ -0,0 +1,144 @@
+#include <cpu/idt.h>
+#include <drivers/mouse.h>
+#include <fs/devfs.h>
+#include <fs/fifo.h>
+#include <fs/vfs.h>
+#include <stdint.h>
+
+uint8_t mouse_cycle = 0; // unsigned char
+uint8_t mouse_uint8_t[3]; // signed char
+uint8_t mouse_x = 0; // signed char
+uint8_t mouse_y = 0; // signed char
+vfs_inode_t *mouse_inode;
+vfs_fd_t *mouse_fd;
+
+struct mouse_event {
+ uint8_t buttons;
+ uint8_t x;
+ uint8_t y;
+};
+
+int fs_mouse_write(uint8_t *buffer, uint64_t offset, uint64_t len,
+ vfs_fd_t *fd) {
+ int rc = fifo_object_write(buffer, offset, len, fd->inode->internal_object);
+ FIFO_FILE *f = fd->inode->internal_object;
+ mouse_inode->has_data = f->has_data;
+ return rc;
+}
+
+int fs_mouse_read(uint8_t *buffer, uint64_t offset, uint64_t len,
+ vfs_fd_t *fd) {
+ FIFO_FILE *f = fd->inode->internal_object;
+ if (!mouse_inode->has_data)
+ return 0;
+ int rc = fifo_object_read(buffer, offset, len, f);
+ mouse_inode->has_data = f->has_data;
+ return rc;
+}
+
+void add_mouse(void) {
+ mouse_inode = devfs_add_file("/mouse", fs_mouse_read, fs_mouse_write, NULL, 0,
+ 0, FS_TYPE_CHAR_DEVICE);
+ mouse_inode->internal_object = create_fifo_object();
+ // Don't look at this
+ int fd = vfs_open("/dev/mouse", O_RDWR, 0);
+ mouse_fd = get_vfs_fd(fd);
+ get_current_task()->file_descriptors[fd] = NULL;
+}
+
+__attribute__((interrupt)) void what(registers_t *r) { EOI(0xe); }
+
+__attribute__((interrupt)) void int_mouse(registers_t *r) {
+ (void)r;
+ EOI(12);
+ switch (mouse_cycle) {
+ case 0:
+ mouse_uint8_t[0] = inb(0x60);
+ if(!(mouse_uint8_t[0] & (1 << 3))) {
+ mouse_cycle = 0;
+ return;
+ }
+ mouse_cycle++;
+ break;
+ case 1:
+ mouse_uint8_t[1] = inb(0x60);
+ mouse_cycle++;
+ break;
+ case 2:
+ mouse_uint8_t[2] = inb(0x60);
+ mouse_x = mouse_uint8_t[1];
+ mouse_y = mouse_uint8_t[2];
+ mouse_cycle = 0;
+ struct mouse_event e;
+ e.buttons = mouse_uint8_t[0];
+ e.x = mouse_x;
+ e.y = mouse_y;
+ raw_vfs_pwrite(mouse_fd, &e, sizeof(e), 0);
+ break;
+ }
+}
+
+void mouse_wait(uint8_t a_type) {
+ uint32_t _time_out = 100000;
+ if (a_type == 0) {
+ while (_time_out--) {
+ if ((inb(0x64) & 1) == 1) {
+ return;
+ }
+ }
+ return;
+ } else {
+ while (_time_out--) {
+ if ((inb(0x64) & 2) == 0) {
+ return;
+ }
+ }
+ return;
+ }
+}
+
+void mouse_write(uint8_t a_write) {
+ // Wait to be able to send a command
+ mouse_wait(1);
+ // Tell the mouse we are sending a command
+ outb(0x64, 0xD4);
+ // Wait for the final part
+ mouse_wait(1);
+ // Finally write
+ outb(0x60, a_write);
+}
+
+uint8_t mouse_read() {
+ // Get's response from mouse
+ mouse_wait(0);
+ return inb(0x60);
+}
+
+void install_mouse(void) {
+ uint8_t _status; // unsigned char
+ asm("cli");
+ // Enable the auxiliary mouse device
+ mouse_wait(1);
+ outb(0x64, 0xA8);
+
+ // Enable the interrupts
+ mouse_wait(1);
+ outb(0x64, 0x20);
+ mouse_wait(0);
+ _status = (inb(0x60) | 2);
+ mouse_wait(1);
+ outb(0x64, 0x60);
+ mouse_wait(1);
+ outb(0x60, _status);
+
+ // Tell the mouse to use default settings
+ mouse_write(0xF6);
+ mouse_read(); // Acknowledge
+
+ // Enable the mouse
+ mouse_write(0xF4);
+ mouse_read(); // Acknowledge
+
+ install_handler(int_mouse, INT_32_INTERRUPT_GATE(0x3), 12 + 0x20);
+ install_handler(what, INT_32_INTERRUPT_GATE(0x3), 0xe + 0x20);
+}