diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index a7ad531b3b..af068e4c3b 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -70,6 +70,7 @@ set(KERNEL_SOURCES Devices/KCOVInstance.cpp Devices/PCISerialDevice.cpp Devices/SerialDevice.cpp + Devices/HID/AllMiceDevice.cpp Devices/HID/KeyboardDevice.cpp Devices/HID/Management.cpp Devices/HID/MouseDevice.cpp diff --git a/Kernel/Devices/HID/AllMiceDevice.cpp b/Kernel/Devices/HID/AllMiceDevice.cpp new file mode 100644 index 0000000000..1f0716de30 --- /dev/null +++ b/Kernel/Devices/HID/AllMiceDevice.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Kernel { + +NonnullRefPtr AllMiceDevice::must_create() +{ + return *MUST(DeviceManagement::try_create_device()); +} + +AllMiceDevice::AllMiceDevice() + : CharacterDevice(12, 0) +{ +} + +void AllMiceDevice::enqueue_mouse_packet(MousePacket packet) +{ + { + SpinlockLocker lock(m_queue_lock); + m_queue.enqueue(packet); + } + evaluate_block_conditions(); +} + +AllMiceDevice::~AllMiceDevice() = default; + +bool AllMiceDevice::can_read(OpenFileDescription const&, u64) const +{ + SpinlockLocker lock(m_queue_lock); + return !m_queue.is_empty(); +} + +ErrorOr AllMiceDevice::read(OpenFileDescription&, u64, UserOrKernelBuffer& buffer, size_t size) +{ + VERIFY(size > 0); + size_t nread = 0; + size_t remaining_space_in_buffer = static_cast(size) - nread; + SpinlockLocker lock(m_queue_lock); + while (!m_queue.is_empty() && remaining_space_in_buffer) { + auto packet = m_queue.dequeue(); + + size_t bytes_read_from_packet = min(remaining_space_in_buffer, sizeof(MousePacket)); + TRY(buffer.write(&packet, nread, bytes_read_from_packet)); + nread += bytes_read_from_packet; + remaining_space_in_buffer -= bytes_read_from_packet; + } + return nread; +} + +} diff --git a/Kernel/Devices/HID/AllMiceDevice.h b/Kernel/Devices/HID/AllMiceDevice.h new file mode 100644 index 0000000000..0c2580d06a --- /dev/null +++ b/Kernel/Devices/HID/AllMiceDevice.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace Kernel { + +class AllMiceDevice final : public CharacterDevice { + friend class DeviceManagement; + +public: + static NonnullRefPtr must_create(); + + virtual ~AllMiceDevice() override; + + void enqueue_mouse_packet(MousePacket packet); + +private: + AllMiceDevice(); + + // ^CharacterDevice + virtual StringView class_name() const override { return "AllMiceDevice"sv; } + virtual ErrorOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; + virtual bool can_read(OpenFileDescription const&, u64) const override; + virtual ErrorOr write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override { return EINVAL; } + virtual bool can_write(OpenFileDescription const&, u64) const override { return true; } + + mutable Spinlock m_queue_lock {}; + CircularQueue m_queue; +}; +} diff --git a/Kernel/Devices/HID/Management.cpp b/Kernel/Devices/HID/Management.cpp index 10c6119dfc..61ef61e797 100644 --- a/Kernel/Devices/HID/Management.cpp +++ b/Kernel/Devices/HID/Management.cpp @@ -79,6 +79,11 @@ static constexpr Keyboard::CharacterMapData DEFAULT_CHARACTER_MAP = }; // clang-format on +void HIDManagement::enqueue_mouse_packet(Badge, MousePacket packet) +{ + m_all_mice_device->enqueue_mouse_packet(packet); +} + void HIDManagement::set_client(KeyboardClient* client) { SpinlockLocker locker(m_client_lock); @@ -103,6 +108,7 @@ UNMAP_AFTER_INIT HIDManagement::KeymapData::KeymapData() } UNMAP_AFTER_INIT HIDManagement::HIDManagement() + : m_all_mice_device(AllMiceDevice::must_create()) { } diff --git a/Kernel/Devices/HID/Management.h b/Kernel/Devices/HID/Management.h index 31f5c6dcc8..1e9e7cf353 100644 --- a/Kernel/Devices/HID/Management.h +++ b/Kernel/Devices/HID/Management.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,7 @@ class KeyboardClient; class HIDManagement { friend class KeyboardDevice; friend class MouseDevice; + friend class AllMiceDevice; public: HIDManagement(); @@ -56,6 +58,8 @@ public: void attach_standalone_hid_device(HIDDevice&); void detach_standalone_hid_device(HIDDevice&); + void enqueue_mouse_packet(Badge, MousePacket); + private: size_t generate_minor_device_number_for_mouse(); size_t generate_minor_device_number_for_keyboard(); @@ -65,6 +69,8 @@ private: size_t m_keyboard_minor_number { 0 }; KeyboardClient* m_client { nullptr }; + NonnullRefPtr m_all_mice_device; + SpinlockProtected, LockRank::None> m_hid_serial_io_controllers; // NOTE: This list is used for standalone devices, like USB HID devices // (which are not attached via a SerialIO controller in the sense that diff --git a/Kernel/Devices/HID/MouseDevice.cpp b/Kernel/Devices/HID/MouseDevice.cpp index a8a4640ce2..c97bc3ee79 100644 --- a/Kernel/Devices/HID/MouseDevice.cpp +++ b/Kernel/Devices/HID/MouseDevice.cpp @@ -23,6 +23,7 @@ MouseDevice::MouseDevice() void MouseDevice::handle_mouse_packet_input_event(MousePacket packet) { m_entropy_source.add_random_event(packet); + HIDManagement::the().enqueue_mouse_packet({}, packet); { SpinlockLocker lock(m_queue_lock); m_queue.enqueue(packet);