aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2017-04-24 16:04:48 +0200
committerAlex Auvolat <alex@adnab.me>2017-04-24 16:04:48 +0200
commit978b3234a04f11f959f603db4756253278ca65df (patch)
treeb2c027612168892d9a7477fa0f9cd64228bdf089
parent575b140a57e2bb86f05b8d18f01a9f2cea1f5034 (diff)
downloadkogata-978b3234a04f11f959f603db4756253278ca65df.tar.gz
kogata-978b3234a04f11f959f603db4756253278ca65df.zip
Mouse code
-rw-r--r--src/common/include/proto/mouse.h12
-rw-r--r--src/kernel/core/kmain.c3
-rw-r--r--src/kernel/dev/pckbd.c139
-rw-r--r--src/kernel/dev/pckbdmouse.c315
-rw-r--r--src/kernel/include/dev/pckbdmouse.h (renamed from src/kernel/include/dev/pckbd.h)1
5 files changed, 330 insertions, 140 deletions
diff --git a/src/common/include/proto/mouse.h b/src/common/include/proto/mouse.h
new file mode 100644
index 0000000..782620c
--- /dev/null
+++ b/src/common/include/proto/mouse.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <stdint.h>
+#include <stddef.h>
+
+typedef struct {
+ int16_t delta_x, delta_y;
+ int8_t delta_wheel;
+ uint8_t lbtn, rbtn, midbtn;
+} mouse_event_t;
+
+/* vim: set sts=0 ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c
index 95b63d5..2dabf7e 100644
--- a/src/kernel/core/kmain.c
+++ b/src/kernel/core/kmain.c
@@ -25,7 +25,7 @@
#include <prng.h>
-#include <dev/pckbd.h>
+#include <dev/pckbdmouse.h>
#include <dev/pci.h>
#include <dev/pciide.h>
#include <dev/vesa.h>
@@ -180,6 +180,7 @@ void kernel_init_stage2(void* data) {
// Scan for devices
pckbd_setup(iofs);
+ pcmouse_setup(iofs);
vesa_detect(iofs);
pci_setup();
pciide_detect(iofs);
diff --git a/src/kernel/dev/pckbd.c b/src/kernel/dev/pckbd.c
deleted file mode 100644
index f7452b2..0000000
--- a/src/kernel/dev/pckbd.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include <string.h>
-
-#include <idt.h>
-#include <nullfs.h>
-#include <thread.h>
-
-#include <dev/pckbd.h>
-
-#include <proto/keyboard.h>
-
-#define PCKBD_BUF_LEN 16
-
-kbd_event_t pckbd_buf[PCKBD_BUF_LEN];
-int pckbd_buf_used = 0;
-bool pckbd_escaped = false;
-
-void irq1_handler(registers_t *regs) {
- uint8_t scancode = inb(0x60);
- if (scancode == 0xE0) {
- pckbd_escaped = true;
- } else {
- kbd_event_t ev;
- if (scancode & 0x80) {
- if (pckbd_escaped) {
- ev.scancode = scancode;
- ev.type = KBD_EVENT_KEYRELEASE;
- } else {
- ev.scancode = scancode & 0x7F;
- ev.type = KBD_EVENT_KEYRELEASE;
- }
- } else {
- if (pckbd_escaped) {
- ev.scancode = scancode | 0x80;
- ev.type = KBD_EVENT_KEYPRESS;
- } else {
- ev.scancode = scancode;
- ev.type = KBD_EVENT_KEYPRESS;
- }
- }
-
- if (pckbd_buf_used < PCKBD_BUF_LEN) {
- pckbd_buf[pckbd_buf_used++] = ev;
-
- resume_on(&pckbd_buf);
- }
-
- pckbd_escaped = false;
- }
-}
-
-// ---- VFS operations
-
-bool pckbd_open(fs_node_t *n, int mode);
-size_t pckbd_read(fs_handle_t *h, size_t offset, size_t len, char *buf);
-int pckbd_poll(fs_handle_t *h, void** out_wait_obj);
-void pckbd_close(fs_handle_t *h);
-int pckbd_ioctl(fs_handle_t *h, int command, void* data);
-bool pckbd_stat(fs_node_t *n, stat_t *st);
-
-fs_node_ops_t pckbd_ops = {
- .open = pckbd_open,
- .read = pckbd_read,
- .write = 0,
- .readdir = 0,
- .poll = pckbd_poll,
- .close = pckbd_close,
- .ioctl = pckbd_ioctl,
- .stat = pckbd_stat,
- .walk = 0,
- .delete = 0,
- .move = 0,
- .create = 0,
- .dispose = 0,
-};
-
-void pckbd_setup(fs_t *iofs) {
- uint8_t a = 0, b = 0;
- while ((a = inb(0x60)) != b) b = a;
-
- idt_set_irq_handler(IRQ1, &irq1_handler);
-
- nullfs_add_node(iofs, "/input/pckbd", 0, &pckbd_ops, 0);
-}
-
-bool pckbd_open(fs_node_t *n, int mode) {
- return (mode == FM_READ);
-}
-
-size_t pckbd_read(fs_handle_t *h, size_t offset, size_t len, char *buf) {
- int ret = 0;
-
- int st = enter_critical(CL_NOINT);
-
- while (len - ret >= sizeof(kbd_event_t) && pckbd_buf_used > 0) {
- memcpy(buf + ret, &pckbd_buf[0], sizeof(kbd_event_t));
-
- for (int i = 1; i < pckbd_buf_used; i++) {
- pckbd_buf[i-1] = pckbd_buf[i];
- }
- pckbd_buf_used--;
-
- ret += sizeof(kbd_event_t);
- }
-
- exit_critical(st);
-
- return ret;
-}
-
-int pckbd_poll(fs_handle_t *h, void** out_wait_obj) {
- if (out_wait_obj) *out_wait_obj = &pckbd_buf;
-
- return (pckbd_buf_used > 0 ? SEL_READ : 0);
-}
-
-void pckbd_close(fs_handle_t *h) {
- return; // nothing to do
-}
-
-int pckbd_ioctl(fs_handle_t *h, int command, void* data) {
- if (command == IOCTL_KBD_SET_LEDS) {
- uint8_t leds = (uint32_t)data & 0x07;
-
- outb(0x60, leds);
-
- return 1;
- }
- return 0;
-}
-
-bool pckbd_stat(fs_node_t *n, stat_t *st) {
- st->type = FT_CHARDEV;
- st->size = 0;
- st->access = FM_READ;
-
- return true;
-}
-
-/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/dev/pckbdmouse.c b/src/kernel/dev/pckbdmouse.c
new file mode 100644
index 0000000..eddc02d
--- /dev/null
+++ b/src/kernel/dev/pckbdmouse.c
@@ -0,0 +1,315 @@
+#include <string.h>
+
+#include <idt.h>
+#include <nullfs.h>
+#include <thread.h>
+
+#include <dev/pckbdmouse.h>
+
+#include <proto/keyboard.h>
+#include <proto/mouse.h>
+
+
+// ----------------------------------------------
+// Keyboard
+// ----------------------------------------------
+
+#define PCKBD_BUF_LEN 16
+
+kbd_event_t pckbd_buf[PCKBD_BUF_LEN];
+int pckbd_buf_used = 0;
+bool pckbd_escaped = false;
+
+void irq1_handler(registers_t *regs) {
+ uint8_t scancode = inb(0x60);
+ if (scancode == 0xE0) {
+ pckbd_escaped = true;
+ } else {
+ kbd_event_t ev;
+ if (scancode & 0x80) {
+ if (pckbd_escaped) {
+ ev.scancode = scancode;
+ ev.type = KBD_EVENT_KEYRELEASE;
+ } else {
+ ev.scancode = scancode & 0x7F;
+ ev.type = KBD_EVENT_KEYRELEASE;
+ }
+ } else {
+ if (pckbd_escaped) {
+ ev.scancode = scancode | 0x80;
+ ev.type = KBD_EVENT_KEYPRESS;
+ } else {
+ ev.scancode = scancode;
+ ev.type = KBD_EVENT_KEYPRESS;
+ }
+ }
+
+ if (pckbd_buf_used < PCKBD_BUF_LEN) {
+ pckbd_buf[pckbd_buf_used++] = ev;
+
+ resume_on(&pckbd_buf);
+ }
+
+ pckbd_escaped = false;
+ }
+}
+
+// ---- VFS operations
+
+bool pckbd_open(fs_node_t *n, int mode);
+size_t pckbd_read(fs_handle_t *h, size_t offset, size_t len, char *buf);
+int pckbd_poll(fs_handle_t *h, void** out_wait_obj);
+void pckbd_close(fs_handle_t *h);
+int pckbd_ioctl(fs_handle_t *h, int command, void* data);
+bool pckbd_stat(fs_node_t *n, stat_t *st);
+
+fs_node_ops_t pckbd_ops = {
+ .open = pckbd_open,
+ .read = pckbd_read,
+ .write = 0,
+ .readdir = 0,
+ .poll = pckbd_poll,
+ .close = pckbd_close,
+ .ioctl = pckbd_ioctl,
+ .stat = pckbd_stat,
+ .walk = 0,
+ .delete = 0,
+ .move = 0,
+ .create = 0,
+ .dispose = 0,
+};
+
+void pckbd_setup(fs_t *iofs) {
+ uint8_t a = 0, b = 0;
+ while ((a = inb(0x60)) != b) b = a;
+
+ idt_set_irq_handler(IRQ1, &irq1_handler);
+
+ nullfs_add_node(iofs, "/input/pckbd", 0, &pckbd_ops, 0);
+}
+
+bool pckbd_open(fs_node_t *n, int mode) {
+ return (mode == FM_READ);
+}
+
+size_t pckbd_read(fs_handle_t *h, size_t offset, size_t len, char *buf) {
+ int ret = 0;
+
+ int st = enter_critical(CL_NOINT);
+
+ while (len - ret >= sizeof(kbd_event_t) && pckbd_buf_used > 0) {
+ memcpy(buf + ret, &pckbd_buf[0], sizeof(kbd_event_t));
+
+ for (int i = 1; i < pckbd_buf_used; i++) {
+ pckbd_buf[i-1] = pckbd_buf[i];
+ }
+ pckbd_buf_used--;
+
+ ret += sizeof(kbd_event_t);
+ }
+
+ exit_critical(st);
+
+ return ret;
+}
+
+int pckbd_poll(fs_handle_t *h, void** out_wait_obj) {
+ if (out_wait_obj) *out_wait_obj = &pckbd_buf;
+
+ return (pckbd_buf_used > 0 ? SEL_READ : 0);
+}
+
+void pckbd_close(fs_handle_t *h) {
+ return; // nothing to do
+}
+
+int pckbd_ioctl(fs_handle_t *h, int command, void* data) {
+ if (command == IOCTL_KBD_SET_LEDS) {
+ uint8_t leds = (uint32_t)data & 0x07;
+
+ outb(0x60, leds);
+
+ return 1;
+ }
+ return 0;
+}
+
+bool pckbd_stat(fs_node_t *n, stat_t *st) {
+ st->type = FT_CHARDEV;
+ st->size = 0;
+ st->access = FM_READ;
+
+ return true;
+}
+
+
+// ----------------------------------------------
+// Mouse
+// ----------------------------------------------
+
+#define PCMOUSE_BUF_LEN 64
+
+mouse_event_t pcmouse_buf[PCMOUSE_BUF_LEN];
+int pcmouse_buf_used = 0;
+
+int mouse_cycle = 0;
+int8_t mouse_byte[4];
+
+void irq12_handler(registers_t *regs) {
+ if (mouse_cycle == 0) {
+ mouse_byte[0] = inb(0x60);
+ mouse_cycle = 1;
+ } else if (mouse_cycle == 1) {
+ mouse_byte[1] = inb(0x60);
+ mouse_cycle = 2;
+ } else if (mouse_cycle == 2) {
+ mouse_byte[2] = inb(0x60);
+ mouse_cycle = 0;
+
+ if (mouse_byte[0] & (0x80 | 0x40)) return; // overflow bit is set
+ if (pcmouse_buf_used >= PCMOUSE_BUF_LEN) return;
+
+ mouse_event_t e;
+ e.delta_x = mouse_byte[1];
+ e.delta_y = mouse_byte[2];
+ if (mouse_byte[0] & 0x10) e.delta_x |= 0xFF00;
+ if (mouse_byte[0] & 0x20) e.delta_y |= 0xFF00;
+ e.delta_wheel = 0;
+ e.lbtn = ((mouse_byte[0] & 0x01) != 0);
+ e.rbtn = ((mouse_byte[0] & 0x02) != 0);
+ e.midbtn = ((mouse_byte[0] & 0x04) != 0);
+
+ pcmouse_buf[pcmouse_buf_used++] = e;
+ resume_on(&pcmouse_buf);
+ }
+}
+
+static inline void mouse_wait(int a_type) {
+ size_t _time_out = 100000;
+ if (a_type == 0) {
+ while(_time_out--) {
+ if ((inb(0x64) & 1)==1) return;
+ }
+ } else {
+ while(_time_out--) {
+ if ((inb(0x64) & 2)==0) return;
+ }
+ }
+}
+
+static inline void mouse_write(uint8_t a_write) {
+ mouse_wait(1);
+ outb(0x64, 0xD4);
+ mouse_wait(1);
+ outb(0x60, a_write);
+}
+
+static inline uint8_t mouse_read() {
+ mouse_wait(0);
+ return inb(0x60);
+}
+
+void pcmouse_setup_device() {
+ // Enable mouse device
+ mouse_wait(1);
+ outb(0x64, 0xA8);
+
+ // Enable interrupts
+ mouse_wait(1);
+ outb(0x64, 0x20);
+ mouse_wait(0);
+ uint8_t status = (inb(0x60) | 2);
+ mouse_wait(1);
+ outb(0x64, 0x60);
+ mouse_wait(0);
+ outb(0x60, status);
+
+ // Tell mouse to use default settings
+ mouse_write(0xF6);
+ mouse_read();
+
+ // Enable mouse
+ mouse_write(0xF4);
+ mouse_read();
+}
+
+bool pcmouse_open(fs_node_t *n, int mode);
+size_t pcmouse_read(fs_handle_t *h, size_t offset, size_t len, char *buf);
+int pcmouse_poll(fs_handle_t *h, void** out_wait_obj);
+void pcmouse_close(fs_handle_t *h);
+int pcmouse_ioctl(fs_handle_t *h, int command, void* data);
+bool pcmouse_stat(fs_node_t *n, stat_t *st);
+
+fs_node_ops_t pcmouse_ops = {
+ .open = pcmouse_open,
+ .read = pcmouse_read,
+ .write = 0,
+ .readdir = 0,
+ .poll = pcmouse_poll,
+ .close = pcmouse_close,
+ .ioctl = pcmouse_ioctl,
+ .stat = pcmouse_stat,
+ .walk = 0,
+ .delete = 0,
+ .move = 0,
+ .create = 0,
+ .dispose = 0,
+};
+
+void pcmouse_setup(fs_t *iofs) {
+ pcmouse_setup_device();
+
+ idt_set_irq_handler(IRQ12, &irq12_handler);
+
+ nullfs_add_node(iofs, "/input/pcmouse", 0, &pcmouse_ops, 0);
+}
+
+bool pcmouse_open(fs_node_t *n, int mode) {
+ return (mode == FM_READ);
+}
+
+size_t pcmouse_read(fs_handle_t *h, size_t offset, size_t len, char *buf) {
+ int ret = 0;
+
+ int st = enter_critical(CL_NOINT);
+
+ while (len - ret >= sizeof(mouse_event_t) && pcmouse_buf_used > 0) {
+ memcpy(buf + ret, &pcmouse_buf[0], sizeof(mouse_event_t));
+
+ for (int i = 1; i < pcmouse_buf_used; i++) {
+ pcmouse_buf[i-1] = pcmouse_buf[i];
+ }
+ pcmouse_buf_used--;
+
+ ret += sizeof(mouse_event_t);
+ }
+
+ exit_critical(st);
+
+ return ret;
+}
+
+int pcmouse_poll(fs_handle_t *h, void** out_wait_obj) {
+ if (out_wait_obj) *out_wait_obj = &pcmouse_buf;
+
+ return (pcmouse_buf_used > 0 ? SEL_READ : 0);
+}
+
+void pcmouse_close(fs_handle_t *h) {
+ return; // nothing to do
+}
+
+int pcmouse_ioctl(fs_handle_t *h, int command, void* data) {
+ // No ioctls implemented...
+ return 0;
+}
+
+bool pcmouse_stat(fs_node_t *n, stat_t *st) {
+ st->type = FT_CHARDEV;
+ st->size = 0;
+ st->access = FM_READ;
+
+ return true;
+}
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/include/dev/pckbd.h b/src/kernel/include/dev/pckbdmouse.h
index 7205bb1..6fb0931 100644
--- a/src/kernel/include/dev/pckbd.h
+++ b/src/kernel/include/dev/pckbdmouse.h
@@ -3,5 +3,6 @@
#include <vfs.h>
void pckbd_setup(fs_t *iofs);
+void pcmouse_setup(fs_t *iofs);
/* vim: set ts=4 sw=4 tw=0 noet :*/