Kernel: Implement simple USB HID driver

This should be easily expandable to add HID devices
This commit is contained in:
2024-07-14 02:02:59 +03:00
parent 442ea8a692
commit 1efc6a1385
10 changed files with 1010 additions and 11 deletions

View File

@@ -1,5 +1,6 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/NoCopyMove.h>
#include <kernel/Memory/DMARegion.h>
@@ -9,6 +10,18 @@
namespace Kernel
{
class USBClassDriver
{
BAN_NON_COPYABLE(USBClassDriver);
BAN_NON_MOVABLE(USBClassDriver);
public:
USBClassDriver() = default;
virtual ~USBClassDriver() = default;
virtual void handle_input_data(BAN::ConstByteSpan, uint8_t endpoint_id) = 0;
};
class USBDevice
{
BAN_NON_COPYABLE(USBDevice);
@@ -47,11 +60,13 @@ namespace Kernel
const BAN::Vector<ConfigurationDescriptor>& configurations() { return m_descriptor.configurations; }
virtual BAN::ErrorOr<void> initialize_endpoint(const USBEndpointDescriptor&) = 0;
virtual BAN::ErrorOr<size_t> send_request(const USBDeviceRequest&, paddr_t buffer) = 0;
static USB::SpeedClass determine_speed_class(uint64_t bits_per_second);
protected:
void handle_input_data(BAN::ConstByteSpan, uint8_t endpoint_id);
virtual BAN::ErrorOr<void> initialize_control_endpoint() = 0;
private:
@@ -60,6 +75,9 @@ namespace Kernel
private:
DeviceDescriptor m_descriptor;
BAN::UniqPtr<DMARegion> m_dma_buffer;
// FIXME: support more than one interface from a configuration
BAN::UniqPtr<USBClassDriver> m_class_driver;
};
}

View File

@@ -0,0 +1,94 @@
#pragma once
#include <kernel/Input/InputDevice.h>
#include <kernel/USB/Device.h>
namespace Kernel
{
namespace USBHID
{
struct Report
{
enum class Type { Input, Output, Feature };
uint16_t usage_page;
uint16_t usage_id;
Type type;
uint32_t report_count;
uint32_t report_size;
uint32_t usage_minimum;
uint32_t usage_maximum;
int64_t logical_minimum;
int64_t logical_maximum;
int64_t physical_minimum;
int64_t physical_maximum;
uint8_t flags;
};
struct Collection
{
uint16_t usage_page;
uint16_t usage_id;
uint8_t type;
BAN::Vector<BAN::Variant<Collection, Report>> entries;
};
}
class USBHIDDevice : public InputDevice
{
BAN_NON_COPYABLE(USBHIDDevice);
BAN_NON_MOVABLE(USBHIDDevice);
public:
USBHIDDevice(InputDevice::Type type)
: InputDevice(type)
{}
virtual ~USBHIDDevice() = default;
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;
};
class USBHIDDriver final : public USBClassDriver
{
BAN_NON_COPYABLE(USBHIDDriver);
BAN_NON_MOVABLE(USBHIDDriver);
public:
static BAN::ErrorOr<BAN::UniqPtr<USBHIDDriver>> create(USBDevice&, const USBDevice::InterfaceDescriptor&, uint8_t interface_index);
void handle_input_data(BAN::ConstByteSpan, uint8_t endpoint_id) override;
private:
USBHIDDriver(USBDevice&, const USBDevice::InterfaceDescriptor&, uint8_t interface_index);
~USBHIDDriver();
BAN::ErrorOr<void> initialize();
void forward_collection_inputs(const USBHID::Collection&, BAN::ConstByteSpan& data, size_t bit_offset);
private:
USBDevice& m_device;
USBDevice::InterfaceDescriptor m_interface;
const uint8_t m_interface_index;
uint8_t m_endpoint_id { 0 };
USBHID::Collection m_collection;
BAN::RefPtr<USBHIDDevice> m_hid_device;
friend class BAN::UniqPtr<USBHIDDriver>;
};
}

View File

@@ -26,11 +26,15 @@ namespace Kernel
Mutex mutex;
volatile uint32_t transfer_count { 0 };
volatile XHCI::TRB completion_trb;
BAN::UniqPtr<DMARegion> data_region;
void(XHCIDevice::*callback)(XHCI::TRB);
};
public:
static BAN::ErrorOr<BAN::UniqPtr<XHCIDevice>> create(XHCIController&, uint32_t port_id, uint32_t slot_id);
BAN::ErrorOr<void> initialize_endpoint(const USBEndpointDescriptor&) override;
BAN::ErrorOr<size_t> send_request(const USBDeviceRequest&, paddr_t buffer) override;
void on_transfer_event(const volatile XHCI::TRB&);
@@ -47,6 +51,8 @@ namespace Kernel
~XHCIDevice();
BAN::ErrorOr<void> update_actual_max_packet_size();
void on_interrupt_endpoint_event(XHCI::TRB);
void advance_endpoint_enqueue(Endpoint&, bool chain);
private: