diff --git a/kernel/include/kernel/USB/HID/HIDDriver.h b/kernel/include/kernel/USB/HID/HIDDriver.h index 826c5ad4..f2d8bae4 100644 --- a/kernel/include/kernel/USB/HID/HIDDriver.h +++ b/kernel/include/kernel/USB/HID/HIDDriver.h @@ -58,8 +58,9 @@ namespace Kernel virtual void start_report() = 0; virtual void stop_report() = 0; - virtual void handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) = 0; virtual void handle_array(uint16_t usage_page, uint16_t usage) = 0; + virtual void handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) = 0; + virtual void handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max) = 0; }; class USBHIDDriver final : public USBClassDriver diff --git a/kernel/include/kernel/USB/HID/Keyboard.h b/kernel/include/kernel/USB/HID/Keyboard.h index 6ae9da69..2885bd7b 100644 --- a/kernel/include/kernel/USB/HID/Keyboard.h +++ b/kernel/include/kernel/USB/HID/Keyboard.h @@ -14,8 +14,9 @@ namespace Kernel void start_report() override; void stop_report() override; - void handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) override; void handle_array(uint16_t usage_page, uint16_t usage) override; + void handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) override; + void handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max) override; void update() override; diff --git a/kernel/include/kernel/USB/HID/Mouse.h b/kernel/include/kernel/USB/HID/Mouse.h index 1950beb4..3b89aee8 100644 --- a/kernel/include/kernel/USB/HID/Mouse.h +++ b/kernel/include/kernel/USB/HID/Mouse.h @@ -14,8 +14,9 @@ namespace Kernel void start_report() override; void stop_report() override; - void handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) override; void handle_array(uint16_t usage_page, uint16_t usage) override; + void handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) override; + void handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max) override; private: USBMouse() @@ -23,13 +24,25 @@ namespace Kernel {} ~USBMouse() = default; + private: + struct AbsInfo + { + int64_t val { -1 }; + int64_t min { 0 }; + int64_t max { 0 }; + bool valid() const { return min <= val && val <= max; } + }; + private: BAN::Array m_button_state { false }; BAN::Array m_button_state_temp { false }; - int64_t m_pointer_x { 0 }; - int64_t m_pointer_y { 0 }; + int64_t m_rel_x { 0 }; + int64_t m_rel_y { 0 }; int64_t m_wheel { 0 }; + AbsInfo m_abs_x; + AbsInfo m_abs_y; + friend class BAN::RefPtr; }; diff --git a/kernel/kernel/USB/HID/HIDDriver.cpp b/kernel/kernel/USB/HID/HIDDriver.cpp index 5d1cb2f6..db06feef 100644 --- a/kernel/kernel/USB/HID/HIDDriver.cpp +++ b/kernel/kernel/USB/HID/HIDDriver.cpp @@ -376,17 +376,26 @@ namespace Kernel continue; } - const int64_t physical = - (input.physical_maximum - input.physical_minimum) * - (logical - input.logical_minimum) / - (input.logical_maximum - input.logical_minimum) + - input.physical_minimum; - const uint32_t usage_base = input.usage_id ? input.usage_id : input.usage_minimum; - if (input.flags & 0x02) - device_input.device->handle_variable(input.usage_page, usage_base + i, physical); + + const bool relative = !!(input.flags & 0x04); + const bool variable = !!(input.flags & 0x02); + + if (!variable) + device_input.device->handle_array(input.usage_page, usage_base + logical); else - device_input.device->handle_array(input.usage_page, usage_base + physical); + { + const int64_t physical = + (input.physical_maximum - input.physical_minimum) * + (logical - input.logical_minimum) / + (input.logical_maximum - input.logical_minimum) + + input.physical_minimum; + + if (relative) + device_input.device->handle_variable(input.usage_page, usage_base + i, physical); + else + device_input.device->handle_variable_absolute(input.usage_page, usage_base + i, physical, input.physical_minimum, input.physical_maximum); + } bit_offset += input.report_size; } diff --git a/kernel/kernel/USB/HID/Keyboard.cpp b/kernel/kernel/USB/HID/Keyboard.cpp index 6242f883..eacb5c27 100644 --- a/kernel/kernel/USB/HID/Keyboard.cpp +++ b/kernel/kernel/USB/HID/Keyboard.cpp @@ -102,21 +102,6 @@ namespace Kernel m_keyboard_lock.unlock(m_lock_state); } - void USBKeyboard::handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) - { - ASSERT(m_keyboard_lock.current_processor_has_lock()); - - if (usage_page != 0x07) - { - dprintln_if(DEBUG_USB_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page); - return; - } - if (!state) - return; - if (usage >= 4 && usage < m_keyboard_state_temp.size()) - m_keyboard_state_temp[usage] = state; - } - void USBKeyboard::handle_array(uint16_t usage_page, uint16_t usage) { ASSERT(m_keyboard_lock.current_processor_has_lock()); @@ -130,6 +115,31 @@ namespace Kernel m_keyboard_state_temp[usage] = true; } + void USBKeyboard::handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) + { + (void)usage_page; + (void)usage; + (void)state; + dprintln_if(DEBUG_USB_KEYBOARD, "Unsupported keyboard relative usage page {2H}", usage_page); + } + + void USBKeyboard::handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max) + { + (void)min; (void)max; + + ASSERT(m_keyboard_lock.current_processor_has_lock()); + + if (usage_page != 0x07) + { + dprintln_if(DEBUG_USB_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page); + return; + } + if (!state) + return; + if (usage >= 4 && usage < m_keyboard_state_temp.size()) + m_keyboard_state_temp[usage] = state; + } + void USBKeyboard::update() { using KeyModifier = LibInput::KeyEvent::Modifier; diff --git a/kernel/kernel/USB/HID/Mouse.cpp b/kernel/kernel/USB/HID/Mouse.cpp index 55859ea4..b55ebc6b 100644 --- a/kernel/kernel/USB/HID/Mouse.cpp +++ b/kernel/kernel/USB/HID/Mouse.cpp @@ -6,24 +6,43 @@ namespace Kernel void USBMouse::start_report() { + m_wheel = 0; + m_rel_x = 0; + m_rel_y = 0; + + m_abs_x = {}; + m_abs_y = {}; + for (auto& val : m_button_state_temp) val = false; } void USBMouse::stop_report() { - if (m_pointer_x || m_pointer_y) + if (m_abs_x.valid() && m_abs_y.valid()) { - dprintln_if(DEBUG_USB_MOUSE, "Mouse move event {}, {}", m_pointer_x, m_pointer_y); + dprintln_if(DEBUG_USB_MOUSE, "Mouse move absolute event {}, {}", m_abs_x.val, m_abs_y.val); + + LibInput::MouseEvent event; + event.type = LibInput::MouseEventType::MouseMoveAbsEvent; + event.move_abs_event.abs_x = m_abs_x.val; + event.move_abs_event.min_x = m_abs_x.min; + event.move_abs_event.max_x = m_abs_x.max; + event.move_abs_event.abs_y = m_abs_y.val; + event.move_abs_event.min_y = m_abs_y.min; + event.move_abs_event.max_y = m_abs_y.max; + add_event(BAN::ConstByteSpan::from(event)); + } + + if (m_rel_x || m_rel_y) + { + dprintln_if(DEBUG_USB_MOUSE, "Mouse move event {}, {}", m_rel_x, m_rel_y); LibInput::MouseEvent event; event.type = LibInput::MouseEventType::MouseMoveEvent; - event.move_event.rel_x = m_pointer_x; - event.move_event.rel_y = -m_pointer_y; + event.move_event.rel_x = m_rel_x; + event.move_event.rel_y = -m_rel_y; add_event(BAN::ConstByteSpan::from(event)); - - m_pointer_x = 0; - m_pointer_y = 0; } if (m_wheel) @@ -34,8 +53,6 @@ namespace Kernel event.type = LibInput::MouseEventType::MouseScrollEvent; event.scroll_event.scroll = m_wheel; add_event(BAN::ConstByteSpan::from(event)); - - m_wheel = 0; } for (size_t i = 0; i < m_button_state.size(); i++) @@ -57,6 +74,11 @@ namespace Kernel } } + void USBMouse::handle_array(uint16_t usage_page, uint16_t usage) + { + dprintln_if(DEBUG_USB_MOUSE, "Unhandled array report {2H}:{2H}", usage_page, usage); + } + void USBMouse::handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) { switch (usage_page) @@ -65,16 +87,50 @@ namespace Kernel switch (usage) { case 0x30: - m_pointer_x = state; + m_rel_x = state; break; case 0x31: - m_pointer_y = state; + m_rel_y = state; break; case 0x38: m_wheel = state; break; default: - dprintln_if(DEBUG_USB_MOUSE, "Unsupported mouse usage {2H} on page {2H}", usage, usage_page); + dprintln_if(DEBUG_USB_MOUSE, "Unsupported relative mouse usage {2H} on page {2H}", usage, usage_page); + break; + } + break; + default: + dprintln_if(DEBUG_USB_MOUSE, "Unsupported relative mouse usage page {2H}", usage_page); + break; + } + } + + void USBMouse::handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max) + { + (void)min; (void)max; + + switch (usage_page) + { + case 0x01: // pointer + switch (usage) + { + case 0x30: + m_abs_x = { + .val = state, + .min = min, + .max = max, + }; + break; + case 0x31: + m_abs_y = { + .val = state, + .min = min, + .max = max, + }; + break; + default: + dprintln_if(DEBUG_USB_MOUSE, "Unsupported absolute mouse usage {2H} on page {2H}", usage, usage_page); break; } break; @@ -84,14 +140,9 @@ namespace Kernel m_button_state_temp[usage - 1] = state; break; default: - dprintln_if(DEBUG_USB_MOUSE, "Unsupported mouse usage page {2H}", usage_page); + dprintln_if(DEBUG_USB_MOUSE, "Unsupported absolute mouse usage page {2H}", usage_page); break; } } - void USBMouse::handle_array(uint16_t usage_page, uint16_t usage) - { - dprintln_if(DEBUG_USB_MOUSE, "Unhandled array report {2H}:{2H}", usage_page, usage); - } - } diff --git a/userspace/libraries/LibInput/include/LibInput/MouseEvent.h b/userspace/libraries/LibInput/include/LibInput/MouseEvent.h index ac39c4f6..6e0905d5 100644 --- a/userspace/libraries/LibInput/include/LibInput/MouseEvent.h +++ b/userspace/libraries/LibInput/include/LibInput/MouseEvent.h @@ -22,6 +22,16 @@ namespace LibInput int32_t rel_y; }; + struct MouseMoveAbsEvent + { + int32_t abs_x; + int32_t abs_y; + int32_t min_x; + int32_t min_y; + int32_t max_x; + int32_t max_y; + }; + struct MouseScrollEvent { int32_t scroll; @@ -31,6 +41,7 @@ namespace LibInput { MouseButtonEvent, MouseMoveEvent, + MouseMoveAbsEvent, MouseScrollEvent, }; @@ -41,6 +52,7 @@ namespace LibInput { MouseButtonEvent button_event; MouseMoveEvent move_event; + MouseMoveAbsEvent move_abs_event; MouseScrollEvent scroll_event; }; };