Kernel/HID: Introduce the all-mice device

This device will be used by userspace to read mouse packets from all
mouse devices that are attached to the machine.

This change is a preparation before we can enable seamless hotplug
capabilities in WindowServer for mouse devices, without any major change
on the userspace side.
This commit is contained in:
Liav A 2023-10-06 21:59:39 +03:00 committed by Andrew Kaster
parent 75183402fd
commit 8a0a3638f0
6 changed files with 111 additions and 0 deletions

View file

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

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/Devices/DeviceManagement.h>
#include <Kernel/Devices/HID/AllMiceDevice.h>
#include <Kernel/Devices/HID/Management.h>
namespace Kernel {
NonnullRefPtr<AllMiceDevice> AllMiceDevice::must_create()
{
return *MUST(DeviceManagement::try_create_device<AllMiceDevice>());
}
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<size_t> 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_t>(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;
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/CircularQueue.h>
#include <AK/Types.h>
#include <Kernel/API/MousePacket.h>
#include <Kernel/Devices/CharacterDevice.h>
#include <Kernel/Security/Random.h>
namespace Kernel {
class AllMiceDevice final : public CharacterDevice {
friend class DeviceManagement;
public:
static NonnullRefPtr<AllMiceDevice> 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<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override;
virtual bool can_read(OpenFileDescription const&, u64) const override;
virtual ErrorOr<size_t> write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override { return EINVAL; }
virtual bool can_write(OpenFileDescription const&, u64) const override { return true; }
mutable Spinlock<LockRank::None> m_queue_lock {};
CircularQueue<MousePacket, 1000> m_queue;
};
}

View file

@ -79,6 +79,11 @@ static constexpr Keyboard::CharacterMapData DEFAULT_CHARACTER_MAP =
};
// clang-format on
void HIDManagement::enqueue_mouse_packet(Badge<MouseDevice>, 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())
{
}

View file

@ -16,6 +16,7 @@
#include <AK/Types.h>
#include <Kernel/API/KeyCode.h>
#include <Kernel/Bus/SerialIO/Controller.h>
#include <Kernel/Devices/HID/AllMiceDevice.h>
#include <Kernel/Devices/HID/Device.h>
#include <Kernel/Locking/Spinlock.h>
#include <Kernel/Locking/SpinlockProtected.h>
@ -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<MouseDevice>, 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<AllMiceDevice> m_all_mice_device;
SpinlockProtected<IntrusiveList<&SerialIOController::m_list_node>, 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

View file

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