summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-01-11 02:28:53 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-01-11 02:28:53 +0100
commite740f1195a2f0525296626862b2f7b66a6b5348e (patch)
tree92204a0db95610b49b3a6c071e59d0dcfaae263a
parentd1ceb4b6038c1047988977f93f1ab5510dcf3d70 (diff)
downloadserenity-e740f1195a2f0525296626862b2f7b66a6b5348e.zip
Add a simple PS/2 mouse device.
It's not hooked up to anything just yet, but it does read movement deltas.
-rw-r--r--Kernel/Makefile1
-rw-r--r--Kernel/PS2MouseDevice.cpp113
-rw-r--r--Kernel/PS2MouseDevice.h28
-rw-r--r--Kernel/init.cpp5
4 files changed, 146 insertions, 1 deletions
diff --git a/Kernel/Makefile b/Kernel/Makefile
index 813ce41d7b..96aaac4d16 100644
--- a/Kernel/Makefile
+++ b/Kernel/Makefile
@@ -25,6 +25,7 @@ KERNEL_OBJS = \
ELFImage.o \
ELFLoader.o \
KSyms.o \
+ PS2MouseDevice.o \
WindowComposer.o
VFS_OBJS = \
diff --git a/Kernel/PS2MouseDevice.cpp b/Kernel/PS2MouseDevice.cpp
new file mode 100644
index 0000000000..c829c60539
--- /dev/null
+++ b/Kernel/PS2MouseDevice.cpp
@@ -0,0 +1,113 @@
+#include "PS2MouseDevice.h"
+#include "IO.h"
+
+PS2MouseDevice::PS2MouseDevice()
+ : IRQHandler(12)
+ , CharacterDevice(10, 1)
+{
+ initialize();
+}
+
+PS2MouseDevice::~PS2MouseDevice()
+{
+}
+
+void PS2MouseDevice::handle_irq()
+{
+ m_data[m_data_state] = IO::in8(0x60);
+ switch (m_data_state) {
+ case 0:
+ case 1:
+ ++m_data_state;
+ break;
+ case 2:
+ m_data_state = 0;
+ dbgprintf("PS2Mouse: %d, %d\n", m_data[1], m_data[2]);
+ break;
+ }
+}
+
+void PS2MouseDevice::wait_then_write(byte port, byte data)
+{
+ prepare_for_output();
+ IO::out8(port, data);
+}
+
+byte PS2MouseDevice::wait_then_read(byte port)
+{
+ prepare_for_input();
+ return IO::in8(port);
+}
+
+void PS2MouseDevice::initialize()
+{
+ // Enable PS aux port
+ wait_then_write(0x64, 0xa8);
+
+ // Enable interrupts
+ wait_then_write(0x64, 0x20);
+
+ byte status = wait_then_read(0x60) | 2;
+ wait_then_write(0x64, 0x60);
+ wait_then_write(0x60, status);
+
+ // Set default settings.
+ mouse_write(0xf6);
+ byte ack1 = mouse_read();
+ ASSERT(ack1 == 0xfa);
+
+ // Enable.
+ mouse_write(0xf4);
+ byte ack2 = mouse_read();
+ ASSERT(ack2 == 0xfa);
+
+ enable_irq();
+}
+
+void PS2MouseDevice::prepare_for_input()
+{
+ for (;;) {
+ if (IO::in8(0x64) & 1)
+ return;
+ }
+}
+
+void PS2MouseDevice::prepare_for_output()
+{
+ for (;;) {
+ if (!(IO::in8(0x64) & 2))
+ return;
+ }
+}
+
+void PS2MouseDevice::mouse_write(byte data)
+{
+ prepare_for_output();
+ IO::out8(0x64, 0xd4);
+ prepare_for_output();
+ IO::out8(0x60, data);
+}
+
+byte PS2MouseDevice::mouse_read()
+{
+ prepare_for_input();
+ return IO::in8(0x60);
+}
+
+bool PS2MouseDevice::has_data_available_for_reading() const
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+ssize_t PS2MouseDevice::read(byte* buffer, size_t buffer_size)
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+ssize_t PS2MouseDevice::write(const byte *buffer, size_t buffer_size)
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
diff --git a/Kernel/PS2MouseDevice.h b/Kernel/PS2MouseDevice.h
new file mode 100644
index 0000000000..d7587949d4
--- /dev/null
+++ b/Kernel/PS2MouseDevice.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <VirtualFileSystem/CharacterDevice.h>
+#include "IRQHandler.h"
+
+class PS2MouseDevice final : public IRQHandler, public CharacterDevice {
+public:
+ PS2MouseDevice();
+ virtual ~PS2MouseDevice() override;
+
+private:
+ virtual bool has_data_available_for_reading() const override;
+ virtual ssize_t read(byte* buffer, size_t buffer_size) override;
+ virtual ssize_t write(const byte* buffer, size_t buffer_size) override;
+
+ virtual void handle_irq() override;
+
+ void initialize();
+ void prepare_for_input();
+ void prepare_for_output();
+ void mouse_write(byte);
+ byte mouse_read();
+ void wait_then_write(byte port, byte data);
+ byte wait_then_read(byte port);
+
+ byte m_data_state { 0 };
+ signed_byte m_data[3];
+};
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index 3b6074d21a..76d36780c2 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -20,6 +20,7 @@
#include "RTC.h"
#include "VirtualConsole.h"
#include "Scheduler.h"
+#include "PS2MouseDevice.h"
#define SPAWN_MULTIPLE_SHELLS
//#define STRESS_TEST_SPAWNING
@@ -31,6 +32,7 @@ VirtualConsole* tty1;
VirtualConsole* tty2;
VirtualConsole* tty3;
Keyboard* keyboard;
+PS2MouseDevice* ps2mouse;
#ifdef STRESS_TEST_SPAWNING
static void spawn_stress() NORETURN;
@@ -71,7 +73,7 @@ static void init_stage2()
vfs->register_character_device(*dev_random);
vfs->register_character_device(*keyboard);
-
+ vfs->register_character_device(*ps2mouse);
vfs->register_character_device(*tty0);
vfs->register_character_device(*tty1);
vfs->register_character_device(*tty2);
@@ -125,6 +127,7 @@ void init()
idt_init();
keyboard = new Keyboard;
+ ps2mouse = new PS2MouseDevice;
VirtualConsole::initialize();
tty0 = new VirtualConsole(0, VirtualConsole::AdoptCurrentVGABuffer);