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:
2024-07-12 20:45:15 +03:00
parent 110a45bee6
commit a97a574718
17 changed files with 197 additions and 177 deletions

View File

@@ -119,10 +119,4 @@ namespace Kernel
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++;
}
}

View File

@@ -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;
}
}

View File

@@ -89,9 +89,9 @@ namespace Kernel::Input
uint8_t PS2Controller::get_device_index(PS2Device* device) const
{
ASSERT(device);
if (m_devices[0] && device == m_devices[0].ptr())
if (m_devices[0].ptr() == device)
return 0;
if (m_devices[1] && device == m_devices[1].ptr())
if (m_devices[1].ptr() == device)
return 1;
ASSERT_NOT_REACHED();
}
@@ -359,12 +359,12 @@ namespace Kernel::Input
TRY(send_command(PS2::Command::WRITE_CONFIG, config));
// 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;
m_devices[device]->send_initialize();
DevFileSystem::get().add_device(m_devices[device]);
m_devices[i]->send_initialize();
DevFileSystem::get().add_device(m_devices[i]);
}
return {};

View File

@@ -1,18 +1,13 @@
#include <kernel/Device/DeviceNumbers.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Input/PS2/Config.h>
#include <kernel/Input/PS2/Device.h>
#include <kernel/IO.h>
#include <sys/sysmacros.h>
namespace Kernel::Input
{
PS2Device::PS2Device(PS2Controller& controller)
: CharacterDevice(0440, 0, 901)
, m_rdev(makedev(DeviceNumber::Input, DevFileSystem::get().get_next_input_device()))
, m_name(MUST(BAN::String::formatted("input{}", minor(m_rdev))))
PS2Device::PS2Device(PS2Controller& controller, InputDevice::Type type)
: InputDevice(type)
, m_controller(controller)
{ }

View File

@@ -4,20 +4,18 @@
#include <kernel/Input/PS2/Keyboard.h>
#include <kernel/Thread.h>
#include <LibInput/KeyboardLayout.h>
#include <LibInput/KeyEvent.h>
namespace Kernel::Input
{
BAN::ErrorOr<PS2Keyboard*> PS2Keyboard::create(PS2Controller& controller)
BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> PS2Keyboard::create(PS2Controller& controller)
{
PS2Keyboard* keyboard = new PS2Keyboard(controller);
if (keyboard == nullptr)
return BAN::Error::from_errno(ENOMEM);
return keyboard;
return TRY(BAN::RefPtr<PS2Keyboard>::create(controller));
}
PS2Keyboard::PS2Keyboard(PS2Controller& controller)
: PS2Device(controller)
: PS2Device(controller, InputDevice::Type::Keyboard)
{ }
void PS2Keyboard::send_initialize()
@@ -166,17 +164,7 @@ namespace Kernel::Input
RawKeyEvent event;
event.modifier = m_modifiers | (released ? 0 : KeyModifier::Pressed);
event.keycode = keycode.value();
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();
add_event(BAN::ConstByteSpan::from(event));
}
void PS2Keyboard::update_leds()
@@ -193,30 +181,4 @@ namespace Kernel::Input
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);
}
}

View File

@@ -3,6 +3,7 @@
#include <kernel/Input/PS2/Config.h>
#include <kernel/Input/PS2/Mouse.h>
#include <kernel/Thread.h>
#include <LibInput/MouseEvent.h>
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
@@ -10,16 +11,13 @@
namespace Kernel::Input
{
BAN::ErrorOr<PS2Mouse*> PS2Mouse::create(PS2Controller& controller)
BAN::ErrorOr<BAN::RefPtr<PS2Mouse>> PS2Mouse::create(PS2Controller& controller)
{
PS2Mouse* mouse = new PS2Mouse(controller);
if (mouse == nullptr)
return BAN::Error::from_errno(ENOMEM);
return mouse;
return TRY(BAN::RefPtr<PS2Mouse>::create(controller));
}
PS2Mouse::PS2Mouse(PS2Controller& controller)
: PS2Device(controller)
: PS2Device(controller, InputDevice::Type::Mouse)
{ }
void PS2Mouse::send_initialize()
@@ -110,10 +108,6 @@ namespace Kernel::Input
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 =
[](int index) -> MouseButton
{
@@ -137,10 +131,11 @@ namespace Kernel::Input
if ((new_button_mask & (1 << i)) == (m_button_mask & (1 << i)))
continue;
auto& event = events[event_count++];
MouseEvent event;
event.type = MouseEventType::MouseButtonEvent;
event.button_event.button = button_index_to_button(i);
event.button_event.pressed = !!(new_button_mask & (1 << i));
add_event(BAN::ConstByteSpan::from(event));
}
m_button_mask = new_button_mask;
@@ -148,71 +143,20 @@ namespace Kernel::Input
if (rel_x || rel_y)
{
auto& event = events[event_count++];
MouseEvent event;
event.type = MouseEventType::MouseMoveEvent;
event.move_event.rel_x = rel_x;
event.move_event.rel_y = rel_y;
add_event(BAN::ConstByteSpan::from(event));
}
if (rel_z)
{
auto& event = events[event_count++];
MouseEvent event;
event.type = MouseEventType::MouseScrollEvent;
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);
}
}

View File

@@ -83,7 +83,7 @@ namespace Kernel
Process::create_kernel(
[](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())
{
dprintln("no input device found");