mirror of
https://github.com/fergalmoran/ladybird.git
synced 2025-12-22 09:19:03 +00:00
447 lines
20 KiB
C++
447 lines
20 KiB
C++
/*
|
|
* Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/Span.h>
|
|
#include <AK/String.h>
|
|
#include <Kernel/Bus/VirtIO/Transport/PCIe/TransportLink.h>
|
|
#include <Kernel/Devices/HID/Management.h>
|
|
#include <Kernel/Devices/HID/VirtIO/EvDevDefinitions.h>
|
|
#include <Kernel/Devices/HID/VirtIO/Input.h>
|
|
#include <Kernel/Sections.h>
|
|
|
|
namespace Kernel::VirtIO {
|
|
|
|
struct VirtIOInputEvent {
|
|
LittleEndian<u16> type;
|
|
LittleEndian<u16> code;
|
|
LittleEndian<u32> value;
|
|
};
|
|
static_assert(AssertSize<VirtIOInputEvent, 8>());
|
|
|
|
struct VirtIOInputConfig {
|
|
enum class Select : u8 {
|
|
Unset = 0x00,
|
|
IDName = 0x01,
|
|
IDSerial = 0x02,
|
|
IDDevIDs = 0x03,
|
|
PropBits = 0x10,
|
|
EvBits = 0x11,
|
|
AbsInfo = 0x12,
|
|
};
|
|
|
|
struct AbsInfo {
|
|
LittleEndian<u32> min;
|
|
LittleEndian<u32> max;
|
|
LittleEndian<u32> fuzz;
|
|
LittleEndian<u32> flat;
|
|
LittleEndian<u32> res;
|
|
};
|
|
static_assert(AssertSize<AbsInfo, 20>());
|
|
|
|
struct DevIDs {
|
|
LittleEndian<u16> bustype;
|
|
LittleEndian<u16> vendor;
|
|
LittleEndian<u16> product;
|
|
LittleEndian<u16> version;
|
|
};
|
|
static_assert(AssertSize<DevIDs, 8>());
|
|
|
|
Select select;
|
|
u8 subsel;
|
|
u8 size;
|
|
u8 reserved[5];
|
|
union {
|
|
char string[128];
|
|
u8 bitmap[128];
|
|
AbsInfo abs;
|
|
DevIDs ids;
|
|
} u;
|
|
};
|
|
static_assert(AssertSize<VirtIOInputConfig, 136>());
|
|
|
|
// clang-format off
|
|
static constexpr auto unshifted_evdev_key_map = to_array<KeyCodeEntry const>({
|
|
// 0x00-0x0f
|
|
{ Key_Invalid, 0xff }, { Key_Escape, 0x01 }, { Key_1, 0x02 }, { Key_2, 0x03 },
|
|
{ Key_3, 0x04 }, { Key_4, 0x05 }, { Key_5, 0x06 }, { Key_6, 0x07 },
|
|
{ Key_7, 0x08 }, { Key_8, 0x09 }, { Key_9, 0x0a }, { Key_0, 0x0b },
|
|
{ Key_Minus, 0x0c }, { Key_Equal, 0x0d }, { Key_Backspace, 0x0e }, { Key_Tab, 0x0f },
|
|
|
|
// 0x10-0x1f
|
|
{ Key_Q, 0x10 }, { Key_W, 0x11 }, { Key_E, 0x12 }, { Key_R, 0x13 },
|
|
{ Key_T, 0x14 }, { Key_Y, 0x15 }, { Key_U, 0x16 }, { Key_I, 0x17 },
|
|
{ Key_O, 0x18 }, { Key_P, 0x19 }, { Key_LeftBracket, 0x1a }, { Key_RightBracket, 0x1b },
|
|
{ Key_Return, 0x1c }, { Key_Control, 0x1d }, { Key_A, 0x1e }, { Key_S, 0x1f },
|
|
|
|
// 0x20-0x2f
|
|
{ Key_D, 0x20 }, { Key_F, 0x21 }, { Key_G, 0x22 }, { Key_H, 0x23 },
|
|
{ Key_J, 0x24 }, { Key_K, 0x25 }, { Key_L, 0x26 }, { Key_Semicolon, 0x27 },
|
|
{ Key_Apostrophe, 0x28 }, { Key_Backtick, 0x29 }, { Key_LeftShift, 0xff }, { Key_Backslash, 0x2b },
|
|
{ Key_Z, 0x2c }, { Key_X, 0x2d }, { Key_C, 0x2e }, { Key_V, 0x2f },
|
|
|
|
// 0x30-0x3f
|
|
{ Key_B, 0x30 }, { Key_N, 0x31 }, { Key_M, 0x32 }, { Key_Comma, 0x33 },
|
|
{ Key_Period, 0x34 }, { Key_Slash, 0x35 }, { Key_RightShift, 0xff }, { Key_Asterisk, 0x37 },
|
|
{ Key_Alt, 0xff }, { Key_Space, 0x39 }, { Key_CapsLock, 0xff }, { Key_F1, 0xff },
|
|
{ Key_F2, 0xff }, { Key_F3, 0xff }, { Key_F4, 0xff }, { Key_F5, 0xff },
|
|
|
|
// 0x40-0x4f
|
|
{ Key_F6, 0xff }, { Key_F7, 0xff }, { Key_F8, 0xff }, { Key_F9, 0xff },
|
|
{ Key_F10, 0xff }, { Key_NumLock, 0x45 }, { Key_ScrollLock, 0xff }, { Key_Home, 0xff },
|
|
{ Key_Up, 0xff }, { Key_PageUp, 0xff }, { Key_Minus, 0x4a }, { Key_Left, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Right, 0xff }, { Key_Plus, 0x4e }, { Key_End, 0xff },
|
|
|
|
// 0x50-0x5f
|
|
{ Key_Down, 0xff }, { Key_PageDown, 0xff }, { Key_Insert, 0xff }, { Key_Delete, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Backslash, 0x56 }, { Key_F11, 0xff },
|
|
{ Key_F12, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff },
|
|
|
|
// 0x60-0x6f
|
|
// FIXME: Add Numpad "/" key to character map for key code 0x62
|
|
{ Key_Return, 0xff }, { Key_RightControl, 0xff }, { Key_Slash, 0xff }, { Key_SysRq, 0xff },
|
|
{ Key_RightAlt, 0xff }, { Key_Invalid, 0xff }, { Key_Home, 0xff }, { Key_Up, 0xff },
|
|
{ Key_PageUp, 0xff }, { Key_Left, 0xff }, { Key_Right, 0xff }, { Key_End, 0xff },
|
|
{ Key_Down, 0xff }, { Key_PageDown, 0xff }, { Key_Insert, 0xff }, { Key_Delete, 0xff },
|
|
|
|
// 0x70-0x7f
|
|
{ Key_Invalid, 0xff }, { Key_Mute, 0xff }, { Key_VolumeDown, 0xff }, { Key_VolumeUp, 0xff },
|
|
{ Key_Power, 0xff }, { Key_Equal, 0xff }, { Key_Invalid, 0xff }, { Key_PauseBreak, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Super, 0xff }, { Key_Super, 0xff }, { Key_Menu, 0xff },
|
|
|
|
// 0x80-0x8f
|
|
{ Key_Stop, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff },
|
|
{ Key_Calculator, 0xff }, { Key_Invalid, 0xff }, { Key_Sleep, 0xff }, { Key_Wake, 0xff },
|
|
});
|
|
// clang-format on
|
|
|
|
// clang-format off
|
|
static constexpr auto shifted_evdev_key_map = to_array<KeyCodeEntry const>({
|
|
// 0x00-0x0f
|
|
{ Key_Invalid, 0xff }, { Key_Escape, 0x01 }, { Key_ExclamationPoint, 0x02 }, { Key_AtSign, 0x03 },
|
|
{ Key_Hashtag, 0x04 }, { Key_Dollar, 0x05 }, { Key_Percent, 0x06 }, { Key_Circumflex, 0x07 },
|
|
{ Key_Ampersand, 0x08 }, { Key_Asterisk, 0x09 }, { Key_LeftParen, 0x0a }, { Key_RightParen, 0x0b },
|
|
{ Key_Underscore, 0x0c }, { Key_Plus, 0x0d }, { Key_Backspace, 0x0e }, { Key_Tab, 0x0f },
|
|
|
|
// 0x10-0x1f
|
|
{ Key_Q, 0x10 }, { Key_W, 0x11 }, { Key_E, 0x12 }, { Key_R, 0x13 },
|
|
{ Key_T, 0x14 }, { Key_Y, 0x15 }, { Key_U, 0x16 }, { Key_I, 0x17 },
|
|
{ Key_O, 0x18 }, { Key_P, 0x19 }, { Key_LeftBrace, 0x1a }, { Key_RightBrace, 0x1b },
|
|
{ Key_Return, 0x1c }, { Key_Control, 0x1d }, { Key_A, 0x1e }, { Key_S, 0x1f },
|
|
|
|
// 0x20-0x2f
|
|
{ Key_D, 0x20 }, { Key_F, 0x21 }, { Key_G, 0x22 }, { Key_H, 0x23 },
|
|
{ Key_J, 0x24 }, { Key_K, 0x25 }, { Key_L, 0x26 }, { Key_Colon, 0x27 },
|
|
{ Key_DoubleQuote, 0x28 }, { Key_Tilde, 0x29 }, { Key_LeftShift, 0xff }, { Key_Pipe, 0x2b },
|
|
{ Key_Z, 0x2c }, { Key_X, 0x2d }, { Key_C, 0x2e }, { Key_V, 0x2f },
|
|
|
|
// 0x30-0x3f
|
|
{ Key_B, 0x30 }, { Key_N, 0x31 }, { Key_M, 0x32 }, { Key_LessThan, 0x33 },
|
|
{ Key_GreaterThan, 0x34 }, { Key_QuestionMark, 0x35 }, { Key_RightShift, 0xff }, { Key_Asterisk, 0x37 },
|
|
{ Key_Alt, 0xff }, { Key_Space, 0x39 }, { Key_CapsLock, 0xff }, { Key_F1, 0xff },
|
|
{ Key_F2, 0xff }, { Key_F3, 0xff }, { Key_F4, 0xff }, { Key_F5, 0xff },
|
|
|
|
// 0x40-0x4f
|
|
{ Key_F6, 0xff }, { Key_F7, 0xff }, { Key_F8, 0xff }, { Key_F9, 0xff },
|
|
{ Key_F10, 0xff }, { Key_NumLock, 0xff }, { Key_ScrollLock, 0xff }, { Key_Home, 0xff },
|
|
{ Key_Up, 0xff }, { Key_PageUp, 0xff }, { Key_Minus, 0x4a }, { Key_Left, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Right, 0xff }, { Key_Plus, 0x4e }, { Key_End, 0xff },
|
|
|
|
// 0x50-0x5f
|
|
{ Key_Down, 0xff }, { Key_PageDown, 0xff }, { Key_Insert, 0xff }, { Key_Delete, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Pipe, 0x56 }, { Key_F11, 0xff },
|
|
{ Key_F12, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff },
|
|
{ Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff }, { Key_Invalid, 0xff },
|
|
});
|
|
// clang-format on
|
|
|
|
UNMAP_AFTER_INIT NonnullLockRefPtr<Input> Input::must_create_for_pci_instance(PCI::DeviceIdentifier const& device_identifier)
|
|
{
|
|
auto pci_transport_link = MUST(PCIeTransportLink::create(device_identifier));
|
|
return adopt_lock_ref_if_nonnull(new Input(move(pci_transport_link))).release_nonnull();
|
|
}
|
|
|
|
UNMAP_AFTER_INIT ErrorOr<void> Input::initialize_virtio_resources()
|
|
{
|
|
TRY(Device::initialize_virtio_resources());
|
|
auto const* cfg = TRY(transport_entity().get_config(VirtIO::ConfigurationType::Device));
|
|
TRY(negotiate_features([&](auto) { return 0; }));
|
|
|
|
transport_entity().config_write8(*cfg, offsetof(VirtIOInputConfig, subsel), 0);
|
|
|
|
OwnPtr<KString> name;
|
|
|
|
transport_entity().config_write8(*cfg, offsetof(VirtIOInputConfig, select), to_underlying(VirtIOInputConfig::Select::IDName));
|
|
transport_entity().read_config_atomic([&]() {
|
|
auto size = transport_entity().config_read8(*cfg, offsetof(VirtIOInputConfig, size));
|
|
if (size == 0)
|
|
return;
|
|
|
|
VERIFY(size <= sizeof(VirtIOInputConfig::u.string));
|
|
|
|
char* name_chars = nullptr;
|
|
name = MUST(KString::try_create_uninitialized(size, name_chars));
|
|
|
|
for (size_t i = 0; i < size; i++)
|
|
name_chars[i] = static_cast<char>(transport_entity().config_read8(*cfg, offsetof(VirtIOInputConfig, u.string) + i));
|
|
});
|
|
|
|
if (name)
|
|
dbgln("VirtIO::Input: Device name: {}", name);
|
|
|
|
transport_entity().config_write8(*cfg, offsetof(VirtIOInputConfig, select), to_underlying(VirtIOInputConfig::Select::AbsInfo));
|
|
transport_entity().read_config_atomic([&]() {
|
|
auto size = transport_entity().config_read8(*cfg, offsetof(VirtIOInputConfig, size));
|
|
if (size == 0)
|
|
return;
|
|
|
|
VERIFY(size == sizeof(VirtIOInputConfig::u.abs));
|
|
|
|
m_abs_min = bit_cast<LittleEndian<u32>>(transport_entity().config_read32(*cfg, offsetof(VirtIOInputConfig, u.abs.min)));
|
|
m_abs_max = bit_cast<LittleEndian<u32>>(transport_entity().config_read32(*cfg, offsetof(VirtIOInputConfig, u.abs.max)));
|
|
});
|
|
|
|
TRY(setup_queues(2));
|
|
finish_init();
|
|
|
|
auto& event_queue = get_queue(EVENTQ);
|
|
SpinlockLocker event_queue_lock(event_queue.lock());
|
|
|
|
m_event_buffer_region = TRY(MM.allocate_contiguous_kernel_region(TRY(Memory::page_round_up(event_queue.size() * sizeof(VirtIOInputEvent))), "VirtIO::Input eventq"sv, Memory::Region::Access::ReadWrite));
|
|
|
|
QueueChain event_queue_chain(event_queue);
|
|
|
|
for (size_t queue_idx = 0; queue_idx < event_queue.size(); ++queue_idx) {
|
|
auto buffer_start = m_event_buffer_region->physical_page(0)->paddr().offset(queue_idx * sizeof(VirtIOInputEvent));
|
|
auto did_add_buffer = event_queue_chain.add_buffer_to_chain(buffer_start, sizeof(VirtIOInputEvent), BufferType::DeviceWritable);
|
|
VERIFY(did_add_buffer);
|
|
supply_chain_and_notify(EVENTQ, event_queue_chain);
|
|
}
|
|
|
|
HIDManagement::the().attach_standalone_hid_device(*m_mouse_device);
|
|
HIDManagement::the().attach_standalone_hid_device(*m_keyboard_device);
|
|
|
|
return {};
|
|
}
|
|
|
|
UNMAP_AFTER_INIT Input::Input(NonnullOwnPtr<TransportEntity> transport_entity)
|
|
: VirtIO::Device(move(transport_entity))
|
|
, m_mouse_device(MouseDevice::try_to_initialize().release_value_but_fixme_should_propagate_errors())
|
|
, m_keyboard_device(KeyboardDevice::try_to_initialize().release_value_but_fixme_should_propagate_errors())
|
|
{
|
|
}
|
|
|
|
ErrorOr<void> Input::handle_device_config_change()
|
|
{
|
|
return {};
|
|
}
|
|
|
|
void Input::handle_queue_update(u16 queue_index)
|
|
{
|
|
VERIFY(queue_index == EVENTQ);
|
|
|
|
auto& queue = get_queue(EVENTQ);
|
|
SpinlockLocker queue_lock(queue.lock());
|
|
|
|
size_t used;
|
|
QueueChain popped_chain = queue.pop_used_buffer_chain(used);
|
|
while (!popped_chain.is_empty()) {
|
|
popped_chain.for_each([this](PhysicalAddress paddr, size_t) {
|
|
size_t offset = paddr.get() - m_event_buffer_region->physical_page(0)->paddr().get();
|
|
auto const& event = *reinterpret_cast<VirtIOInputEvent const*>(m_event_buffer_region->vaddr().offset(offset).as_ptr());
|
|
handle_event(event);
|
|
});
|
|
|
|
supply_chain_and_notify(EVENTQ, popped_chain);
|
|
popped_chain = queue.pop_used_buffer_chain(used);
|
|
}
|
|
}
|
|
|
|
void Input::handle_event(VirtIOInputEvent const& event)
|
|
{
|
|
// TODO: Set lock key LEDs
|
|
|
|
switch (event.type) {
|
|
case EV_SYN:
|
|
switch (event.code) {
|
|
case SYN_REPORT:
|
|
m_mouse_device->handle_mouse_packet_input_event(m_current_mouse_packet);
|
|
|
|
// Don't reset the x/y values if the last event was an absolute event, as otherwise the mouse would jump to the top left corner on events other than mouse movement.
|
|
if (m_current_mouse_packet.is_relative) {
|
|
m_current_mouse_packet.x = 0;
|
|
m_current_mouse_packet.y = 0;
|
|
}
|
|
|
|
m_current_mouse_packet.z = 0;
|
|
m_current_mouse_packet.w = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
dbgln_if(VIRTIO_DEBUG, "VirtIO::Input: Unknown EV_SYN event code: {:#x}", event.code);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case EV_KEY:
|
|
switch (event.code) {
|
|
case BTN_LEFT:
|
|
if (event.value == 1)
|
|
m_current_mouse_packet.buttons |= MousePacket::Button::LeftButton;
|
|
else
|
|
m_current_mouse_packet.buttons &= ~MousePacket::Button::LeftButton;
|
|
break;
|
|
|
|
case BTN_RIGHT:
|
|
if (event.value == 1)
|
|
m_current_mouse_packet.buttons |= MousePacket::Button::RightButton;
|
|
else
|
|
m_current_mouse_packet.buttons &= ~MousePacket::Button::RightButton;
|
|
break;
|
|
|
|
case BTN_MIDDLE:
|
|
if (event.value == 1)
|
|
m_current_mouse_packet.buttons |= MousePacket::Button::MiddleButton;
|
|
else
|
|
m_current_mouse_packet.buttons &= ~MousePacket::Button::MiddleButton;
|
|
break;
|
|
|
|
default:
|
|
// NOTE: We only supply entropy from the keyboard device, as each MouseDevice already has a EntropySource attached to it.
|
|
m_entropy_source.add_random_event(event.code);
|
|
|
|
m_keyboard_device->update_modifier(Mod_Keypad, false);
|
|
|
|
RawKeyEvent raw_key_event;
|
|
raw_key_event.is_press_down = event.value == 1;
|
|
raw_key_event.scancode = event.code;
|
|
|
|
switch (event.code) {
|
|
case KEY_LEFTALT:
|
|
m_keyboard_device->update_modifier(Mod_Alt, raw_key_event.is_press());
|
|
break;
|
|
|
|
case KEY_LEFTCTRL:
|
|
case KEY_RIGHTCTRL:
|
|
m_keyboard_device->update_modifier(Mod_Ctrl, raw_key_event.is_press());
|
|
break;
|
|
|
|
case KEY_LEFTSHIFT:
|
|
case KEY_RIGHTSHIFT:
|
|
m_keyboard_device->update_modifier(Mod_Shift, raw_key_event.is_press());
|
|
break;
|
|
|
|
case KEY_LEFTMETA:
|
|
case KEY_RIGHTMETA:
|
|
m_keyboard_device->update_modifier(Mod_Super, raw_key_event.is_press());
|
|
break;
|
|
|
|
case KEY_RIGHTALT:
|
|
m_keyboard_device->update_modifier(Mod_AltGr, raw_key_event.is_press());
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ((event.code >= KEY_KP7 && event.code <= KEY_KPDOT)
|
|
|| event.code == KEY_KPASTERISK
|
|
|| event.code == KEY_KPENTER
|
|
|| event.code == KEY_KPEQUAL
|
|
|| event.code == KEY_KPSLASH) {
|
|
m_keyboard_device->update_modifier(Mod_Keypad, true);
|
|
}
|
|
|
|
// The shift key only applies to small key codes, so only use the shifted key map if the event code is small enough.
|
|
bool use_shifted_key_map = (m_keyboard_device->modifiers() & Mod_Shift) != 0 && event.code < shifted_evdev_key_map.size();
|
|
|
|
auto key_map = use_shifted_key_map ? Span<KeyCodeEntry const>(shifted_evdev_key_map) : Span<KeyCodeEntry const>(unshifted_evdev_key_map);
|
|
|
|
if (event.code >= key_map.size()) {
|
|
dbgln_if(VIRTIO_DEBUG, "VirtIO::Input: Unknown EV_KEY event code: {:#x}", event.code);
|
|
return;
|
|
}
|
|
|
|
raw_key_event.code_entry = key_map[event.code];
|
|
|
|
KeyEvent key_event {
|
|
.key = raw_key_event.code_entry.key_code,
|
|
.map_entry_index = raw_key_event.code_entry.map_entry_index,
|
|
.scancode = raw_key_event.scancode,
|
|
.flags = raw_key_event.is_press() ? static_cast<u8>(Is_Press) : static_cast<u8>(0),
|
|
};
|
|
|
|
if (m_keyboard_device->num_lock_on() && (m_keyboard_device->modifiers() & Mod_Shift) == 0) {
|
|
if (key_event.scancode >= KEY_KP7 && raw_key_event.scancode <= KEY_KPDOT) {
|
|
auto index = key_event.scancode - KEY_KP7;
|
|
static constexpr auto numpad_key_map = to_array<KeyCodeEntry>({
|
|
{ Key_7, 0x08 },
|
|
{ Key_8, 0x09 },
|
|
{ Key_9, 0x0a },
|
|
{ Key_Invalid, 0xff },
|
|
{ Key_4, 0x05 },
|
|
{ Key_5, 0x06 },
|
|
{ Key_6, 0x07 },
|
|
{ Key_Invalid, 0xff },
|
|
{ Key_1, 0x02 },
|
|
{ Key_2, 0x03 },
|
|
{ Key_3, 0x04 },
|
|
{ Key_0, 0x0b },
|
|
{ Key_Period, 0x34 },
|
|
});
|
|
|
|
if (numpad_key_map[index].key_code != Key_Invalid) {
|
|
key_event.key = numpad_key_map[index].key_code;
|
|
key_event.map_entry_index = numpad_key_map[index].map_entry_index;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_keyboard_device->handle_input_event(key_event);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case EV_REL: {
|
|
if (event.code == REL_X) {
|
|
m_current_mouse_packet.is_relative = true;
|
|
m_current_mouse_packet.x = static_cast<int>(event.value);
|
|
} else if (event.code == REL_Y) {
|
|
m_current_mouse_packet.is_relative = true;
|
|
m_current_mouse_packet.y = -static_cast<int>(event.value);
|
|
} else if (event.code == REL_WHEEL) {
|
|
m_current_mouse_packet.z = -static_cast<int>(event.value);
|
|
} else {
|
|
dbgln_if(VIRTIO_DEBUG, "VirtIO::Input: Unknown EV_REL event code: {:#x}", event.code);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case EV_ABS: {
|
|
if (event.code == ABS_X) {
|
|
m_current_mouse_packet.is_relative = false;
|
|
m_current_mouse_packet.x = static_cast<int>((event.value - m_abs_min) * 0xffff / (m_abs_max - m_abs_min));
|
|
} else if (event.code == ABS_Y) {
|
|
m_current_mouse_packet.is_relative = false;
|
|
m_current_mouse_packet.y = static_cast<int>((event.value - m_abs_min) * 0xffff / (m_abs_max - m_abs_min));
|
|
} else {
|
|
dbgln_if(VIRTIO_DEBUG, "VirtIO::Input: Unknown EV_ABS event code: {:#x}", event.code);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
dbgln_if(VIRTIO_DEBUG, "VirtIO::Input: Unknown event type: {:#x}", event.type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|