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:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user