forked from Bananymous/banan-os
Kernel: Rewrite the whole input system
PS/2 code is now kind of messed up, but it works. Keyboards and mice are now an abstract class that is automatically exposed to userspace. This will make adding USB input much nicer.
This commit is contained in:
parent
110a45bee6
commit
a97a574718
|
@ -34,6 +34,7 @@ set(KERNEL_SOURCES
|
||||||
kernel/FS/VirtualFileSystem.cpp
|
kernel/FS/VirtualFileSystem.cpp
|
||||||
kernel/GDT.cpp
|
kernel/GDT.cpp
|
||||||
kernel/IDT.cpp
|
kernel/IDT.cpp
|
||||||
|
kernel/Input/InputDevice.cpp
|
||||||
kernel/Input/PS2/Controller.cpp
|
kernel/Input/PS2/Controller.cpp
|
||||||
kernel/Input/PS2/Device.cpp
|
kernel/Input/PS2/Device.cpp
|
||||||
kernel/Input/PS2/Keyboard.cpp
|
kernel/Input/PS2/Keyboard.cpp
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace Kernel
|
||||||
Null,
|
Null,
|
||||||
Zero,
|
Zero,
|
||||||
Debug,
|
Debug,
|
||||||
Input,
|
Keyboard,
|
||||||
|
Mouse,
|
||||||
SCSI,
|
SCSI,
|
||||||
NVMeController,
|
NVMeController,
|
||||||
NVMeNamespace,
|
NVMeNamespace,
|
||||||
|
|
|
@ -20,8 +20,6 @@ namespace Kernel
|
||||||
void add_device(BAN::RefPtr<Device>);
|
void add_device(BAN::RefPtr<Device>);
|
||||||
void add_inode(BAN::StringView path, BAN::RefPtr<TmpInode>);
|
void add_inode(BAN::StringView path, BAN::RefPtr<TmpInode>);
|
||||||
|
|
||||||
int get_next_input_device() const;
|
|
||||||
|
|
||||||
void initiate_sync(bool should_block);
|
void initiate_sync(bool should_block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/ByteSpan.h>
|
||||||
|
|
||||||
|
#include <kernel/Device/Device.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class InputDevice : public CharacterDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
Mouse,
|
||||||
|
Keyboard,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
InputDevice(Type type);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void add_event(BAN::ConstByteSpan);
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||||
|
|
||||||
|
bool can_read_impl() const override { SpinLockGuard _(m_event_lock); return m_event_count > 0; }
|
||||||
|
bool can_write_impl() const override { return false; }
|
||||||
|
bool has_error_impl() const override { return false; }
|
||||||
|
|
||||||
|
virtual BAN::StringView name() const final override { return m_name; }
|
||||||
|
virtual dev_t rdev() const final override { return m_rdev; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const dev_t m_rdev;
|
||||||
|
const BAN::String m_name;
|
||||||
|
|
||||||
|
mutable SpinLock m_event_lock;
|
||||||
|
Semaphore m_event_semaphore;
|
||||||
|
|
||||||
|
static constexpr size_t m_max_event_count { 128 };
|
||||||
|
|
||||||
|
BAN::Vector<uint8_t> m_event_buffer;
|
||||||
|
const size_t m_event_size;
|
||||||
|
size_t m_event_tail { 0 };
|
||||||
|
size_t m_event_head { 0 };
|
||||||
|
size_t m_event_count { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -60,6 +60,7 @@ namespace Kernel::Input
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::RefPtr<PS2Device> m_devices[2];
|
BAN::RefPtr<PS2Device> m_devices[2];
|
||||||
|
|
||||||
Mutex m_mutex;
|
Mutex m_mutex;
|
||||||
|
|
||||||
BAN::CircularQueue<Command, 128> m_command_queue;
|
BAN::CircularQueue<Command, 128> m_command_queue;
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/Input/PS2/Controller.h>
|
#include <kernel/Input/PS2/Controller.h>
|
||||||
|
#include <kernel/Input/InputDevice.h>
|
||||||
#include <kernel/Interruptable.h>
|
#include <kernel/Interruptable.h>
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
||||||
|
|
||||||
class PS2Device : public CharacterDevice, public Interruptable
|
class PS2Device : public Interruptable, public InputDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~PS2Device() {}
|
|
||||||
|
|
||||||
virtual void send_initialize() = 0;
|
virtual void send_initialize() = 0;
|
||||||
|
|
||||||
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) = 0;
|
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) = 0;
|
||||||
|
@ -21,17 +20,10 @@ namespace Kernel::Input
|
||||||
|
|
||||||
virtual void handle_byte(uint8_t) = 0;
|
virtual void handle_byte(uint8_t) = 0;
|
||||||
|
|
||||||
virtual BAN::StringView name() const final override { return m_name; }
|
protected:
|
||||||
virtual dev_t rdev() const final override { return m_rdev; }
|
PS2Device(PS2Controller&, InputDevice::Type type);
|
||||||
|
|
||||||
virtual void update() final override { m_controller.update_command_queue(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PS2Device(PS2Controller&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const dev_t m_rdev;
|
|
||||||
const BAN::String m_name;
|
|
||||||
PS2Controller& m_controller;
|
PS2Controller& m_controller;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/Array.h>
|
#include <BAN/Array.h>
|
||||||
#include <BAN/CircularQueue.h>
|
|
||||||
#include <kernel/Input/PS2/Device.h>
|
#include <kernel/Input/PS2/Device.h>
|
||||||
#include <kernel/Input/PS2/Keymap.h>
|
#include <kernel/Input/PS2/Keymap.h>
|
||||||
#include <kernel/Semaphore.h>
|
|
||||||
#include <LibInput/KeyEvent.h>
|
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
||||||
|
@ -20,13 +17,15 @@ namespace Kernel::Input
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<PS2Keyboard*> create(PS2Controller&);
|
static BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> create(PS2Controller&);
|
||||||
virtual void send_initialize() override;
|
virtual void send_initialize() override;
|
||||||
|
|
||||||
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override;
|
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override;
|
||||||
|
|
||||||
virtual void handle_byte(uint8_t) final override;
|
virtual void handle_byte(uint8_t) final override;
|
||||||
|
|
||||||
|
virtual void update() final override { m_controller.update_command_queue(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PS2Keyboard(PS2Controller& controller);
|
PS2Keyboard(PS2Controller& controller);
|
||||||
|
|
||||||
|
@ -37,22 +36,11 @@ namespace Kernel::Input
|
||||||
uint8_t m_byte_index { 0 };
|
uint8_t m_byte_index { 0 };
|
||||||
|
|
||||||
uint8_t m_scancode_set { 0xFF };
|
uint8_t m_scancode_set { 0xFF };
|
||||||
|
|
||||||
uint16_t m_modifiers { 0 };
|
uint16_t m_modifiers { 0 };
|
||||||
|
|
||||||
BAN::CircularQueue<LibInput::RawKeyEvent, 50> m_event_queue;
|
|
||||||
SpinLock m_event_lock;
|
|
||||||
|
|
||||||
PS2Keymap m_keymap;
|
PS2Keymap m_keymap;
|
||||||
|
|
||||||
Semaphore m_semaphore;
|
friend class BAN::RefPtr<PS2Keyboard>;
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return !m_event_queue.empty(); }
|
|
||||||
virtual bool can_write_impl() const override { return false; }
|
|
||||||
virtual bool has_error_impl() const override { return false; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kernel/Input/PS2/Device.h>
|
#include <kernel/Input/PS2/Device.h>
|
||||||
#include <kernel/Semaphore.h>
|
|
||||||
#include <LibInput/MouseEvent.h>
|
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
||||||
|
@ -16,13 +14,15 @@ namespace Kernel::Input
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<PS2Mouse*> create(PS2Controller&);
|
static BAN::ErrorOr<BAN::RefPtr<PS2Mouse>> create(PS2Controller&);
|
||||||
virtual void send_initialize() override;
|
virtual void send_initialize() override;
|
||||||
|
|
||||||
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override { (void)command_data; (void)command_size; }
|
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override { (void)command_data; (void)command_size; }
|
||||||
|
|
||||||
virtual void handle_byte(uint8_t) final override;
|
virtual void handle_byte(uint8_t) final override;
|
||||||
|
|
||||||
|
virtual void update() final override { m_controller.update_command_queue(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PS2Mouse(PS2Controller& controller);
|
PS2Mouse(PS2Controller& controller);
|
||||||
|
|
||||||
|
@ -36,17 +36,7 @@ namespace Kernel::Input
|
||||||
uint8_t m_mouse_id { 0x00 };
|
uint8_t m_mouse_id { 0x00 };
|
||||||
uint8_t m_button_mask { 0x00 };
|
uint8_t m_button_mask { 0x00 };
|
||||||
|
|
||||||
BAN::CircularQueue<LibInput::MouseEvent, 128> m_event_queue;
|
friend class BAN::RefPtr<PS2Mouse>;
|
||||||
SpinLock m_event_lock;
|
|
||||||
|
|
||||||
Semaphore m_semaphore;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return !m_event_queue.empty(); }
|
|
||||||
virtual bool can_write_impl() const override { return false; }
|
|
||||||
virtual bool has_error_impl() const override { return false; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,10 +119,4 @@ namespace Kernel
|
||||||
MUST(static_cast<TmpDirectoryInode*>(root_inode().ptr())->link_inode(*inode, path));
|
MUST(static_cast<TmpDirectoryInode*>(root_inode().ptr())->link_inode(*inode, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
int DevFileSystem::get_next_input_device() const
|
|
||||||
{
|
|
||||||
static BAN::Atomic<dev_t> next_dev = 0;
|
|
||||||
return next_dev++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
#include <kernel/Device/DeviceNumbers.h>
|
||||||
|
#include <kernel/Input/InputDevice.h>
|
||||||
|
#include <kernel/Lock/LockGuard.h>
|
||||||
|
|
||||||
|
#include <LibInput/KeyEvent.h>
|
||||||
|
#include <LibInput/MouseEvent.h>
|
||||||
|
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
static BAN::Atomic<uint16_t> s_next_keyboard { 0 };
|
||||||
|
static BAN::Atomic<uint16_t> s_next_mouse { 0 };
|
||||||
|
|
||||||
|
static const char* get_name_format(InputDevice::Type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case InputDevice::Type::Keyboard:
|
||||||
|
return "keyboard{}";
|
||||||
|
case InputDevice::Type::Mouse:
|
||||||
|
return "mouse{}";
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
static dev_t get_rdev(InputDevice::Type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case InputDevice::Type::Keyboard:
|
||||||
|
return makedev(DeviceNumber::Keyboard, s_next_keyboard++);
|
||||||
|
case InputDevice::Type::Mouse:
|
||||||
|
return makedev(DeviceNumber::Mouse, s_next_mouse++);
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t get_event_size(InputDevice::Type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case InputDevice::Type::Keyboard:
|
||||||
|
return sizeof(LibInput::RawKeyEvent);
|
||||||
|
case InputDevice::Type::Mouse:
|
||||||
|
return sizeof(LibInput::MouseEvent);
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
InputDevice::InputDevice(Type type)
|
||||||
|
: CharacterDevice(0440, 0, 901)
|
||||||
|
, m_rdev(get_rdev(type))
|
||||||
|
, m_name(MUST(BAN::String::formatted(get_name_format(type), minor(m_rdev))))
|
||||||
|
, m_event_size(get_event_size(type))
|
||||||
|
{
|
||||||
|
MUST(m_event_buffer.resize(m_event_size * m_max_event_count, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputDevice::add_event(BAN::ConstByteSpan event)
|
||||||
|
{
|
||||||
|
SpinLockGuard _(m_event_lock);
|
||||||
|
ASSERT(event.size() == m_event_size);
|
||||||
|
|
||||||
|
if (m_event_count == m_max_event_count)
|
||||||
|
{
|
||||||
|
m_event_tail = (m_event_tail + 1) % m_max_event_count;
|
||||||
|
m_event_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&m_event_buffer[m_event_head * m_event_size], event.data(), m_event_size);
|
||||||
|
m_event_head = (m_event_head + 1) % m_max_event_count;
|
||||||
|
m_event_count++;
|
||||||
|
|
||||||
|
m_event_semaphore.unblock();
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> InputDevice::read_impl(off_t, BAN::ByteSpan buffer)
|
||||||
|
{
|
||||||
|
if (buffer.size() < m_event_size)
|
||||||
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
|
auto state = m_event_lock.lock();
|
||||||
|
while (m_event_count == 0)
|
||||||
|
{
|
||||||
|
m_event_lock.unlock(state);
|
||||||
|
{
|
||||||
|
LockFreeGuard _(m_mutex);
|
||||||
|
TRY(Thread::current().block_or_eintr_indefinite(m_event_semaphore));
|
||||||
|
}
|
||||||
|
state = m_event_lock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer.data(), &m_event_buffer[m_event_tail * m_event_size], m_event_size);
|
||||||
|
m_event_tail = (m_event_tail + 1) % m_max_event_count;
|
||||||
|
m_event_count--;
|
||||||
|
|
||||||
|
m_event_lock.unlock(state);
|
||||||
|
|
||||||
|
return m_event_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -89,9 +89,9 @@ namespace Kernel::Input
|
||||||
uint8_t PS2Controller::get_device_index(PS2Device* device) const
|
uint8_t PS2Controller::get_device_index(PS2Device* device) const
|
||||||
{
|
{
|
||||||
ASSERT(device);
|
ASSERT(device);
|
||||||
if (m_devices[0] && device == m_devices[0].ptr())
|
if (m_devices[0].ptr() == device)
|
||||||
return 0;
|
return 0;
|
||||||
if (m_devices[1] && device == m_devices[1].ptr())
|
if (m_devices[1].ptr() == device)
|
||||||
return 1;
|
return 1;
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -359,12 +359,12 @@ namespace Kernel::Input
|
||||||
TRY(send_command(PS2::Command::WRITE_CONFIG, config));
|
TRY(send_command(PS2::Command::WRITE_CONFIG, config));
|
||||||
|
|
||||||
// Send device initialization sequence after interrupts are enabled
|
// Send device initialization sequence after interrupts are enabled
|
||||||
for (uint8_t device = 0; device < 2; device++)
|
for (uint8_t i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (!m_devices[device])
|
if (!m_devices[i])
|
||||||
continue;
|
continue;
|
||||||
m_devices[device]->send_initialize();
|
m_devices[i]->send_initialize();
|
||||||
DevFileSystem::get().add_device(m_devices[device]);
|
DevFileSystem::get().add_device(m_devices[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
#include <kernel/Device/DeviceNumbers.h>
|
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/Input/PS2/Config.h>
|
#include <kernel/Input/PS2/Config.h>
|
||||||
#include <kernel/Input/PS2/Device.h>
|
#include <kernel/Input/PS2/Device.h>
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
|
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
||||||
|
|
||||||
PS2Device::PS2Device(PS2Controller& controller)
|
PS2Device::PS2Device(PS2Controller& controller, InputDevice::Type type)
|
||||||
: CharacterDevice(0440, 0, 901)
|
: InputDevice(type)
|
||||||
, m_rdev(makedev(DeviceNumber::Input, DevFileSystem::get().get_next_input_device()))
|
|
||||||
, m_name(MUST(BAN::String::formatted("input{}", minor(m_rdev))))
|
|
||||||
, m_controller(controller)
|
, m_controller(controller)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
|
@ -4,20 +4,18 @@
|
||||||
#include <kernel/Input/PS2/Keyboard.h>
|
#include <kernel/Input/PS2/Keyboard.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
#include <LibInput/KeyboardLayout.h>
|
#include <LibInput/KeyboardLayout.h>
|
||||||
|
#include <LibInput/KeyEvent.h>
|
||||||
|
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::ErrorOr<PS2Keyboard*> PS2Keyboard::create(PS2Controller& controller)
|
BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> PS2Keyboard::create(PS2Controller& controller)
|
||||||
{
|
{
|
||||||
PS2Keyboard* keyboard = new PS2Keyboard(controller);
|
return TRY(BAN::RefPtr<PS2Keyboard>::create(controller));
|
||||||
if (keyboard == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
return keyboard;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PS2Keyboard::PS2Keyboard(PS2Controller& controller)
|
PS2Keyboard::PS2Keyboard(PS2Controller& controller)
|
||||||
: PS2Device(controller)
|
: PS2Device(controller, InputDevice::Type::Keyboard)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void PS2Keyboard::send_initialize()
|
void PS2Keyboard::send_initialize()
|
||||||
|
@ -166,17 +164,7 @@ namespace Kernel::Input
|
||||||
RawKeyEvent event;
|
RawKeyEvent event;
|
||||||
event.modifier = m_modifiers | (released ? 0 : KeyModifier::Pressed);
|
event.modifier = m_modifiers | (released ? 0 : KeyModifier::Pressed);
|
||||||
event.keycode = keycode.value();
|
event.keycode = keycode.value();
|
||||||
|
add_event(BAN::ConstByteSpan::from(event));
|
||||||
SpinLockGuard _(m_event_lock);
|
|
||||||
|
|
||||||
if (m_event_queue.full())
|
|
||||||
{
|
|
||||||
dwarnln("PS/2 event queue full");
|
|
||||||
m_event_queue.pop();
|
|
||||||
}
|
|
||||||
m_event_queue.push(event);
|
|
||||||
|
|
||||||
m_semaphore.unblock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PS2Keyboard::update_leds()
|
void PS2Keyboard::update_leds()
|
||||||
|
@ -193,30 +181,4 @@ namespace Kernel::Input
|
||||||
append_command_queue(Command::SET_LEDS, new_leds, 0);
|
append_command_queue(Command::SET_LEDS, new_leds, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> PS2Keyboard::read_impl(off_t, BAN::ByteSpan buffer)
|
|
||||||
{
|
|
||||||
using LibInput::RawKeyEvent;
|
|
||||||
|
|
||||||
if (buffer.size() < sizeof(RawKeyEvent))
|
|
||||||
return BAN::Error::from_errno(ENOBUFS);
|
|
||||||
|
|
||||||
auto state = m_event_lock.lock();
|
|
||||||
while (m_event_queue.empty())
|
|
||||||
{
|
|
||||||
m_event_lock.unlock(state);
|
|
||||||
{
|
|
||||||
LockFreeGuard _(m_mutex);
|
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
|
||||||
}
|
|
||||||
state = m_event_lock.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.as<RawKeyEvent>() = m_event_queue.front();
|
|
||||||
m_event_queue.pop();
|
|
||||||
|
|
||||||
m_event_lock.unlock(state);
|
|
||||||
|
|
||||||
return sizeof(RawKeyEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <kernel/Input/PS2/Config.h>
|
#include <kernel/Input/PS2/Config.h>
|
||||||
#include <kernel/Input/PS2/Mouse.h>
|
#include <kernel/Input/PS2/Mouse.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
#include <LibInput/MouseEvent.h>
|
||||||
|
|
||||||
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
|
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
|
||||||
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
|
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
|
||||||
|
@ -10,16 +11,13 @@
|
||||||
namespace Kernel::Input
|
namespace Kernel::Input
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::ErrorOr<PS2Mouse*> PS2Mouse::create(PS2Controller& controller)
|
BAN::ErrorOr<BAN::RefPtr<PS2Mouse>> PS2Mouse::create(PS2Controller& controller)
|
||||||
{
|
{
|
||||||
PS2Mouse* mouse = new PS2Mouse(controller);
|
return TRY(BAN::RefPtr<PS2Mouse>::create(controller));
|
||||||
if (mouse == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
return mouse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PS2Mouse::PS2Mouse(PS2Controller& controller)
|
PS2Mouse::PS2Mouse(PS2Controller& controller)
|
||||||
: PS2Device(controller)
|
: PS2Device(controller, InputDevice::Type::Mouse)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void PS2Mouse::send_initialize()
|
void PS2Mouse::send_initialize()
|
||||||
|
@ -110,10 +108,6 @@ namespace Kernel::Input
|
||||||
|
|
||||||
m_byte_index = 0;
|
m_byte_index = 0;
|
||||||
|
|
||||||
// Max 7 events, one for each (5) button, one for movement, one for scroll
|
|
||||||
BAN::Array<MouseEvent, 7> events;
|
|
||||||
int event_count = 0;
|
|
||||||
|
|
||||||
auto button_index_to_button =
|
auto button_index_to_button =
|
||||||
[](int index) -> MouseButton
|
[](int index) -> MouseButton
|
||||||
{
|
{
|
||||||
|
@ -137,10 +131,11 @@ namespace Kernel::Input
|
||||||
if ((new_button_mask & (1 << i)) == (m_button_mask & (1 << i)))
|
if ((new_button_mask & (1 << i)) == (m_button_mask & (1 << i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto& event = events[event_count++];
|
MouseEvent event;
|
||||||
event.type = MouseEventType::MouseButtonEvent;
|
event.type = MouseEventType::MouseButtonEvent;
|
||||||
event.button_event.button = button_index_to_button(i);
|
event.button_event.button = button_index_to_button(i);
|
||||||
event.button_event.pressed = !!(new_button_mask & (1 << i));
|
event.button_event.pressed = !!(new_button_mask & (1 << i));
|
||||||
|
add_event(BAN::ConstByteSpan::from(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_button_mask = new_button_mask;
|
m_button_mask = new_button_mask;
|
||||||
|
@ -148,71 +143,20 @@ namespace Kernel::Input
|
||||||
|
|
||||||
if (rel_x || rel_y)
|
if (rel_x || rel_y)
|
||||||
{
|
{
|
||||||
auto& event = events[event_count++];
|
MouseEvent event;
|
||||||
event.type = MouseEventType::MouseMoveEvent;
|
event.type = MouseEventType::MouseMoveEvent;
|
||||||
event.move_event.rel_x = rel_x;
|
event.move_event.rel_x = rel_x;
|
||||||
event.move_event.rel_y = rel_y;
|
event.move_event.rel_y = rel_y;
|
||||||
|
add_event(BAN::ConstByteSpan::from(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rel_z)
|
if (rel_z)
|
||||||
{
|
{
|
||||||
auto& event = events[event_count++];
|
MouseEvent event;
|
||||||
event.type = MouseEventType::MouseScrollEvent;
|
event.type = MouseEventType::MouseScrollEvent;
|
||||||
event.scroll_event.scroll = rel_z;
|
event.scroll_event.scroll = rel_z;
|
||||||
}
|
add_event(BAN::ConstByteSpan::from(event));
|
||||||
|
|
||||||
SpinLockGuard _(m_event_lock);
|
|
||||||
|
|
||||||
for (int i = 0; i < event_count; i++)
|
|
||||||
{
|
|
||||||
if (!m_event_queue.empty() && m_event_queue.back().type == events[i].type)
|
|
||||||
{
|
|
||||||
if (events[i].type == MouseEventType::MouseMoveEvent)
|
|
||||||
{
|
|
||||||
m_event_queue.back().move_event.rel_x += events[i].move_event.rel_x;
|
|
||||||
m_event_queue.back().move_event.rel_y += events[i].move_event.rel_y;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events[i].type == MouseEventType::MouseScrollEvent)
|
|
||||||
{
|
|
||||||
m_event_queue.back().scroll_event.scroll += events[i].scroll_event.scroll;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_event_queue.full())
|
|
||||||
{
|
|
||||||
dwarnln("PS/2 event queue full");
|
|
||||||
m_event_queue.pop();
|
|
||||||
}
|
|
||||||
m_event_queue.push(events[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_semaphore.unblock();
|
|
||||||
}
|
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> PS2Mouse::read_impl(off_t, BAN::ByteSpan buffer)
|
|
||||||
{
|
|
||||||
using LibInput::MouseEvent;
|
|
||||||
|
|
||||||
if (buffer.size() < sizeof(MouseEvent))
|
|
||||||
return BAN::Error::from_errno(ENOBUFS);
|
|
||||||
|
|
||||||
auto state = m_event_lock.lock();
|
|
||||||
while (m_event_queue.empty())
|
|
||||||
{
|
|
||||||
m_event_lock.unlock(state);
|
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
|
||||||
state = m_event_lock.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.as<MouseEvent>() = m_event_queue.front();
|
|
||||||
m_event_queue.pop();
|
|
||||||
|
|
||||||
m_event_lock.unlock(state);
|
|
||||||
|
|
||||||
return sizeof(MouseEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace Kernel
|
||||||
Process::create_kernel(
|
Process::create_kernel(
|
||||||
[](void*)
|
[](void*)
|
||||||
{
|
{
|
||||||
auto file_or_error = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/input0"_sv, O_RDONLY);
|
auto file_or_error = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/keyboard0"_sv, O_RDONLY);
|
||||||
if (file_or_error.is_error())
|
if (file_or_error.is_error())
|
||||||
{
|
{
|
||||||
dprintln("no input device found");
|
dprintln("no input device found");
|
||||||
|
|
|
@ -158,11 +158,11 @@ int main()
|
||||||
MUST(LibInput::KeyboardLayout::initialize());
|
MUST(LibInput::KeyboardLayout::initialize());
|
||||||
MUST(LibInput::KeyboardLayout::get().load_from_file("/usr/share/keymaps/us.keymap"_sv));
|
MUST(LibInput::KeyboardLayout::get().load_from_file("/usr/share/keymaps/us.keymap"_sv));
|
||||||
|
|
||||||
int keyboard_fd = open("/dev/input0", O_RDONLY);
|
int keyboard_fd = open("/dev/keyboard0", O_RDONLY);
|
||||||
if (keyboard_fd == -1)
|
if (keyboard_fd == -1)
|
||||||
perror("open");
|
perror("open");
|
||||||
|
|
||||||
int mouse_fd = open("/dev/input1", O_RDONLY);
|
int mouse_fd = open("/dev/mouse0", O_RDONLY);
|
||||||
if (mouse_fd == -1)
|
if (mouse_fd == -1)
|
||||||
perror("open");
|
perror("open");
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ void cleanup()
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
const char* fb_path = "/dev/fb0";
|
const char* fb_path = "/dev/fb0";
|
||||||
const char* mouse_path = "/dev/input1";
|
const char* mouse_path = "/dev/mouse0";
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
;
|
;
|
||||||
|
|
Loading…
Reference in New Issue