Compare commits

..

No commits in common. "baa4e6475aa118243244cf635f60e9cfbdd546f4" and "8ddab05ed3b12ce5b0560b59145472cc050ca620" have entirely different histories.

41 changed files with 199 additions and 3919 deletions

View File

@ -18,6 +18,8 @@ namespace BAN
constexpr Optional(const Optional&);
constexpr Optional(const T&);
constexpr Optional(T&&);
template<typename... Args>
constexpr Optional(Args&&...);
~Optional();
@ -38,8 +40,6 @@ namespace BAN
constexpr T release_value();
constexpr T& value();
constexpr const T& value() const;
constexpr T& value_or(T&);
constexpr const T& value_or(const T&) const;
constexpr void clear();
@ -83,6 +83,14 @@ namespace BAN
new (m_storage) T(move(value));
}
template<typename T>
template<typename... Args>
constexpr Optional<T>::Optional(Args&&... args)
: m_has_value(true)
{
new (m_storage) T(forward<Args>(args)...);
}
template<typename T>
Optional<T>::~Optional()
{
@ -104,7 +112,7 @@ namespace BAN
{
clear();
m_has_value = other.has_value();
if (other.has_value())
if (other.has_value)
new (m_storage) T(other.value());
return *this;
}
@ -177,22 +185,6 @@ namespace BAN
return (const T&)m_storage;
}
template<typename T>
constexpr T& Optional<T>::value_or(T& empty)
{
if (!has_value())
return empty;
return (T&)m_storage;
}
template<typename T>
constexpr const T& Optional<T>::value_or(const T& empty) const
{
if (!has_value())
return empty;
return (const T&)m_storage;
}
template<typename T>
constexpr void Optional<T>::clear()
{

View File

@ -286,16 +286,6 @@ namespace BAN
return **reinterpret_cast<const remove_reference_t<T>**>(m_storage);
}
bool has_value() const
{
return m_index != invalid_index();
}
explicit operator bool() const
{
return has_value();
}
void clear()
{
if (m_index != invalid_index())

View File

@ -34,7 +34,6 @@ set(KERNEL_SOURCES
kernel/FS/VirtualFileSystem.cpp
kernel/GDT.cpp
kernel/IDT.cpp
kernel/Input/InputDevice.cpp
kernel/Input/PS2/Controller.cpp
kernel/Input/PS2/Device.cpp
kernel/Input/PS2/Keyboard.cpp
@ -94,13 +93,6 @@ set(KERNEL_SOURCES
kernel/Timer/PIT.cpp
kernel/Timer/RTC.cpp
kernel/Timer/Timer.cpp
kernel/USB/Device.cpp
kernel/USB/HID/HIDDriver.cpp
kernel/USB/HID/Keyboard.cpp
kernel/USB/HID/Mouse.cpp
kernel/USB/USBManager.cpp
kernel/USB/XHCI/Controller.cpp
kernel/USB/XHCI/Device.cpp
icxxabi.cpp
)
@ -177,8 +169,7 @@ target_compile_definitions(kernel PUBLIC __arch=${BANAN_ARCH})
target_compile_options(kernel PUBLIC -O2 -g)
target_compile_options(kernel PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-literal-suffix -fno-rtti -fno-exceptions>)
target_compile_options(kernel PUBLIC -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.)
target_compile_options(kernel PUBLIC -fstack-protector -ffreestanding -fno-omit-frame-pointer -fstrict-volatile-bitfields -mgeneral-regs-only)
target_compile_options(kernel PUBLIC -Wall -Wextra -Werror -Wstack-usage=1024)
target_compile_options(kernel PUBLIC -fstack-protector -ffreestanding -Wall -Wextra -Werror -Wstack-usage=1024 -fno-omit-frame-pointer -mgeneral-regs-only)
# This might not work with other toolchains
target_compile_options(kernel PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-Wno-invalid-offsetof>)

View File

@ -42,20 +42,20 @@ namespace __cxxabiv1
{
using __guard = uint64_t;
extern "C" int __cxa_guard_acquire (__guard* g)
int __cxa_guard_acquire (__guard* g)
{
uint8_t* byte = reinterpret_cast<uint8_t*>(g);
uint8_t zero = 0;
return __atomic_compare_exchange_n(byte, &zero, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
}
extern "C" void __cxa_guard_release (__guard* g)
void __cxa_guard_release (__guard* g)
{
uint8_t* byte = reinterpret_cast<uint8_t*>(g);
__atomic_store_n(byte, 0, __ATOMIC_RELEASE);
}
extern "C" void __cxa_guard_abort (__guard*)
void __cxa_guard_abort (__guard*)
{
Kernel::panic("__cxa_guard_abort");
}

View File

@ -13,8 +13,7 @@ namespace Kernel
Null,
Zero,
Debug,
Keyboard,
Mouse,
Input,
SCSI,
NVMeController,
NVMeNamespace,

View File

@ -20,6 +20,8 @@ namespace Kernel
void add_device(BAN::RefPtr<Device>);
void add_inode(BAN::StringView path, BAN::RefPtr<TmpInode>);
int get_next_input_device() const;
void initiate_sync(bool should_block);
private:

View File

@ -1,50 +0,0 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <kernel/Device/Device.h>
namespace Kernel
{
class InputDevice : public CharacterDevice
{
public:
enum class Type
{
Mouse,
Keyboard,
};
public:
InputDevice(Type type);
protected:
void add_event(BAN::ConstByteSpan);
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
bool can_read_impl() const override { SpinLockGuard _(m_event_lock); return m_event_count > 0; }
bool can_write_impl() const override { return false; }
bool has_error_impl() const override { return false; }
virtual BAN::StringView name() const final override { return m_name; }
virtual dev_t rdev() const final override { return m_rdev; }
private:
const dev_t m_rdev;
const BAN::String m_name;
mutable SpinLock m_event_lock;
Semaphore m_event_semaphore;
static constexpr size_t m_max_event_count { 128 };
BAN::Vector<uint8_t> m_event_buffer;
const size_t m_event_size;
size_t m_event_tail { 0 };
size_t m_event_head { 0 };
size_t m_event_count { 0 };
};
}

View File

@ -60,7 +60,6 @@ namespace Kernel::Input
private:
BAN::RefPtr<PS2Device> m_devices[2];
Mutex m_mutex;
BAN::CircularQueue<Command, 128> m_command_queue;

View File

@ -1,15 +1,16 @@
#pragma once
#include <kernel/Input/PS2/Controller.h>
#include <kernel/Input/InputDevice.h>
#include <kernel/Interruptable.h>
namespace Kernel::Input
{
class PS2Device : public Interruptable, public InputDevice
class PS2Device : public CharacterDevice, public Interruptable
{
public:
virtual ~PS2Device() {}
virtual void send_initialize() = 0;
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) = 0;
@ -20,10 +21,17 @@ namespace Kernel::Input
virtual void handle_byte(uint8_t) = 0;
protected:
PS2Device(PS2Controller&, InputDevice::Type type);
virtual BAN::StringView name() const final override { return m_name; }
virtual dev_t rdev() const final override { return m_rdev; }
virtual void update() final override { m_controller.update_command_queue(); }
protected:
PS2Device(PS2Controller&);
private:
const dev_t m_rdev;
const BAN::String m_name;
PS2Controller& m_controller;
};

View File

@ -1,8 +1,11 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/CircularQueue.h>
#include <kernel/Input/PS2/Device.h>
#include <kernel/Input/PS2/Keymap.h>
#include <kernel/Semaphore.h>
#include <LibInput/KeyEvent.h>
namespace Kernel::Input
{
@ -17,15 +20,13 @@ namespace Kernel::Input
};
public:
static BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> create(PS2Controller&);
static BAN::ErrorOr<PS2Keyboard*> create(PS2Controller&);
virtual void send_initialize() override;
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override;
virtual void handle_byte(uint8_t) final override;
virtual void update() final override { m_controller.update_command_queue(); }
private:
PS2Keyboard(PS2Controller& controller);
@ -36,11 +37,22 @@ namespace Kernel::Input
uint8_t m_byte_index { 0 };
uint8_t m_scancode_set { 0xFF };
uint16_t m_modifiers { 0 };
BAN::CircularQueue<LibInput::RawKeyEvent, 50> m_event_queue;
SpinLock m_event_lock;
PS2Keymap m_keymap;
friend class BAN::RefPtr<PS2Keyboard>;
Semaphore m_semaphore;
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual bool can_read_impl() const override { return !m_event_queue.empty(); }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
};
}

View File

@ -1,6 +1,8 @@
#pragma once
#include <kernel/Input/PS2/Device.h>
#include <kernel/Semaphore.h>
#include <LibInput/MouseEvent.h>
namespace Kernel::Input
{
@ -14,15 +16,13 @@ namespace Kernel::Input
};
public:
static BAN::ErrorOr<BAN::RefPtr<PS2Mouse>> create(PS2Controller&);
static BAN::ErrorOr<PS2Mouse*> create(PS2Controller&);
virtual void send_initialize() override;
virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override { (void)command_data; (void)command_size; }
virtual void handle_byte(uint8_t) final override;
virtual void update() final override { m_controller.update_command_queue(); }
private:
PS2Mouse(PS2Controller& controller);
@ -36,7 +36,17 @@ namespace Kernel::Input
uint8_t m_mouse_id { 0x00 };
uint8_t m_button_mask { 0x00 };
friend class BAN::RefPtr<PS2Mouse>;
BAN::CircularQueue<LibInput::MouseEvent, 128> m_event_queue;
SpinLock m_event_lock;
Semaphore m_semaphore;
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual bool can_read_impl() const override { return !m_event_queue.empty(); }
virtual bool can_write_impl() const override { return false; }
virtual bool has_error_impl() const override { return false; }
};
}

View File

@ -1,10 +0,0 @@
#pragma once
namespace Kernel
{
class USBController
{
};
}

View File

@ -1,167 +0,0 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
namespace Kernel
{
namespace USB
{
enum class SpeedClass
{
None,
LowSpeed,
FullSpeed,
HighSpeed,
SuperSpeed,
};
enum class DeviceBaseClass : uint8_t
{
CommunicationAndCDCControl = 0x02,
Hub = 0x09,
BillboardDeviceClass = 0x11,
DiagnosticDevice = 0xDC,
Miscellaneous = 0xEF,
VendorSpecific = 0xFF,
};
enum class InterfaceBaseClass : uint8_t
{
Audio = 0x01,
CommunicationAndCDCControl = 0x02,
HID = 0x03,
Physical = 0x05,
Image = 0x06,
Printer = 0x07,
MassStorage = 0x08,
CDCData = 0x0A,
SmartCard = 0x0B,
ContentSecurity = 0x0D,
Video = 0x0E,
PersonalHealthcare = 0x0F,
AudioVideoDevice = 0x10,
USBTypeCBridgeClass = 0x12,
USBBulkDisplayProtocolDeviceClass = 0x13,
MCTPOverUSBProtocolEndpointDeviceClass = 0x14,
I3CDeviceClass = 0x3C,
DiagnosticDevice = 0xDC,
WirelessController = 0xE0,
Miscellaneous = 0xEF,
ApplicationSpecific = 0xFE,
VendorSpecific = 0xFF,
};
enum DescriptorType : uint8_t
{
DEVICE = 1,
CONFIGURATION = 2,
STRING = 3,
INTERFACE = 4,
ENDPOINT = 5,
DEVICE_QUALIFIER = 6,
OTHER_SPEED_CONFIGURATION = 7,
INTERFACE_POWER = 8,
};
enum RequestType : uint8_t
{
HostToDevice = 0b0 << 7,
DeviceToHost = 0b1 << 7,
Standard = 0b00 << 5,
Class = 0b01 << 5,
Vendor = 0b10 << 5,
Device = 0b00000,
Interface = 0b00001,
Endpoint = 0b00010,
Other = 0b00011,
};
enum Request : uint8_t
{
GET_STATUS = 0,
CLEAR_FEATURE = 1,
SET_FEATURE = 3,
SET_ADDRESS = 5,
GET_DESCRIPTOR = 6,
SET_DESCRIPTOR = 7,
GET_CONFIGURATION = 8,
SET_CONFIGURATION = 9,
GET_INTERFACE = 10,
SET_INTERFACE = 11,
SYNC_FRAME = 12,
};
}
struct USBDeviceDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdUSB;
uint8_t bDeviceClass;
uint8_t bDeviceSubClass;
uint8_t bDeviceProtocol;
uint8_t bMaxPacketSize0;
uint16_t idVendor;
uint16_t idProduct;
uint16_t bcdDevice;
uint8_t iManufacturer;
uint8_t iProduct;
uint8_t iSerialNumber;
uint8_t bNumConfigurations;
};
static_assert(sizeof(USBDeviceDescriptor) == 18);
struct USBConfigurationDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength __attribute__((packed));
uint8_t bNumInterfaces;
uint8_t bConfigurationValue;
uint8_t iConfiguration;
uint8_t bmAttributes;
uint8_t bMaxPower;
};
static_assert(sizeof(USBConfigurationDescriptor) == 9);
static constexpr size_t foo = sizeof(USBConfigurationDescriptor);
struct USBInterfaceDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bInterfaceNumber;
uint8_t bAlternateSetting;
uint8_t bNumEndpoints;
uint8_t bInterfaceClass;
uint8_t bInterfaceSubClass;
uint8_t bInterfaceProtocol;
uint8_t iInterface;
};
static_assert(sizeof(USBInterfaceDescriptor) == 9);
struct USBEndpointDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize __attribute__((packed));
uint8_t bInterval;
};
static_assert(sizeof(USBEndpointDescriptor) == 7);
struct USBDeviceRequest
{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
};
static_assert(sizeof(USBDeviceRequest) == 8);
}

View File

@ -1,83 +0,0 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/NoCopyMove.h>
#include <kernel/Memory/DMARegion.h>
#include <kernel/USB/USBManager.h>
#include <kernel/USB/Controller.h>
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);
BAN_NON_MOVABLE(USBDevice);
public:
struct EndpointDescriptor
{
USBEndpointDescriptor descriptor;
};
struct InterfaceDescriptor
{
USBInterfaceDescriptor descriptor;
BAN::Vector<EndpointDescriptor> endpoints;
BAN::Vector<BAN::Vector<uint8_t>> misc_descriptors;
};
struct ConfigurationDescriptor
{
USBConfigurationDescriptor desciptor;
BAN::Vector<InterfaceDescriptor> interfaces;
};
struct DeviceDescriptor
{
USBDeviceDescriptor descriptor;
BAN::Vector<ConfigurationDescriptor> configurations;
};
public:
USBDevice() = default;
virtual ~USBDevice() = default;
BAN::ErrorOr<void> initialize();
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:
BAN::ErrorOr<ConfigurationDescriptor> parse_configuration(size_t index);
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

@ -1,94 +0,0 @@
#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

@ -1,34 +0,0 @@
#pragma once
#include <kernel/USB/HID/HIDDriver.h>
namespace Kernel
{
class USBKeyboard final : public USBHIDDevice
{
BAN_NON_COPYABLE(USBKeyboard);
BAN_NON_MOVABLE(USBKeyboard);
public:
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;
private:
USBKeyboard()
: USBHIDDevice(InputDevice::Type::Keyboard)
{}
~USBKeyboard() = default;
private:
BAN::Array<bool, 0x100> m_keyboard_state { false };
BAN::Array<bool, 0x100> m_keyboard_state_temp { false };
uint8_t m_toggle_mask { 0 };
friend class BAN::RefPtr<USBKeyboard>;
};
}

View File

@ -1,36 +0,0 @@
#pragma once
#include <kernel/USB/HID/HIDDriver.h>
namespace Kernel
{
class USBMouse final : public USBHIDDevice
{
BAN_NON_COPYABLE(USBMouse);
BAN_NON_MOVABLE(USBMouse);
public:
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;
private:
USBMouse()
: USBHIDDevice(InputDevice::Type::Mouse)
{}
~USBMouse() = default;
private:
BAN::Array<bool, 5> m_button_state { false };
BAN::Array<bool, 5> m_button_state_temp { false };
int64_t m_pointer_x { 0 };
int64_t m_pointer_y { 0 };
int64_t m_wheel { 0 };
friend class BAN::RefPtr<USBMouse>;
};
}

View File

@ -1,30 +0,0 @@
#pragma once
#include <kernel/PCI.h>
#include <kernel/USB/Controller.h>
#include <kernel/USB/Definitions.h>
namespace Kernel
{
class USBManager
{
BAN_NON_COPYABLE(USBManager);
BAN_NON_MOVABLE(USBManager);
public:
static BAN::ErrorOr<void> initialize();
static USBManager& get();
BAN::ErrorOr<void> add_controller(PCI::Device& pci_device);
private:
USBManager() = default;
private:
BAN::Vector<BAN::UniqPtr<USBController>> m_controllers;
friend class BAN::UniqPtr<USBManager>;
};
}

View File

@ -1,105 +0,0 @@
#pragma once
#include <BAN/Vector.h>
#include <kernel/Lock/Mutex.h>
#include <kernel/Memory/DMARegion.h>
#include <kernel/USB/USBManager.h>
#include <kernel/USB/XHCI/Definitions.h>
namespace Kernel
{
class XHCIDevice;
class XHCIController : public USBController, public Interruptable
{
BAN_NON_COPYABLE(XHCIController);
BAN_NON_MOVABLE(XHCIController);
public:
struct Port
{
uint8_t revision_major { 0 };
uint8_t revision_minor { 0 };
uint8_t slot_type { 0 };
uint8_t slot_id { 0 };
uint64_t speed_id_to_speed[0x10] {
0,
12'000'000,
1'500'000,
480'000'000,
5'000'000'000,
10'000'000'000,
5'000'000'000,
10'000'000'000,
};
};
public:
static BAN::ErrorOr<BAN::UniqPtr<XHCIController>> initialize(PCI::Device&);
void handle_irq() final override;
private:
XHCIController(PCI::Device& pci_device);
~XHCIController();
BAN::ErrorOr<void> initialize_impl();
BAN::ErrorOr<void> initialize_ports();
BAN::ErrorOr<void> initialize_primary_interrupter();
BAN::ErrorOr<void> reset_controller();
void port_updater_task();
BAN::ErrorOr<void> initialize_slot(int port_index);
BAN::ErrorOr<XHCI::TRB> send_command(const XHCI::TRB&);
void advance_command_enqueue();
bool context_size_set() { return capability_regs().hccparams1.context_size; }
const Port& port(uint32_t port_id) const { return m_ports[port_id - 1]; }
volatile XHCI::CapabilityRegs& capability_regs();
volatile XHCI::OperationalRegs& operational_regs();
volatile XHCI::RuntimeRegs& runtime_regs();
volatile uint32_t& doorbell_reg(uint32_t slot_id);
volatile uint64_t& dcbaa_reg(uint32_t slot_id);
const volatile XHCI::TRB& current_event_trb();
private:
static constexpr uint32_t m_command_ring_trb_count = 256;
static constexpr uint32_t m_event_ring_trb_count = 252;
Mutex m_mutex;
Process* m_port_updater { nullptr };
Semaphore m_port_semaphore;
BAN::Atomic<bool> m_port_changed { false };
PCI::Device& m_pci_device;
BAN::UniqPtr<PCI::BarRegion> m_configuration_bar;
BAN::UniqPtr<DMARegion> m_dcbaa_region;
BAN::UniqPtr<DMARegion> m_command_ring_region;
uint32_t m_command_enqueue { 0 };
bool m_command_cycle { 1 };
BAN::UniqPtr<DMARegion> m_event_ring_region;
uint32_t m_event_dequeue { 0 };
bool m_event_cycle { 1 };
BAN::Vector<XHCI::TRB> m_command_completions;
BAN::Vector<Port> m_ports;
BAN::Vector<BAN::UniqPtr<XHCIDevice>> m_slots;
friend class XHCIDevice;
friend class BAN::UniqPtr<XHCIController>;
};
}

View File

@ -1,626 +0,0 @@
#pragma once
#include <stdint.h>
namespace Kernel::XHCI
{
struct CapabilityRegs
{
uint32_t caplength : 8;
uint32_t : 8;
uint32_t minor_revision : 8;
uint32_t major_revision : 8;
union
{
uint32_t hcsparams1_raw;
struct
{
uint32_t max_slots : 8;
uint32_t max_interrupters : 11;
uint32_t : 5;
uint32_t max_ports : 8;
} hcsparams1;
};
union
{
uint32_t hcsparams2_raw;
struct
{
uint32_t isochronous_scheduling_threshold : 4;
uint32_t event_ring_segment_table_max : 4;
uint32_t : 13;
uint32_t max_scratchpad_buffers_hi : 5;
uint32_t scratchpad_restore : 1;
uint32_t max_scratchpad_buffers_lo : 5;
} hcsparams2;
};
union
{
uint32_t hcsparams3_raw;
struct
{
uint32_t u1_device_exit_latency : 8;
uint32_t : 8;
uint32_t u2_device_exit_latency : 16;
} hcsparams3;
};
union
{
uint32_t hccparams1_raw;
struct
{
uint32_t addressing_capability64 : 1;
uint32_t bw_negotation_capability : 1;
uint32_t context_size : 1;
uint32_t port_power_control : 1;
uint32_t port_indicators : 1;
uint32_t light_hc_reset_capability : 1;
uint32_t latency_tolerance_messaging_capability : 1;
uint32_t no_secondary_sid_support : 1;
uint32_t parse_all_event_data : 1;
uint32_t stopped_short_packet_capability : 1;
uint32_t stopped_edtla_capability : 1;
uint32_t contiguous_frame_id_capability : 1;
uint32_t maximum_primary_stream_array_size : 4;
uint32_t xhci_extended_capabilities_pointer : 16;
} hccparams1;
};
uint32_t dboff;
uint32_t rstoff;
union
{
uint32_t hccparams2_raw;
struct
{
uint32_t u3_entry_capability : 1;
uint32_t configure_endpoint_command_max_latency_too_large_capability : 1;
uint32_t force_save_context_capability : 1;
uint32_t compliance_transition_capability : 1;
uint32_t large_esit_payload_capability : 1;
uint32_t configuration_information_capability : 1;
uint32_t extended_tbc_capability : 1;
uint32_t extended_tbc_trb_status_capability : 1;
uint32_t get_set_extended_property_capability : 1;
uint32_t virtualiaztion_based_trusted_io_capability : 1;
uint32_t : 22;
} hccparams2;
};
};
static_assert(sizeof(CapabilityRegs) == 0x20);
struct PortRegs
{
uint32_t portsc;
uint32_t portmsc;
uint32_t portli;
uint32_t porthlpmc;
};
static_assert(sizeof(PortRegs) == 0x10);
struct OperationalRegs
{
union
{
uint32_t usbcmd_raw;
struct
{
uint32_t run_stop : 1;
uint32_t host_controller_reset : 1;
uint32_t interrupter_enable : 1;
uint32_t host_system_error_enable : 1;
uint32_t : 3;
uint32_t light_host_controller_reset : 1;
uint32_t controller_save_state : 1;
uint32_t controller_restore_state : 1;
uint32_t enable_wrap_event : 1;
uint32_t enable_u3_mfindex_stop : 1;
uint32_t : 1;
uint32_t cem_enable : 1;
uint32_t extended_tbc_enable : 1;
uint32_t extended_tbc_trb_status_enable : 1;
uint32_t vtio_enable : 1;
uint32_t : 15;
} usbcmd;
};
uint32_t usbsts;
uint32_t pagesize;
uint32_t __reserved0[2];
uint32_t dnctrl;
uint32_t crcr_lo;
uint32_t crcr_hi;
uint32_t __reserved1[4];
uint32_t dcbaap_lo;
uint32_t dcbaap_hi;
union
{
uint32_t config_raw;
struct
{
uint32_t max_device_slots_enabled : 8;
uint32_t u3_entry_enable : 1;
uint32_t configuration_information_enable : 1;
uint32_t : 22;
} config;
};
uint32_t __reserved2[241];
PortRegs ports[];
};
static_assert(sizeof(OperationalRegs) == 0x400);
struct InterrupterRegs
{
uint32_t iman;
uint32_t imod;
uint32_t erstsz;
uint32_t __reserved;
uint64_t erstba;
uint64_t erdp;
};
static_assert(sizeof(InterrupterRegs) == 0x20);
struct RuntimeRegs
{
uint32_t mfindex;
uint32_t __reserved[7];
InterrupterRegs irs[];
};
static_assert(sizeof(RuntimeRegs) == 0x20);
struct TRB
{
union
{
struct
{
uint64_t parameter;
uint32_t status;
uint16_t cycle : 1;
uint16_t ent : 1;
uint16_t : 8;
uint16_t trb_type : 6;
uint16_t control;
};
struct
{
uint32_t dword0;
uint32_t dword1;
uint32_t dword2;
uint32_t dword3;
} raw;
struct
{
uint64_t data_buffer_pointer : 64;
uint32_t trb_transfer_length : 17;
uint32_t td_size : 5;
uint32_t interrupt_target : 10;
uint32_t cycle_bit : 1;
uint32_t evaluate_next_trb : 1;
uint32_t interrupt_on_short_packet : 1;
uint32_t no_snoop : 1;
uint32_t chain_bit : 1;
uint32_t interrupt_on_completion : 1;
uint32_t immediate_data : 1;
uint32_t : 2;
uint32_t block_event_interrupt : 1;
uint32_t trb_type : 6;
uint32_t : 16;
} normal;
struct
{
uint32_t bmRequestType : 8;
uint32_t bRequest : 8;
uint32_t wValue : 16;
uint32_t wIndex : 16;
uint32_t wLength : 16;
uint32_t trb_transfer_length : 17;
uint32_t : 5;
uint32_t interrupt_target : 10;
uint32_t cycle_bit : 1;
uint32_t : 4;
uint32_t interrupt_on_completion : 1;
uint32_t immediate_data : 1;
uint32_t : 3;
uint32_t trb_type : 6;
uint32_t transfer_type : 2;
uint32_t : 14;
} setup_stage;
struct
{
uint64_t data_buffer_pointer : 64;
uint32_t trb_transfer_length : 17;
uint32_t td_size : 5;
uint32_t interrupt_target : 10;
uint32_t cycle_bit : 1;
uint32_t evaluate_next_trb : 1;
uint32_t interrupt_on_short_packet : 1;
uint32_t no_snoop : 1;
uint32_t chain_bit : 1;
uint32_t interrupt_on_completion : 1;
uint32_t immediate_data : 1;
uint32_t : 3;
uint32_t trb_type : 6;
uint32_t direction : 1;
uint32_t : 15;
} data_stage;
struct
{
uint32_t : 32;
uint32_t : 32;
uint32_t : 22;
uint32_t interrupter_target : 10;
uint32_t cycle_bit : 1;
uint32_t evaluate_next_trb : 1;
uint32_t : 2;
uint32_t chain_bit : 1;
uint32_t interrupt_on_completion : 1;
uint32_t : 4;
uint32_t trb_type : 6;
uint32_t direction : 1;
uint32_t : 15;
} status_stage;
struct
{
uint64_t trb_pointer : 64;
uint32_t trb_transfer_length : 24;
uint32_t completion_code : 8;
uint32_t cycle_bit : 1;
uint32_t : 1;
uint32_t event_data : 1;
uint32_t : 7;
uint32_t trb_type : 6;
uint32_t endpoint_id : 5;
uint32_t : 3;
uint32_t slot_id : 8;
} transfer_event;
struct
{
uint64_t command_trb_pointer : 64;
uint32_t command_completion_parameter : 24;
uint32_t completion_code : 8;
uint32_t cycle_bit : 1;
uint32_t : 9;
uint32_t trb_type : 6;
uint32_t vf_id : 8;
uint32_t slot_id : 8;
} command_completion_event;
struct
{
uint32_t : 24;
uint32_t port_id : 8;
uint32_t : 32;
uint32_t : 24;
uint32_t completion_code : 8;
uint32_t cycle : 1;
uint32_t : 9;
uint32_t trb_type : 6;
uint32_t : 16;
} port_status_chage_event;
struct
{
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
uint32_t cycle : 1;
uint32_t : 9;
uint32_t trb_type : 6;
uint32_t slot_type : 5;
uint32_t : 11;
} enable_slot_command;
struct
{
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
uint32_t cycle : 1;
uint32_t : 9;
uint32_t trb_type : 6;
uint32_t : 8;
uint32_t slot_id : 8;
} disable_slot_command;
struct
{
uint64_t input_context_pointer : 64;
uint32_t : 32;
uint32_t cycle_bit : 1;
uint32_t : 8;
uint32_t block_set_address_request : 1;
uint32_t trb_type : 6;
uint32_t : 8;
uint32_t slot_id : 8;
} address_device_command;
struct
{
uint64_t input_context_pointer : 64;
uint32_t : 32;
uint32_t cycle_bit : 1;
uint32_t : 8;
uint32_t deconfigure : 1;
uint32_t trb_type : 6;
uint32_t : 8;
uint32_t slot_id : 8;
} configure_endpoint_command;
struct
{
uint64_t ring_segment_ponter : 64;
uint32_t : 22;
uint32_t interrupter_target : 10;
uint32_t cycle_bit : 1;
uint32_t toggle_cycle : 1;
uint32_t : 2;
uint32_t chain_bit : 1;
uint32_t interrupt_on_completion : 1;
uint32_t : 4;
uint32_t trb_type : 6;
uint32_t : 16;
} link_trb;
};
};
static_assert(sizeof(TRB) == 0x10);
struct EventRingTableEntry
{
uint64_t rsba;
uint32_t rsz;
uint32_t __reserved;
};
static_assert(sizeof(EventRingTableEntry) == 0x10);
struct ExtendedCap
{
uint32_t capability_id : 8;
uint32_t next_capability : 8;
uint32_t : 16;
};
static_assert(sizeof(ExtendedCap) == 4);
struct SupportedPrococolCap
{
uint32_t capability_id : 8;
uint32_t next_capability : 8;
uint32_t minor_revision : 8;
uint32_t major_revision : 8;
uint32_t name_string : 32;
uint32_t compatible_port_offset : 8;
uint32_t compatible_port_count : 8;
uint32_t protocol_defied : 12;
uint32_t protocol_speed_id_count : 4;
uint32_t protocol_slot_type : 5;
uint32_t : 27;
};
static_assert(sizeof(SupportedPrococolCap) == 0x10);
struct SlotContext
{
uint32_t route_string : 20;
uint32_t speed : 4;
uint32_t : 1;
uint32_t multi_tt : 1;
uint32_t hub : 1;
uint32_t context_entries : 5;
uint16_t max_exit_latency;
uint8_t root_hub_port_number;
uint8_t number_of_ports;
uint32_t parent_hub_slot_id : 8;
uint32_t parent_port_number : 8;
uint32_t tt_think_time : 2;
uint32_t : 4;
uint32_t interrupter_target : 10;
uint32_t usb_device_address : 8;
uint32_t : 19;
uint32_t slot_state : 5;
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
};
static_assert(sizeof(SlotContext) == 0x20);
struct EndpointContext
{
uint32_t endpoint_state : 3;
uint32_t : 5;
uint32_t mult : 2;
uint32_t max_primary_streams : 5;
uint32_t linear_stream_array : 1;
uint32_t interval : 8;
uint32_t max_esit_payload_hi : 8;
uint32_t : 1;
uint32_t error_count : 2;
uint32_t endpoint_type : 3;
uint32_t : 1;
uint32_t host_initiate_disable : 1;
uint32_t max_burst_size : 8;
uint32_t max_packet_size : 16;
// LSB is dequeue cycle state
uint64_t tr_dequeue_pointer;
uint32_t average_trb_length : 16;
uint32_t max_esit_payload_lo : 16;
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
};
static_assert(sizeof(EndpointContext) == 0x20);
struct InputControlContext
{
uint32_t drop_context_flags;
uint32_t add_context_flags;
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
uint32_t : 32;
uint8_t configuration_value;
uint8_t interface_number;
uint8_t alternate_setting;
uint8_t : 8;
};
static_assert(sizeof(InputControlContext) == 0x20);
enum USBSTS
{
HCHalted = 1 << 0,
HostSystemError = 1 << 2,
EventInterrupt = 1 << 3,
PortChangeDetect = 1 << 4,
SaveStateStatus = 1 << 8,
RstoreStateStatus = 1 << 9,
SaveRestoreError = 1 << 10,
ControllerNotReady = 1 << 11,
HostControllerError = 1 << 12,
};
enum CRCR : uint32_t
{
RingCycleState = 1 << 0,
CommandStop = 1 << 1,
CommandAbort = 1 << 2,
CommandRingRunning = 1 << 3,
};
enum IMAN : uint32_t
{
InterruptPending = 1 << 0,
InterruptEnable = 1 << 1,
};
enum ERDP
{
EventHandlerBusy = 1 << 3,
};
enum PORTSC : uint32_t
{
CCS = 1u << 0,
PED = 1u << 1,
OCA = 1u << 3,
PR = 1u << 4,
PP = 1u << 9,
LWS = 1u << 16,
CSC = 1u << 17,
PEC = 1u << 18,
WRC = 1u << 19,
OCC = 1u << 20,
PRC = 1u << 21,
PLC = 1u << 22,
CEC = 1u << 23,
CAS = 1u << 24,
WCE = 1u << 25,
WDE = 1u << 26,
WOE = 1u << 27,
DR = 1u << 30,
WPR = 1u << 31,
PLS_SHIFT = 5,
PLS_MASK = 0xF,
PORT_SPEED_SHIFT = 10,
PORT_SPEED_MASK = 0xF,
PIC_SHIFT = 14,
PIC_MASK = 0x3,
};
enum ExtendedCapabilityID : uint8_t
{
USBLegacySupport = 1,
SupportedProtocol = 2,
ExtendedPowerManagement = 3,
IOVirtualization = 4,
MessageInterrupt = 5,
LocalMemory = 6,
USBDebugCapability = 10,
ExtendedMessageInterrupt = 17,
};
enum TRBType
{
Normal = 1,
SetupStage = 2,
DataStage = 3,
StatusStage = 4,
Link = 6,
EnableSlotCommand = 9,
DisableSlotCommand = 10,
AddressDeviceCommand = 11,
ConfigureEndpointCommand = 12,
EvaluateContextCommand = 13,
ResetEndpointCommand = 14,
StopEndpointCommand = 15,
SetTRDequeuePointerCommand = 16,
ResetDeviceCommand = 17,
ForceEventCommand = 18,
NegotiateBandwidthCommand = 19,
SetLatencyToleranceValueCommand = 20,
GetPortBandwidthCommand = 21,
ForceHeaderCommand = 22,
NoOpCommand = 23,
GetExtendedPropertyCommand = 24,
SetExtendedPropertyCommand = 25,
TransferEvent = 32,
CommandCompletionEvent = 33,
PortStatusChangeEvent = 34,
BandwidthRequestEvent = 35,
DoorbellEvent = 36,
HostControllerEvent = 37,
DeviceNotificationEvent = 38,
MFINDEXWrapEvent = 39,
};
enum EndpointType
{
IsochOut = 1,
BulkOut = 2,
InterruptOut = 3,
Control = 4,
IsochIn = 5,
BulkIn = 6,
InterruptIn = 7,
};
}

View File

@ -1,75 +0,0 @@
#pragma once
#include <BAN/Array.h>
#include <BAN/RefPtr.h>
#include <kernel/USB/Device.h>
#include <kernel/USB/XHCI/Controller.h>
namespace Kernel
{
class XHCIDevice final : public USBDevice
{
BAN_NON_COPYABLE(XHCIDevice);
BAN_NON_MOVABLE(XHCIDevice);
public:
struct Endpoint
{
BAN::UniqPtr<DMARegion> transfer_ring;
uint32_t max_packet_size { 0 };
uint32_t dequeue_index { 0 };
uint32_t enqueue_index { 0 };
bool cycle_bit { 1 };
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&);
protected:
BAN::ErrorOr<void> initialize_control_endpoint() override;
private:
XHCIDevice(XHCIController& controller, uint32_t port_id, uint32_t slot_id)
: m_controller(controller)
, m_port_id(port_id)
, m_slot_id(slot_id)
{}
~XHCIDevice();
BAN::ErrorOr<void> update_actual_max_packet_size();
void on_interrupt_endpoint_event(XHCI::TRB);
void advance_endpoint_enqueue(Endpoint&, bool chain);
private:
static constexpr uint32_t m_transfer_ring_trb_count = PAGE_SIZE / sizeof(XHCI::TRB);
XHCIController& m_controller;
const uint32_t m_port_id;
const uint32_t m_slot_id;
Mutex m_mutex;
BAN::UniqPtr<DMARegion> m_input_context;
BAN::UniqPtr<DMARegion> m_output_context;
BAN::Array<Endpoint, 31> m_endpoints;
friend class BAN::UniqPtr<XHCIDevice>;
};
}

View File

@ -119,4 +119,10 @@ namespace Kernel
MUST(static_cast<TmpDirectoryInode*>(root_inode().ptr())->link_inode(*inode, path));
}
int DevFileSystem::get_next_input_device() const
{
static BAN::Atomic<dev_t> next_dev = 0;
return next_dev++;
}
}

View File

@ -1,104 +0,0 @@
#include <kernel/Device/DeviceNumbers.h>
#include <kernel/Input/InputDevice.h>
#include <kernel/Lock/LockGuard.h>
#include <LibInput/KeyEvent.h>
#include <LibInput/MouseEvent.h>
#include <sys/sysmacros.h>
namespace Kernel
{
static BAN::Atomic<uint16_t> s_next_keyboard { 0 };
static BAN::Atomic<uint16_t> s_next_mouse { 0 };
static const char* get_name_format(InputDevice::Type type)
{
switch (type)
{
case InputDevice::Type::Keyboard:
return "keyboard{}";
case InputDevice::Type::Mouse:
return "mouse{}";
}
ASSERT_NOT_REACHED();
}
static dev_t get_rdev(InputDevice::Type type)
{
switch (type)
{
case InputDevice::Type::Keyboard:
return makedev(DeviceNumber::Keyboard, s_next_keyboard++);
case InputDevice::Type::Mouse:
return makedev(DeviceNumber::Mouse, s_next_mouse++);
}
ASSERT_NOT_REACHED();
}
static size_t get_event_size(InputDevice::Type type)
{
switch (type)
{
case InputDevice::Type::Keyboard:
return sizeof(LibInput::RawKeyEvent);
case InputDevice::Type::Mouse:
return sizeof(LibInput::MouseEvent);
}
ASSERT_NOT_REACHED();
}
InputDevice::InputDevice(Type type)
: CharacterDevice(0440, 0, 901)
, m_rdev(get_rdev(type))
, m_name(MUST(BAN::String::formatted(get_name_format(type), minor(m_rdev))))
, m_event_size(get_event_size(type))
{
MUST(m_event_buffer.resize(m_event_size * m_max_event_count, 0));
}
void InputDevice::add_event(BAN::ConstByteSpan event)
{
SpinLockGuard _(m_event_lock);
ASSERT(event.size() == m_event_size);
if (m_event_count == m_max_event_count)
{
m_event_tail = (m_event_tail + 1) % m_max_event_count;
m_event_count--;
}
memcpy(&m_event_buffer[m_event_head * m_event_size], event.data(), m_event_size);
m_event_head = (m_event_head + 1) % m_max_event_count;
m_event_count++;
m_event_semaphore.unblock();
}
BAN::ErrorOr<size_t> InputDevice::read_impl(off_t, BAN::ByteSpan buffer)
{
if (buffer.size() < m_event_size)
return BAN::Error::from_errno(ENOBUFS);
auto state = m_event_lock.lock();
while (m_event_count == 0)
{
m_event_lock.unlock(state);
{
LockFreeGuard _(m_mutex);
TRY(Thread::current().block_or_eintr_indefinite(m_event_semaphore));
}
state = m_event_lock.lock();
}
memcpy(buffer.data(), &m_event_buffer[m_event_tail * m_event_size], m_event_size);
m_event_tail = (m_event_tail + 1) % m_max_event_count;
m_event_count--;
m_event_lock.unlock(state);
return m_event_size;
}
}

View File

@ -89,9 +89,9 @@ namespace Kernel::Input
uint8_t PS2Controller::get_device_index(PS2Device* device) const
{
ASSERT(device);
if (m_devices[0].ptr() == device)
if (m_devices[0] && device == m_devices[0].ptr())
return 0;
if (m_devices[1].ptr() == device)
if (m_devices[1] && device == m_devices[1].ptr())
return 1;
ASSERT_NOT_REACHED();
}
@ -359,12 +359,12 @@ namespace Kernel::Input
TRY(send_command(PS2::Command::WRITE_CONFIG, config));
// Send device initialization sequence after interrupts are enabled
for (uint8_t i = 0; i < 2; i++)
for (uint8_t device = 0; device < 2; device++)
{
if (!m_devices[i])
if (!m_devices[device])
continue;
m_devices[i]->send_initialize();
DevFileSystem::get().add_device(m_devices[i]);
m_devices[device]->send_initialize();
DevFileSystem::get().add_device(m_devices[device]);
}
return {};

View File

@ -1,13 +1,18 @@
#include <kernel/Device/DeviceNumbers.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Input/PS2/Config.h>
#include <kernel/Input/PS2/Device.h>
#include <kernel/IO.h>
#include <sys/sysmacros.h>
namespace Kernel::Input
{
PS2Device::PS2Device(PS2Controller& controller, InputDevice::Type type)
: InputDevice(type)
PS2Device::PS2Device(PS2Controller& controller)
: CharacterDevice(0440, 0, 901)
, m_rdev(makedev(DeviceNumber::Input, DevFileSystem::get().get_next_input_device()))
, m_name(MUST(BAN::String::formatted("input{}", minor(m_rdev))))
, m_controller(controller)
{ }

View File

@ -4,18 +4,20 @@
#include <kernel/Input/PS2/Keyboard.h>
#include <kernel/Thread.h>
#include <LibInput/KeyboardLayout.h>
#include <LibInput/KeyEvent.h>
namespace Kernel::Input
{
BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> PS2Keyboard::create(PS2Controller& controller)
BAN::ErrorOr<PS2Keyboard*> PS2Keyboard::create(PS2Controller& controller)
{
return TRY(BAN::RefPtr<PS2Keyboard>::create(controller));
PS2Keyboard* keyboard = new PS2Keyboard(controller);
if (keyboard == nullptr)
return BAN::Error::from_errno(ENOMEM);
return keyboard;
}
PS2Keyboard::PS2Keyboard(PS2Controller& controller)
: PS2Device(controller, InputDevice::Type::Keyboard)
: PS2Device(controller)
{ }
void PS2Keyboard::send_initialize()
@ -164,7 +166,17 @@ namespace Kernel::Input
RawKeyEvent event;
event.modifier = m_modifiers | (released ? 0 : KeyModifier::Pressed);
event.keycode = keycode.value();
add_event(BAN::ConstByteSpan::from(event));
SpinLockGuard _(m_event_lock);
if (m_event_queue.full())
{
dwarnln("PS/2 event queue full");
m_event_queue.pop();
}
m_event_queue.push(event);
m_semaphore.unblock();
}
void PS2Keyboard::update_leds()
@ -181,4 +193,30 @@ namespace Kernel::Input
append_command_queue(Command::SET_LEDS, new_leds, 0);
}
BAN::ErrorOr<size_t> PS2Keyboard::read_impl(off_t, BAN::ByteSpan buffer)
{
using LibInput::RawKeyEvent;
if (buffer.size() < sizeof(RawKeyEvent))
return BAN::Error::from_errno(ENOBUFS);
auto state = m_event_lock.lock();
while (m_event_queue.empty())
{
m_event_lock.unlock(state);
{
LockFreeGuard _(m_mutex);
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
}
state = m_event_lock.lock();
}
buffer.as<RawKeyEvent>() = m_event_queue.front();
m_event_queue.pop();
m_event_lock.unlock(state);
return sizeof(RawKeyEvent);
}
}

View File

@ -3,7 +3,6 @@
#include <kernel/Input/PS2/Config.h>
#include <kernel/Input/PS2/Mouse.h>
#include <kernel/Thread.h>
#include <LibInput/MouseEvent.h>
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
@ -11,13 +10,16 @@
namespace Kernel::Input
{
BAN::ErrorOr<BAN::RefPtr<PS2Mouse>> PS2Mouse::create(PS2Controller& controller)
BAN::ErrorOr<PS2Mouse*> PS2Mouse::create(PS2Controller& controller)
{
return TRY(BAN::RefPtr<PS2Mouse>::create(controller));
PS2Mouse* mouse = new PS2Mouse(controller);
if (mouse == nullptr)
return BAN::Error::from_errno(ENOMEM);
return mouse;
}
PS2Mouse::PS2Mouse(PS2Controller& controller)
: PS2Device(controller, InputDevice::Type::Mouse)
: PS2Device(controller)
{ }
void PS2Mouse::send_initialize()
@ -108,6 +110,10 @@ namespace Kernel::Input
m_byte_index = 0;
// Max 7 events, one for each (5) button, one for movement, one for scroll
BAN::Array<MouseEvent, 7> events;
int event_count = 0;
auto button_index_to_button =
[](int index) -> MouseButton
{
@ -131,11 +137,10 @@ namespace Kernel::Input
if ((new_button_mask & (1 << i)) == (m_button_mask & (1 << i)))
continue;
MouseEvent event;
auto& event = events[event_count++];
event.type = MouseEventType::MouseButtonEvent;
event.button_event.button = button_index_to_button(i);
event.button_event.pressed = !!(new_button_mask & (1 << i));
add_event(BAN::ConstByteSpan::from(event));
}
m_button_mask = new_button_mask;
@ -143,20 +148,71 @@ namespace Kernel::Input
if (rel_x || rel_y)
{
MouseEvent event;
auto& event = events[event_count++];
event.type = MouseEventType::MouseMoveEvent;
event.move_event.rel_x = rel_x;
event.move_event.rel_y = rel_y;
add_event(BAN::ConstByteSpan::from(event));
}
if (rel_z)
{
MouseEvent event;
auto& event = events[event_count++];
event.type = MouseEventType::MouseScrollEvent;
event.scroll_event.scroll = rel_z;
add_event(BAN::ConstByteSpan::from(event));
}
SpinLockGuard _(m_event_lock);
for (int i = 0; i < event_count; i++)
{
if (!m_event_queue.empty() && m_event_queue.back().type == events[i].type)
{
if (events[i].type == MouseEventType::MouseMoveEvent)
{
m_event_queue.back().move_event.rel_x += events[i].move_event.rel_x;
m_event_queue.back().move_event.rel_y += events[i].move_event.rel_y;
continue;
}
if (events[i].type == MouseEventType::MouseScrollEvent)
{
m_event_queue.back().scroll_event.scroll += events[i].scroll_event.scroll;
continue;
}
}
if (m_event_queue.full())
{
dwarnln("PS/2 event queue full");
m_event_queue.pop();
}
m_event_queue.push(events[i]);
}
m_semaphore.unblock();
}
BAN::ErrorOr<size_t> PS2Mouse::read_impl(off_t, BAN::ByteSpan buffer)
{
using LibInput::MouseEvent;
if (buffer.size() < sizeof(MouseEvent))
return BAN::Error::from_errno(ENOBUFS);
auto state = m_event_lock.lock();
while (m_event_queue.empty())
{
m_event_lock.unlock(state);
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
state = m_event_lock.lock();
}
buffer.as<MouseEvent>() = m_event_queue.front();
m_event_queue.pop();
m_event_lock.unlock(state);
return sizeof(MouseEvent);
}
}

View File

@ -8,7 +8,6 @@
#include <kernel/Storage/ATA/AHCI/Controller.h>
#include <kernel/Storage/ATA/ATAController.h>
#include <kernel/Storage/NVMe/Controller.h>
#include <kernel/USB/USBManager.h>
#define INVALID_VENDOR 0xFFFF
#define MULTI_FUNCTION 0x80
@ -210,20 +209,6 @@ namespace Kernel::PCI
dprintln("{}", res.error());
break;
}
case 0x0C:
{
switch (pci_device.subclass())
{
case 0x03:
if (auto res = USBManager::get().add_controller(pci_device); res.is_error())
dprintln("{}", res.error());
break;
default:
dprintln("unsupported serail bus controller (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
break;
}
break;
}
default:
break;
}

View File

@ -83,7 +83,7 @@ namespace Kernel
Process::create_kernel(
[](void*)
{
auto file_or_error = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/keyboard0"_sv, O_RDONLY);
auto file_or_error = VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, "/dev/input0"_sv, O_RDONLY);
if (file_or_error.is_error())
{
dprintln("no input device found");

View File

@ -1,327 +0,0 @@
#include <kernel/Memory/DMARegion.h>
#include <kernel/USB/Device.h>
#include <kernel/USB/HID/HIDDriver.h>
#define DEBUG_USB 0
#define USB_DUMP_DESCRIPTORS 0
namespace Kernel
{
BAN::ErrorOr<void> USBDevice::initialize()
{
TRY(initialize_control_endpoint());
m_dma_buffer = TRY(DMARegion::create(1024));
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Standard | USB::RequestType::Device;
request.bRequest = USB::Request::GET_DESCRIPTOR;
request.wValue = 0x0100;
request.wIndex = 0;
request.wLength = sizeof(USBDeviceDescriptor);
auto transferred = TRY(send_request(request, m_dma_buffer->paddr()));
m_descriptor.descriptor = *reinterpret_cast<const USBDeviceDescriptor*>(m_dma_buffer->vaddr());
if (transferred < sizeof(USBDeviceDescriptor) || transferred < m_descriptor.descriptor.bLength)
{
dprintln("invalid device descriptor response {}");
return BAN::Error::from_errno(EINVAL);
}
dprintln_if(DEBUG_USB, "device has {} configurations", m_descriptor.descriptor.bNumConfigurations);
for (uint32_t i = 0; i < m_descriptor.descriptor.bNumConfigurations; i++)
if (auto opt_configuration = parse_configuration(i); !opt_configuration.is_error())
TRY(m_descriptor.configurations.push_back(opt_configuration.release_value()));
#if USB_DUMP_DESCRIPTORS
const auto& descriptor = m_descriptor.descriptor;
dprintln("device descriptor");
dprintln(" bLength: {}", descriptor.bLength);
dprintln(" bDescriptorType: {}", descriptor.bDescriptorType);
dprintln(" bcdUSB: {}", descriptor.bcdUSB);
dprintln(" bDeviceClass: {}", descriptor.bDeviceClass);
dprintln(" bDeviceSubClass: {}", descriptor.bDeviceSubClass);
dprintln(" bDeviceProtocol: {}", descriptor.bDeviceProtocol);
dprintln(" bMaxPacketSize0: {}", descriptor.bMaxPacketSize0);
dprintln(" idVendor: {}", descriptor.idVendor);
dprintln(" idProduct: {}", descriptor.idProduct);
dprintln(" bcdDevice: {}", descriptor.bcdDevice);
dprintln(" iManufacturer: {}", descriptor.iManufacturer);
dprintln(" iProduct: {}", descriptor.iProduct);
dprintln(" iSerialNumber: {}", descriptor.iSerialNumber);
dprintln(" bNumConfigurations: {}", descriptor.bNumConfigurations);
for (const auto& configuration : m_descriptor.configurations)
{
const auto& descriptor = configuration.desciptor;
dprintln(" configuration");
dprintln(" bLength: {}", descriptor.bLength);
dprintln(" bDescriptorType: {}", descriptor.bDescriptorType);
dprintln(" wTotalLength: {}", descriptor.wTotalLength);
dprintln(" bNumInterfaces: {}", descriptor.bNumInterfaces);
dprintln(" bConfigurationValue: {}", descriptor.bConfigurationValue);
dprintln(" iConfiguration: {}", descriptor.iConfiguration);
dprintln(" bmAttributes: {}", descriptor.bmAttributes);
dprintln(" bMaxPower: {}", descriptor.bMaxPower);
for (const auto& interface : configuration.interfaces)
{
const auto& descriptor = interface.descriptor;
dprintln(" interface");
dprintln(" bLength: {}", descriptor.bLength);
dprintln(" bDescriptorType: {}", descriptor.bDescriptorType);
dprintln(" bInterfaceNumber: {}", descriptor.bInterfaceNumber);
dprintln(" bAlternateSetting: {}", descriptor.bAlternateSetting);
dprintln(" bNumEndpoints: {}", descriptor.bNumEndpoints);
dprintln(" bInterfaceClass: {}", descriptor.bInterfaceClass);
dprintln(" bInterfaceSubClass: {}", descriptor.bInterfaceSubClass);
dprintln(" bInterfaceProtocol: {}", descriptor.bInterfaceProtocol);
dprintln(" iInterface: {}", descriptor.iInterface);
for (const auto& endpoint : interface.endpoints)
{
const auto& descriptor = endpoint.descriptor;
dprintln(" endpoint");
dprintln(" bLength: {}", descriptor.bLength);
dprintln(" bDescriptorType: {}", descriptor.bDescriptorType);
dprintln(" bEndpointAddress: {}", descriptor.bEndpointAddress);
dprintln(" bmAttributes: {}", descriptor.bmAttributes);
dprintln(" wMaxPacketSize: {}", +descriptor.wMaxPacketSize);
dprintln(" bInterval: {}", descriptor.bInterval);
}
}
}
#endif
if (m_descriptor.descriptor.bDeviceClass)
{
switch (static_cast<USB::DeviceBaseClass>(m_descriptor.descriptor.bDeviceClass))
{
case USB::DeviceBaseClass::CommunicationAndCDCControl:
dprintln_if(DEBUG_USB, "Found CommunicationAndCDCControl device");
return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::Hub:
dprintln_if(DEBUG_USB, "Found Hub device");
return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::BillboardDeviceClass:
dprintln_if(DEBUG_USB, "Found BillboardDeviceClass device");
return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::DiagnosticDevice:
dprintln_if(DEBUG_USB, "Found DiagnosticDevice device");
return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::Miscellaneous:
dprintln_if(DEBUG_USB, "Found Miscellaneous device");
return BAN::Error::from_errno(ENOTSUP);
case USB::DeviceBaseClass::VendorSpecific:
dprintln_if(DEBUG_USB, "Found VendorSpecific device");
return BAN::Error::from_errno(ENOTSUP);
default:
dprintln_if(DEBUG_USB, "Invalid device base class {2H}", m_descriptor.descriptor.bDeviceClass);
return BAN::Error::from_errno(EFAULT);
}
ASSERT_NOT_REACHED();
}
for (size_t i = 0; i < m_descriptor.configurations.size(); i++)
{
const auto& configuration = m_descriptor.configurations[i];
{
dprintln_if(DEBUG_USB, "Setting configuration 0x{2H}", configuration.desciptor.bConfigurationValue);
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Standard | USB::RequestType::Device;
request.bRequest = USB::Request::SET_CONFIGURATION;
request.wValue = configuration.desciptor.bConfigurationValue;
request.wIndex = 0;
request.wLength = 0;
TRY(send_request(request, 0));
}
for (size_t j = 0; j < configuration.interfaces.size(); j++)
{
const auto& interface = configuration.interfaces[j];
switch (static_cast<USB::InterfaceBaseClass>(interface.descriptor.bInterfaceClass))
{
case USB::InterfaceBaseClass::Audio:
dprintln_if(DEBUG_USB, "Found Audio interface");
break;
case USB::InterfaceBaseClass::CommunicationAndCDCControl:
dprintln_if(DEBUG_USB, "Found CommunicationAndCDCControl interface");
break;
case USB::InterfaceBaseClass::HID:
if (auto result = USBHIDDriver::create(*this, interface, j); !result.is_error())
m_class_driver = result.release_value();
break;
case USB::InterfaceBaseClass::Physical:
dprintln_if(DEBUG_USB, "Found Physical interface");
break;
case USB::InterfaceBaseClass::Image:
dprintln_if(DEBUG_USB, "Found Image interface");
break;
case USB::InterfaceBaseClass::Printer:
dprintln_if(DEBUG_USB, "Found Printer interface");
break;
case USB::InterfaceBaseClass::MassStorage:
dprintln_if(DEBUG_USB, "Found MassStorage interface");
break;
case USB::InterfaceBaseClass::CDCData:
dprintln_if(DEBUG_USB, "Found CDCData interface");
break;
case USB::InterfaceBaseClass::SmartCard:
dprintln_if(DEBUG_USB, "Found SmartCard interface");
break;
case USB::InterfaceBaseClass::ContentSecurity:
dprintln_if(DEBUG_USB, "Found ContentSecurity interface");
break;
case USB::InterfaceBaseClass::Video:
dprintln_if(DEBUG_USB, "Found Video interface");
break;
case USB::InterfaceBaseClass::PersonalHealthcare:
dprintln_if(DEBUG_USB, "Found PersonalHealthcare interface");
break;
case USB::InterfaceBaseClass::AudioVideoDevice:
dprintln_if(DEBUG_USB, "Found AudioVideoDevice interface");
break;
case USB::InterfaceBaseClass::USBTypeCBridgeClass:
dprintln_if(DEBUG_USB, "Found USBTypeCBridgeClass interface");
break;
case USB::InterfaceBaseClass::USBBulkDisplayProtocolDeviceClass:
dprintln_if(DEBUG_USB, "Found USBBulkDisplayProtocolDeviceClass interface");
break;
case USB::InterfaceBaseClass::MCTPOverUSBProtocolEndpointDeviceClass:
dprintln_if(DEBUG_USB, "Found MCTPOverUSBProtocolEndpointDeviceClass interface");
break;
case USB::InterfaceBaseClass::I3CDeviceClass:
dprintln_if(DEBUG_USB, "Found I3CDeviceClass interface");
break;
case USB::InterfaceBaseClass::DiagnosticDevice:
dprintln_if(DEBUG_USB, "Found DiagnosticDevice interface");
break;
case USB::InterfaceBaseClass::WirelessController:
dprintln_if(DEBUG_USB, "Found WirelessController interface");
break;
case USB::InterfaceBaseClass::Miscellaneous:
dprintln_if(DEBUG_USB, "Found Miscellaneous interface");
break;
case USB::InterfaceBaseClass::ApplicationSpecific:
dprintln_if(DEBUG_USB, "Found ApplicationSpecific interface");
break;
case USB::InterfaceBaseClass::VendorSpecific:
dprintln_if(DEBUG_USB, "Found VendorSpecific interface");
break;
default:
dprintln_if(DEBUG_USB, "Invalid interface base class {2H}", interface.descriptor.bInterfaceClass);
break;
}
if (m_class_driver)
{
dprintln("Successfully initialized USB interface");
return {};
}
}
}
return BAN::Error::from_errno(ENOTSUP);
}
BAN::ErrorOr<USBDevice::ConfigurationDescriptor> USBDevice::parse_configuration(size_t index)
{
{
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Standard | USB::RequestType::Device;
request.bRequest = USB::Request::GET_DESCRIPTOR;
request.wValue = 0x0200 | index;
request.wIndex = 0;
request.wLength = m_dma_buffer->size();
auto transferred = TRY(send_request(request, m_dma_buffer->paddr()));
auto configuration = *reinterpret_cast<const USBConfigurationDescriptor*>(m_dma_buffer->vaddr());
dprintln_if(DEBUG_USB, "configuration {} is {} bytes", index, +configuration.wTotalLength);
if (configuration.bLength < sizeof(USBConfigurationDescriptor) || transferred < configuration.wTotalLength)
{
dwarnln("invalid configuration descriptor size: {} length, {} total", configuration.bLength, +configuration.wTotalLength);
return BAN::Error::from_errno(EINVAL);
}
}
ConfigurationDescriptor configuration;
configuration.desciptor = *reinterpret_cast<const USBConfigurationDescriptor*>(m_dma_buffer->vaddr());
ptrdiff_t offset = configuration.desciptor.bLength;
while (offset < configuration.desciptor.wTotalLength)
{
const uint8_t length = *reinterpret_cast<const uint8_t*>(m_dma_buffer->vaddr() + offset + 0);
const uint8_t type = *reinterpret_cast<const uint8_t*>(m_dma_buffer->vaddr() + offset + 1);
switch (type)
{
case USB::DescriptorType::INTERFACE:
if (length < sizeof(USBInterfaceDescriptor))
{
dwarnln("invalid interface descriptor size {}", length);
return BAN::Error::from_errno(EINVAL);
}
TRY(configuration.interfaces.emplace_back(
*reinterpret_cast<const USBInterfaceDescriptor*>(m_dma_buffer->vaddr() + offset),
BAN::Vector<EndpointDescriptor>(),
BAN::Vector<BAN::Vector<uint8_t>>()
));
break;
case USB::DescriptorType::ENDPOINT:
if (length < sizeof(USBEndpointDescriptor))
{
dwarnln("invalid interface descriptor size {}", length);
return BAN::Error::from_errno(EINVAL);
}
if (configuration.interfaces.empty())
{
dwarnln("invalid endpoint descriptor before interface descriptor");
return BAN::Error::from_errno(EINVAL);
}
TRY(configuration.interfaces.back().endpoints.emplace_back(
*reinterpret_cast<const USBEndpointDescriptor*>(m_dma_buffer->vaddr() + offset)
));
break;
default:
if (configuration.interfaces.empty())
dprintln_if(DEBUG_USB, "skipping descriptor type {}", type);
else
{
BAN::Vector<uint8_t> descriptor;
TRY(descriptor.resize(length));
memcpy(descriptor.data(), reinterpret_cast<const void*>(m_dma_buffer->vaddr() + offset), length);
TRY(configuration.interfaces.back().misc_descriptors.push_back(BAN::move(descriptor)));
}
break;
}
offset += length;
}
return BAN::move(configuration);
}
void USBDevice::handle_input_data(BAN::ConstByteSpan data, uint8_t endpoint_id)
{
if (m_class_driver)
m_class_driver->handle_input_data(data, endpoint_id);
}
USB::SpeedClass USBDevice::determine_speed_class(uint64_t bits_per_second)
{
if (bits_per_second <= 1'500'000)
return USB::SpeedClass::LowSpeed;
if (bits_per_second <= 12'000'000)
return USB::SpeedClass::FullSpeed;
else if (bits_per_second <= 480'000'000)
return USB::SpeedClass::HighSpeed;
return USB::SpeedClass::SuperSpeed;
}
}

View File

@ -1,742 +0,0 @@
#include <BAN/ByteSpan.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/USB/HID/HIDDriver.h>
#include <kernel/USB/HID/Keyboard.h>
#include <kernel/USB/HID/Mouse.h>
#define DEBUG_HID 0
namespace Kernel
{
enum class HIDDescriptorType : uint8_t
{
HID = 0x21,
Report = 0x22,
Physical = 0x23,
};
struct HIDDescriptor
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
struct
{
uint8_t bDescriptorType;
uint16_t wItemLength;
} __attribute__((packed)) descriptors[];
} __attribute__((packed));
static_assert(sizeof(HIDDescriptor) == 6);
struct GlobalState
{
BAN::Optional<uint16_t> usage_page;
BAN::Optional<int32_t> logical_minimum;
BAN::Optional<int32_t> logical_maximum_signed;
BAN::Optional<int32_t> logical_maximum_unsigned;
BAN::Optional<int32_t> physical_minimum;
BAN::Optional<int32_t> physical_maximum;
// FIXME: support units
BAN::Optional<uint32_t> report_size;
// FIXME: support report id
BAN::Optional<uint32_t> report_count;
};
struct LocalState
{
BAN::Vector<uint32_t> usage_stack;
BAN::Optional<uint32_t> usage_minimum;
BAN::Optional<uint32_t> usage_maximum;
// FIXME: support all local items
};
using namespace USBHID;
#if DEBUG_HID
static void dump_hid_collection(const Collection& collection, size_t indent);
#endif
static BAN::ErrorOr<Collection> parse_report_descriptor(BAN::ConstByteSpan report_data);
BAN::ErrorOr<BAN::UniqPtr<USBHIDDriver>> USBHIDDriver::create(USBDevice& device, const USBDevice::InterfaceDescriptor& interface, uint8_t interface_index)
{
auto result = TRY(BAN::UniqPtr<USBHIDDriver>::create(device, interface, interface_index));
TRY(result->initialize());
return result;
}
USBHIDDriver::USBHIDDriver(USBDevice& device, const USBDevice::InterfaceDescriptor& interface, uint8_t interface_index)
: m_device(device)
, m_interface(interface)
, m_interface_index(interface_index)
{}
USBHIDDriver::~USBHIDDriver()
{}
BAN::ErrorOr<void> USBHIDDriver::initialize()
{
auto dma_buffer = TRY(DMARegion::create(1024));
ASSERT(static_cast<USB::InterfaceBaseClass>(m_interface.descriptor.bInterfaceClass) == USB::InterfaceBaseClass::HID);
size_t endpoint_index = static_cast<size_t>(-1);
for (size_t i = 0; i < m_interface.endpoints.size(); i++)
{
const auto& endpoint = m_interface.endpoints[i];
if (!(endpoint.descriptor.bEndpointAddress & 0x80))
continue;
if (endpoint.descriptor.bmAttributes != 0x03)
continue;
endpoint_index = i;
break;
}
if (endpoint_index >= m_interface.endpoints.size())
{
dwarnln("HID device does not contain IN interrupt endpoint");
return BAN::Error::from_errno(EFAULT);
}
bool hid_descriptor_invalid = false;
size_t hid_descriptor_index = static_cast<size_t>(-1);
for (size_t i = 0; i < m_interface.misc_descriptors.size(); i++)
{
if (static_cast<HIDDescriptorType>(m_interface.misc_descriptors[i][1]) != HIDDescriptorType::HID)
continue;
if (m_interface.misc_descriptors[i].size() < sizeof(HIDDescriptor))
hid_descriptor_invalid = true;
const auto& hid_descriptor = *reinterpret_cast<const HIDDescriptor*>(m_interface.misc_descriptors[i].data());
if (hid_descriptor.bLength != m_interface.misc_descriptors[i].size())
hid_descriptor_invalid = true;
if (hid_descriptor.bLength != sizeof(HIDDescriptor) + hid_descriptor.bNumDescriptors * 3)
hid_descriptor_invalid = true;
hid_descriptor_index = i;
break;
}
if (hid_descriptor_index >= m_interface.misc_descriptors.size())
{
dwarnln("HID device does not contain HID descriptor");
return BAN::Error::from_errno(EFAULT);
}
if (hid_descriptor_invalid)
{
dwarnln("HID device contains an invalid HID descriptor");
return BAN::Error::from_errno(EFAULT);
}
// If this device supports boot protocol, make sure it is not used
if (m_interface.endpoints.front().descriptor.bDescriptorType & 0x80)
{
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Class | USB::RequestType::Interface;
request.bRequest = USB::Request::SET_INTERFACE;
request.wValue = 1; // report protocol
request.wIndex = m_interface_index;
request.wLength = 0;
TRY(m_device.send_request(request, 0));
}
Collection collection {};
const auto& hid_descriptor = *reinterpret_cast<const HIDDescriptor*>(m_interface.misc_descriptors[hid_descriptor_index].data());
dprintln_if(DEBUG_HID, "HID descriptor ({} bytes)", m_interface.misc_descriptors[hid_descriptor_index].size());
dprintln_if(DEBUG_HID, " bLength: {}", hid_descriptor.bLength);
dprintln_if(DEBUG_HID, " bDescriptorType: {}", hid_descriptor.bDescriptorType);
dprintln_if(DEBUG_HID, " bcdHID: {H}.{2H}", hid_descriptor.bcdHID >> 8, hid_descriptor.bcdHID & 0xFF);
dprintln_if(DEBUG_HID, " bCountryCode: {}", hid_descriptor.bCountryCode);
dprintln_if(DEBUG_HID, " bNumDescriptors: {}", hid_descriptor.bNumDescriptors);
bool report_descriptor_parsed = false;
for (size_t i = 0; i < hid_descriptor.bNumDescriptors; i++)
{
auto descriptor = hid_descriptor.descriptors[i];
if (static_cast<HIDDescriptorType>(descriptor.bDescriptorType) != HIDDescriptorType::Report)
{
dprintln_if(DEBUG_HID, "Skipping HID descriptor type 0x{2H}", descriptor.bDescriptorType);
continue;
}
if (report_descriptor_parsed)
{
dwarnln("Multiple report descriptors specified");
return BAN::Error::from_errno(ENOTSUP);
}
if (descriptor.wItemLength > dma_buffer->size())
{
dwarnln("Too big report descriptor size {} bytes ({} supported)", +descriptor.wItemLength, dma_buffer->size());
return BAN::Error::from_errno(ENOBUFS);
}
{
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Standard | USB::RequestType::Interface;
request.bRequest = USB::Request::GET_DESCRIPTOR;
request.wValue = static_cast<uint16_t>(HIDDescriptorType::Report) << 8;
request.wIndex = m_interface_index;
request.wLength = descriptor.wItemLength;
auto transferred = TRY(m_device.send_request(request, dma_buffer->paddr()));
if (transferred < descriptor.wItemLength)
{
dwarnln("HID device did not respond with full report descriptor");
return BAN::Error::from_errno(EFAULT);
}
}
dprintln_if(DEBUG_HID, "Parsing {} byte report descriptor", +descriptor.wItemLength);
auto report_data = BAN::ConstByteSpan(reinterpret_cast<uint8_t*>(dma_buffer->vaddr()), descriptor.wItemLength);
collection = TRY(parse_report_descriptor(report_data));
report_descriptor_parsed = true;
}
if (!report_descriptor_parsed)
{
dwarnln("No report descriptors specified");
return BAN::Error::from_errno(EFAULT);
}
if (collection.usage_page != 0x01)
{
dwarnln("Top most collection is not generic desktop page");
return BAN::Error::from_errno(EFAULT);
}
#if DEBUG_HID
{
SpinLockGuard _(Debug::s_debug_lock);
dump_hid_collection(collection, 0);
}
#endif
switch (collection.usage_id)
{
case 0x02:
m_hid_device = TRY(BAN::RefPtr<USBMouse>::create());
break;
case 0x06:
m_hid_device = TRY(BAN::RefPtr<USBKeyboard>::create());
break;
default:
dwarnln("Unsupported generic descript page usage 0x{2H}", collection.usage_id);
return BAN::Error::from_errno(ENOTSUP);
}
DevFileSystem::get().add_device(m_hid_device);
const auto& endpoint_descriptor = m_interface.endpoints[endpoint_index].descriptor;
m_endpoint_id = (endpoint_descriptor.bEndpointAddress & 0x0F) * 2 + !!(endpoint_descriptor.bEndpointAddress & 0x80);
m_collection = BAN::move(collection);
TRY(m_device.initialize_endpoint(endpoint_descriptor));
return {};
}
void USBHIDDriver::forward_collection_inputs(const Collection& collection, BAN::ConstByteSpan& data, size_t bit_offset)
{
const auto extract_bits =
[data](size_t bit_offset, size_t bit_count, bool as_unsigned) -> int64_t
{
if (bit_offset >= data.size() * 8)
return 0;
if (bit_count + bit_offset > data.size() * 8)
bit_count = data.size() * 8 - bit_offset;
uint32_t result = 0;
uint32_t result_offset = 0;
while (result_offset < bit_count)
{
const uint32_t byte = bit_offset / 8;
const uint32_t bit = bit_offset % 8;
const uint32_t count = BAN::Math::min<uint32_t>(bit_count - result_offset, 8 - bit);
const uint32_t mask = (1 << count) - 1;
result |= static_cast<uint32_t>((data[byte] >> bit) & mask) << result_offset;
bit_offset += count;
result_offset += count;
}
if (!as_unsigned && (result & (1u << (bit_count - 1))))
{
const uint32_t mask = (1u << bit_count) - 1;
return -(static_cast<int64_t>(~result & mask) + 1);
}
return result;
};
for (const auto& entry : collection.entries)
{
if (entry.has<Collection>())
{
forward_collection_inputs(entry.get<Collection>(), data, bit_offset);
continue;
}
ASSERT(entry.has<Report>());
const auto& input = entry.get<Report>();
if (input.type != Report::Type::Input)
continue;
ASSERT(input.report_size <= 32);
if (input.usage_id == 0 && input.usage_minimum == 0 && input.usage_maximum == 0)
{
bit_offset += input.report_size * input.report_count;
continue;
}
for (uint32_t i = 0; i < input.report_count; i++)
{
const int64_t logical = extract_bits(bit_offset, input.report_size, input.logical_minimum >= 0);
if (logical < input.logical_minimum || logical > input.logical_maximum)
{
bit_offset += input.report_size;
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)
m_hid_device->handle_variable(input.usage_page, usage_base + i, physical);
else
m_hid_device->handle_array(input.usage_page, usage_base + physical);
bit_offset += input.report_size;
}
}
}
void USBHIDDriver::handle_input_data(BAN::ConstByteSpan data, uint8_t endpoint_id)
{
ASSERT(m_endpoint_id == endpoint_id);
if constexpr(DEBUG_HID)
{
const auto nibble_to_hex = [](uint8_t x) -> char { return x + (x < 10 ? '0' : 'A' - 10); };
char buffer[512];
char* ptr = buffer;
for (size_t i = 0; i < BAN::Math::min<size_t>((sizeof(buffer) - 1) / 3, data.size()); i++)
{
*ptr++ = nibble_to_hex(data[i] >> 4);
*ptr++ = nibble_to_hex(data[i] & 0xF);
*ptr++ = ' ';
}
*ptr = '\0';
dprintln_if(DEBUG_HID, "Received {} bytes from endpoint {}: {}", data.size(), endpoint_id, buffer);
}
m_hid_device->start_report();
forward_collection_inputs(m_collection, data, 0);
m_hid_device->stop_report();
}
BAN::ErrorOr<Collection> parse_report_descriptor(BAN::ConstByteSpan report_data)
{
BAN::Vector<GlobalState> global_stack;
GlobalState global_state;
LocalState local_state;
BAN::Optional<Collection> result;
BAN::Vector<Collection> collection_stack;
const auto extract_report_item =
[&](bool as_unsigned) -> int64_t
{
uint32_t value = 0;
auto value_data = report_data.slice(1);
switch (report_data[0] & 0x03)
{
case 1: value = as_unsigned ? value_data.as<const uint8_t>() : value_data.as<const int8_t>(); break;
case 2: value = as_unsigned ? value_data.as<const uint16_t>() : value_data.as<const int16_t>(); break;
case 3: value = as_unsigned ? value_data.as<const uint32_t>() : value_data.as<const int32_t>(); break;
}
return value;
};
constexpr auto get_correct_sign =
[](int64_t min, int64_t max_signed, int64_t max_unsigned) -> int64_t
{
if (min < 0 || max_signed >= 0)
return max_signed;
return max_unsigned;
};
const auto add_data_item =
[&](Report::Type type, uint32_t item_data, BAN::Vector<BAN::Variant<Collection, Report>>& container) -> BAN::ErrorOr<void>
{
if (!global_state.report_count.has_value() || !global_state.report_size.has_value())
{
dwarnln("Report count and/or report size is not defined");
return BAN::Error::from_errno(EFAULT);
}
if (!global_state.usage_page.has_value())
{
dwarnln("Usage page is not defined");
return BAN::Error::from_errno(EFAULT);
}
if (!global_state.logical_minimum.has_value() || !global_state.logical_maximum_signed.has_value())
{
dwarnln("Logical minimum and/or logical maximum is not defined");
return BAN::Error::from_errno(EFAULT);
}
if (global_state.physical_minimum.has_value() != global_state.physical_minimum.has_value())
{
dwarnln("Only one of physical minimum and physical maximum is defined");
return BAN::Error::from_errno(EFAULT);
}
if (local_state.usage_minimum.has_value() != local_state.usage_maximum.has_value())
{
dwarnln("Only one of logical minimum and logical maximum is defined");
return BAN::Error::from_errno(EFAULT);
}
const int64_t logical_minimum = global_state.logical_minimum.value();
const int64_t logical_maximum = get_correct_sign(
global_state.logical_minimum.value(),
global_state.logical_maximum_signed.value(),
global_state.logical_maximum_unsigned.value()
);
int64_t physical_minimum = logical_minimum;
int64_t physical_maximum = logical_maximum;
if (global_state.physical_minimum.has_value() && (global_state.physical_minimum.value() || global_state.physical_maximum.value()))
{
physical_minimum = global_state.physical_minimum.value();
physical_maximum = global_state.physical_maximum.value();
}
if (local_state.usage_stack.empty())
{
if (local_state.usage_minimum.has_value() && local_state.usage_maximum.has_value())
{
Report item;
item.usage_page = global_state.usage_page.value();
item.usage_id = 0;
item.usage_minimum = local_state.usage_minimum.value();
item.usage_maximum = local_state.usage_maximum.value();
item.type = type;
item.report_count = global_state.report_count.value();
item.report_size = global_state.report_size.value();
item.logical_minimum = logical_minimum;
item.logical_maximum = logical_maximum;
item.physical_minimum = physical_minimum;
item.physical_maximum = physical_maximum;
item.flags = item_data;
TRY(container.push_back(item));
return {};
}
Report item;
item.usage_page = global_state.usage_page.value();
item.usage_id = 0;
item.usage_minimum = 0;
item.usage_maximum = 0;
item.type = type;
item.report_count = global_state.report_count.value();
item.report_size = global_state.report_size.value();
item.logical_minimum = 0;
item.logical_maximum = 0;
item.physical_minimum = 0;
item.physical_maximum = 0;
item.flags = item_data;
TRY(container.push_back(item));
return {};
}
for (size_t i = 0; i < global_state.report_count.value(); i++)
{
const uint32_t usage = local_state.usage_stack[BAN::Math::min<size_t>(i, local_state.usage_stack.size() - 1)];
Report item;
item.usage_page = (usage >> 16) ? (usage >> 16) : global_state.usage_page.value();
item.usage_id = usage & 0xFFFF;
item.usage_minimum = 0;
item.usage_maximum = 0;
item.type = type;
item.report_count = 1;
item.report_size = global_state.report_size.value();
item.logical_minimum = logical_minimum;
item.logical_maximum = logical_maximum;
item.physical_minimum = physical_minimum;
item.physical_maximum = physical_maximum;
item.flags = item_data;
TRY(container.push_back(item));
}
return {};
};
while (report_data.size() > 0)
{
const uint8_t item_size = report_data[0] & 0x03;
const uint8_t item_type = (report_data[0] >> 2) & 0x03;
const uint8_t item_tag = (report_data[0] >> 4) & 0x0F;
if (item_type == 0)
{
switch (item_tag)
{
case 0b1000: // input
if (collection_stack.empty())
{
dwarnln("Invalid input item outside of collection");
return BAN::Error::from_errno(EFAULT);
}
TRY(add_data_item(Report::Type::Input, extract_report_item(true), collection_stack.back().entries));
break;
case 0b1001: // output
if (collection_stack.empty())
{
dwarnln("Invalid input item outside of collection");
return BAN::Error::from_errno(EFAULT);
}
TRY(add_data_item(Report::Type::Output, extract_report_item(true), collection_stack.back().entries));
break;
case 0b1011: // feature
if (collection_stack.empty())
{
dwarnln("Invalid input item outside of collection");
return BAN::Error::from_errno(EFAULT);
}
TRY(add_data_item(Report::Type::Feature, extract_report_item(true), collection_stack.back().entries));
break;
case 0b1010: // collection
{
if (local_state.usage_stack.size() != 1)
{
dwarnln("{} usages specified for collection", local_state.usage_stack.empty() ? "No" : "Multiple");
return BAN::Error::from_errno(EFAULT);
}
uint16_t usage_page = 0;
if (global_state.usage_page.has_value())
usage_page = global_state.usage_page.value();
if (local_state.usage_stack.front() >> 16)
usage_page = local_state.usage_stack.front() >> 16;
if (usage_page == 0)
{
dwarnln("Usage page not specified for a collection");
return BAN::Error::from_errno(EFAULT);
}
TRY(collection_stack.emplace_back());
collection_stack.back().usage_page = usage_page;
collection_stack.back().usage_id = local_state.usage_stack.front();
break;
}
case 0b1100: // end collection
if (collection_stack.empty())
{
dwarnln("End collection outside of collection");
return BAN::Error::from_errno(EFAULT);
}
if (collection_stack.size() == 1)
{
if (result.has_value())
{
dwarnln("Multiple top-level collections not supported");
return BAN::Error::from_errno(ENOTSUP);
}
result = BAN::move(collection_stack.back());
collection_stack.pop_back();
}
else
{
TRY(collection_stack[collection_stack.size() - 2].entries.push_back(BAN::move(collection_stack.back())));
collection_stack.pop_back();
}
break;
default:
dwarnln("Report has reserved main item tag 0b{4b}", item_tag);
return BAN::Error::from_errno(EFAULT);
}
local_state = LocalState();
}
else if (item_type == 1)
{
switch (item_tag)
{
case 0b0000: // usage page
global_state.usage_page = extract_report_item(true);
break;
case 0b0001: // logical minimum
global_state.logical_minimum = extract_report_item(false);
break;
case 0b0010: // logical maximum
global_state.logical_maximum_signed = extract_report_item(false);
global_state.logical_maximum_unsigned = extract_report_item(true);
break;
case 0b0011: // physical minimum
global_state.physical_minimum = extract_report_item(false);
break;
case 0b0100: // physical maximum
global_state.physical_maximum = extract_report_item(false);
break;
case 0b0101: // unit exponent
dwarnln("Report units are not supported");
return BAN::Error::from_errno(ENOTSUP);
case 0b0110: // unit
dwarnln("Report units are not supported");
return BAN::Error::from_errno(ENOTSUP);
case 0b0111: // report size
global_state.report_size = extract_report_item(true);
break;
case 0b1000: // report id
dwarnln("Report IDs are not supported");
return BAN::Error::from_errno(ENOTSUP);
case 0b1001: // report count
global_state.report_count = extract_report_item(true);
break;
case 0b1010: // push
TRY(global_stack.push_back(global_state));
break;
case 0b1011: // pop
if (global_stack.empty())
{
dwarnln("Report pop from empty stack");
return BAN::Error::from_errno(EFAULT);
}
global_state = global_stack.back();
global_stack.pop_back();
break;
default:
dwarnln("Report has reserved global item tag 0b{4b}", item_tag);
return BAN::Error::from_errno(EFAULT);
}
}
else if (item_type == 2)
{
switch (item_tag)
{
case 0b0000: // usage
TRY(local_state.usage_stack.emplace_back(extract_report_item(true)));
break;
case 0b0001: // usage minimum
local_state.usage_minimum = extract_report_item(true);
break;
case 0b0010: // usage maximum
local_state.usage_maximum = extract_report_item(true);
break;
case 0b0011: // designator index
case 0b0100: // designator minimum
case 0b0101: // designator maximum
case 0b0111: // string index
case 0b1000: // string minimum
case 0b1001: // string maximum
case 0b1010: // delimeter
dwarnln("Unsupported local item tag 0b{4b}", item_tag);
return BAN::Error::from_errno(ENOTSUP);
default:
dwarnln("Report has reserved local item tag 0b{4b}", item_tag);
return BAN::Error::from_errno(EFAULT);
}
}
else
{
dwarnln("Report has reserved item type 0b{2b}", item_type);
return BAN::Error::from_errno(EFAULT);
}
report_data = report_data.slice(1 + item_size);
}
if (!result.has_value())
{
dwarnln("No collection defined in report descriptor");
return BAN::Error::from_errno(EFAULT);
}
return result.release_value();
}
#if DEBUG_HID
static void print_indent(size_t indent)
{
for (size_t i = 0; i < indent; i++)
Debug::putchar(' ');
}
static void dump_hid_report(const Report& report, size_t indent)
{
const char* report_type = "";
switch (report.type)
{
case Report::Type::Input: report_type = "input"; break;
case Report::Type::Output: report_type = "output"; break;
case Report::Type::Feature: report_type = "feature"; break;
}
print_indent(indent);
BAN::Formatter::println(Debug::putchar, "report {}", report_type);
print_indent(indent + 4);
BAN::Formatter::println(Debug::putchar, "usage page: {2H}", report.usage_page);
if (report.usage_id || report.usage_minimum || report.usage_maximum)
{
print_indent(indent + 4);
if (report.usage_id)
BAN::Formatter::println(Debug::putchar, "usage: {2H}", report.usage_id);
else
BAN::Formatter::println(Debug::putchar, "usage: {2H}->{2H}", report.usage_minimum, report.usage_maximum);
}
print_indent(indent + 4);
BAN::Formatter::println(Debug::putchar, "flags: 0b{8b}", report.flags);
print_indent(indent + 4);
BAN::Formatter::println(Debug::putchar, "size: {}", report.report_size);
print_indent(indent + 4);
BAN::Formatter::println(Debug::putchar, "count: {}", report.report_count);
print_indent(indent + 4);
BAN::Formatter::println(Debug::putchar, "lminimum: {}", report.logical_minimum);
print_indent(indent + 4);
BAN::Formatter::println(Debug::putchar, "lmaximum: {}", report.logical_maximum);
print_indent(indent + 4);
BAN::Formatter::println(Debug::putchar, "pminimum: {}", report.physical_minimum);
print_indent(indent + 4);
BAN::Formatter::println(Debug::putchar, "pmaximum: {}", report.physical_maximum);
}
static void dump_hid_collection(const Collection& collection, size_t indent)
{
print_indent(indent);
BAN::Formatter::println(Debug::putchar, "collection {}", collection.type);
print_indent(indent);
BAN::Formatter::println(Debug::putchar, "usage {H}:{H}", collection.usage_page, collection.usage_id);
for (const auto& entry : collection.entries)
{
if (entry.has<Collection>())
dump_hid_collection(entry.get<Collection>(), indent + 4);
if (entry.has<Report>())
dump_hid_report(entry.get<Report>(), indent + 4);
}
}
#endif
}

View File

@ -1,212 +0,0 @@
#include <kernel/USB/HID/Keyboard.h>
#include <LibInput/KeyEvent.h>
#define DEBUG_KEYBOARD 0
namespace Kernel
{
static BAN::Optional<uint8_t> s_scancode_to_keycode[0x100] {};
static bool s_scancode_to_keycode_initialized = false;
static void initialize_scancode_to_keycode();
void USBKeyboard::start_report()
{
for (auto& val : m_keyboard_state_temp)
val = false;
}
void USBKeyboard::stop_report()
{
using KeyModifier = LibInput::KeyEvent::Modifier;
if (!s_scancode_to_keycode_initialized)
initialize_scancode_to_keycode();
// FIXME: RawKeyEvent probably should only contain keycode.
// Modifier should be determined when converting to KeyEvent.
uint8_t modifier = 0;
if (m_keyboard_state_temp[0xE1])
modifier |= KeyModifier::LShift;
if (m_keyboard_state_temp[0xE5])
modifier |= KeyModifier::RShift;
if (m_keyboard_state_temp[0xE0])
modifier |= KeyModifier::LCtrl;
if (m_keyboard_state_temp[0xE4])
modifier |= KeyModifier::RCtrl;
if (m_keyboard_state_temp[0xE2])
modifier |= KeyModifier::LAlt;
if (m_keyboard_state_temp[0xE6])
modifier |= KeyModifier::RAlt;
if (m_keyboard_state_temp[0x39] && !m_keyboard_state[0x39])
m_toggle_mask ^= KeyModifier::CapsLock;
if (m_keyboard_state_temp[0x47] && !m_keyboard_state[0x47])
m_toggle_mask ^= KeyModifier::ScrollLock;
if (m_keyboard_state_temp[0x53] && !m_keyboard_state[0x53])
m_toggle_mask ^= KeyModifier::NumLock;
modifier |= m_toggle_mask;
for (size_t i = 0; i < m_keyboard_state.size(); i++)
{
if (m_keyboard_state[i] == m_keyboard_state_temp[i])
continue;
const bool pressed = m_keyboard_state_temp[i];
if (pressed)
dprintln_if(DEBUG_KEYBOARD, "{2H}", i);
auto opt_keycode = s_scancode_to_keycode[i];
if (opt_keycode.has_value())
{
LibInput::RawKeyEvent event;
event.keycode = opt_keycode.value();
event.modifier = modifier | (pressed ? KeyModifier::Pressed : 0);
add_event(BAN::ConstByteSpan::from(event));
}
m_keyboard_state[i] = m_keyboard_state_temp[i];
}
}
void USBKeyboard::handle_variable(uint16_t usage_page, uint16_t usage, int64_t state)
{
if (usage_page != 0x07)
{
dprintln_if(DEBUG_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page);
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)
{
if (usage_page != 0x07)
{
dprintln_if(DEBUG_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page);
return;
}
if (usage >= 4 && usage < m_keyboard_state_temp.size())
m_keyboard_state_temp[usage] = true;
}
void initialize_scancode_to_keycode()
{
using LibInput::keycode_function;
using LibInput::keycode_normal;
using LibInput::keycode_numpad;
s_scancode_to_keycode[0x35] = keycode_normal(0, 0);
s_scancode_to_keycode[0x1E] = keycode_normal(0, 1);
s_scancode_to_keycode[0x1F] = keycode_normal(0, 2);
s_scancode_to_keycode[0x20] = keycode_normal(0, 3);
s_scancode_to_keycode[0x21] = keycode_normal(0, 4);
s_scancode_to_keycode[0x22] = keycode_normal(0, 5);
s_scancode_to_keycode[0x23] = keycode_normal(0, 6);
s_scancode_to_keycode[0x24] = keycode_normal(0, 7);
s_scancode_to_keycode[0x25] = keycode_normal(0, 8);
s_scancode_to_keycode[0x26] = keycode_normal(0, 9);
s_scancode_to_keycode[0x27] = keycode_normal(0, 10);
s_scancode_to_keycode[0x2D] = keycode_normal(0, 11);
s_scancode_to_keycode[0x2E] = keycode_normal(0, 12);
s_scancode_to_keycode[0x2A] = keycode_normal(0, 13);
s_scancode_to_keycode[0x2B] = keycode_normal(1, 0);
s_scancode_to_keycode[0x14] = keycode_normal(1, 1);
s_scancode_to_keycode[0x1A] = keycode_normal(1, 2);
s_scancode_to_keycode[0x08] = keycode_normal(1, 3);
s_scancode_to_keycode[0x15] = keycode_normal(1, 4);
s_scancode_to_keycode[0x17] = keycode_normal(1, 5);
s_scancode_to_keycode[0x1C] = keycode_normal(1, 6);
s_scancode_to_keycode[0x18] = keycode_normal(1, 7);
s_scancode_to_keycode[0x0C] = keycode_normal(1, 8);
s_scancode_to_keycode[0x12] = keycode_normal(1, 9);
s_scancode_to_keycode[0x13] = keycode_normal(1, 10);
s_scancode_to_keycode[0x2F] = keycode_normal(1, 11);
s_scancode_to_keycode[0x30] = keycode_normal(1, 12);
s_scancode_to_keycode[0x39] = keycode_normal(2, 0);
s_scancode_to_keycode[0x04] = keycode_normal(2, 1);
s_scancode_to_keycode[0x16] = keycode_normal(2, 2);
s_scancode_to_keycode[0x07] = keycode_normal(2, 3);
s_scancode_to_keycode[0x09] = keycode_normal(2, 4);
s_scancode_to_keycode[0x0A] = keycode_normal(2, 5);
s_scancode_to_keycode[0x0B] = keycode_normal(2, 6);
s_scancode_to_keycode[0x0D] = keycode_normal(2, 7);
s_scancode_to_keycode[0x0E] = keycode_normal(2, 8);
s_scancode_to_keycode[0x0F] = keycode_normal(2, 9);
s_scancode_to_keycode[0x33] = keycode_normal(2, 10);
s_scancode_to_keycode[0x34] = keycode_normal(2, 11);
s_scancode_to_keycode[0x31] = keycode_normal(2, 12);
s_scancode_to_keycode[0x28] = keycode_normal(2, 13);
s_scancode_to_keycode[0xE1] = keycode_normal(3, 0);
s_scancode_to_keycode[0x64] = keycode_normal(3, 1);
s_scancode_to_keycode[0x1D] = keycode_normal(3, 2);
s_scancode_to_keycode[0x1B] = keycode_normal(3, 3);
s_scancode_to_keycode[0x06] = keycode_normal(3, 4);
s_scancode_to_keycode[0x19] = keycode_normal(3, 5);
s_scancode_to_keycode[0x05] = keycode_normal(3, 6);
s_scancode_to_keycode[0x11] = keycode_normal(3, 7);
s_scancode_to_keycode[0x10] = keycode_normal(3, 8);
s_scancode_to_keycode[0x36] = keycode_normal(3, 9);
s_scancode_to_keycode[0x37] = keycode_normal(3, 10);
s_scancode_to_keycode[0x38] = keycode_normal(3, 11);
s_scancode_to_keycode[0xE5] = keycode_normal(3, 12);
s_scancode_to_keycode[0xE0] = keycode_normal(4, 1);
s_scancode_to_keycode[0xE3] = keycode_normal(4, 2);
s_scancode_to_keycode[0xE2] = keycode_normal(4, 3);
s_scancode_to_keycode[0x2C] = keycode_normal(4, 4);
s_scancode_to_keycode[0xE6] = keycode_normal(4, 5);
s_scancode_to_keycode[0xE4] = keycode_normal(4, 6);
s_scancode_to_keycode[0x52] = keycode_normal(5, 0);
s_scancode_to_keycode[0x50] = keycode_normal(5, 1);
s_scancode_to_keycode[0x51] = keycode_normal(5, 2);
s_scancode_to_keycode[0x4F] = keycode_normal(5, 3);
s_scancode_to_keycode[0x29] = keycode_function( 0);
s_scancode_to_keycode[0x3A] = keycode_function( 1);
s_scancode_to_keycode[0x3B] = keycode_function( 2);
s_scancode_to_keycode[0x3C] = keycode_function( 3);
s_scancode_to_keycode[0x3D] = keycode_function( 4);
s_scancode_to_keycode[0x3E] = keycode_function( 5);
s_scancode_to_keycode[0x3F] = keycode_function( 6);
s_scancode_to_keycode[0x40] = keycode_function( 7);
s_scancode_to_keycode[0x41] = keycode_function( 8);
s_scancode_to_keycode[0x42] = keycode_function( 9);
s_scancode_to_keycode[0x43] = keycode_function(10);
s_scancode_to_keycode[0x44] = keycode_function(11);
s_scancode_to_keycode[0x45] = keycode_function(12);
s_scancode_to_keycode[0x49] = keycode_function(13);
s_scancode_to_keycode[0x46] = keycode_function(14);
s_scancode_to_keycode[0x4C] = keycode_function(15);
s_scancode_to_keycode[0x4A] = keycode_function(16);
s_scancode_to_keycode[0x4D] = keycode_function(17);
s_scancode_to_keycode[0x4B] = keycode_function(18);
s_scancode_to_keycode[0x4E] = keycode_function(19);
s_scancode_to_keycode[0x53] = keycode_numpad(0, 0);
s_scancode_to_keycode[0x54] = keycode_numpad(0, 1);
s_scancode_to_keycode[0x55] = keycode_numpad(0, 2);
s_scancode_to_keycode[0x56] = keycode_numpad(0, 3);
s_scancode_to_keycode[0x5F] = keycode_numpad(1, 0);
s_scancode_to_keycode[0x60] = keycode_numpad(1, 1);
s_scancode_to_keycode[0x61] = keycode_numpad(1, 2);
s_scancode_to_keycode[0x57] = keycode_numpad(1, 3);
s_scancode_to_keycode[0x5C] = keycode_numpad(2, 0);
s_scancode_to_keycode[0x5D] = keycode_numpad(2, 1);
s_scancode_to_keycode[0x5E] = keycode_numpad(2, 2);
s_scancode_to_keycode[0x59] = keycode_numpad(3, 0);
s_scancode_to_keycode[0x5A] = keycode_numpad(3, 1);
s_scancode_to_keycode[0x5B] = keycode_numpad(3, 2);
s_scancode_to_keycode[0x58] = keycode_numpad(3, 3);
s_scancode_to_keycode[0x62] = keycode_numpad(4, 0);
s_scancode_to_keycode[0x63] = keycode_numpad(4, 1);
s_scancode_to_keycode_initialized = true;
}
}

View File

@ -1,99 +0,0 @@
#include <kernel/USB/HID/Mouse.h>
#include <LibInput/MouseEvent.h>
#define DEBUG_MOUSE 0
namespace Kernel
{
void USBMouse::start_report()
{
for (auto& val : m_button_state_temp)
val = false;
}
void USBMouse::stop_report()
{
if (m_pointer_x || m_pointer_y)
{
dprintln_if(DEBUG_MOUSE, "Mouse move event {}, {}", m_pointer_x, m_pointer_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;
add_event(BAN::ConstByteSpan::from(event));
m_pointer_x = 0;
m_pointer_y = 0;
}
if (m_wheel)
{
dprintln_if(DEBUG_MOUSE, "Mouse scroll event {}", m_wheel);
LibInput::MouseEvent event;
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++)
{
if (m_button_state[i] == m_button_state_temp[i])
continue;
const bool pressed = m_button_state_temp[i];
dprintln_if(DEBUG_MOUSE, "Mouse button event {}: {}", i, pressed);
LibInput::MouseEvent event;
event.type = LibInput::MouseEventType::MouseButtonEvent;
event.button_event.pressed = pressed;
event.button_event.button = static_cast<LibInput::MouseButton>(i);
add_event(BAN::ConstByteSpan::from(event));
m_button_state[i] = m_button_state_temp[i];
}
}
void USBMouse::handle_variable(uint16_t usage_page, uint16_t usage, int64_t state)
{
switch (usage_page)
{
case 0x01: // pointer
switch (usage)
{
case 0x30:
m_pointer_x = state;
break;
case 0x31:
m_pointer_y = state;
break;
case 0x38:
m_wheel = state;
break;
default:
dprintln_if(DEBUG_MOUSE, "Unsupported mouse usage {2H} on page {2H}", usage, usage_page);
break;
}
break;
case 0x09: // button
if (usage == 0 || usage >= m_button_state_temp.size())
break;
m_button_state_temp[usage - 1] = state;
break;
default:
dprintln_if(DEBUG_MOUSE, "Unsupported mouse usage page {2H}", usage_page);
break;
}
}
void USBMouse::handle_array(uint16_t usage_page, uint16_t usage)
{
dprintln_if(DEBUG_MOUSE, "Unhandled array report {2H}:{2H}", usage_page, usage);
}
}

View File

@ -1,57 +0,0 @@
#include <BAN/UniqPtr.h>
#include <kernel/USB/USBManager.h>
#include <kernel/USB/XHCI/Controller.h>
namespace Kernel
{
static BAN::UniqPtr<USBManager> s_instance;
BAN::ErrorOr<void> USBManager::initialize()
{
ASSERT(!s_instance);
auto manager = TRY(BAN::UniqPtr<USBManager>::create());
s_instance = BAN::move(manager);
return {};
}
USBManager& USBManager::get()
{
ASSERT(s_instance);
return *s_instance;
}
BAN::ErrorOr<void> USBManager::add_controller(PCI::Device& pci_device)
{
ASSERT(pci_device.class_code() == 0x0C);
ASSERT(pci_device.subclass() == 0x03);
BAN::UniqPtr<USBController> controller;
switch (pci_device.prog_if())
{
case 0x00:
dprintln("Unsupported UHCI controller");
return BAN::Error::from_errno(ENOTSUP);
case 0x10:
dprintln("Unsupported OHCI controller");
return BAN::Error::from_errno(ENOTSUP);
case 0x20:
dprintln("Unsupported EHCI controller");
return BAN::Error::from_errno(ENOTSUP);
case 0x30:
if (auto ret = XHCIController::initialize(pci_device); ret.is_error())
dprintln("Could not initialize XHCI controller: {}", ret.error());
else
controller = ret.release_value();
break;
default:
return BAN::Error::from_errno(EINVAL);
}
TRY(m_controllers.push_back(BAN::move(controller)));
return {};
}
}

View File

@ -1,506 +0,0 @@
#include <BAN/Bitcast.h>
#include <BAN/StringView.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Process.h>
#include <kernel/Timer/Timer.h>
#include <kernel/USB/XHCI/Controller.h>
#include <kernel/USB/XHCI/Device.h>
#define DEBUG_XHCI 0
namespace Kernel
{
XHCIController::XHCIController(PCI::Device& pci_device)
: m_pci_device(pci_device)
{ }
XHCIController::~XHCIController()
{
if (m_port_updater)
m_port_updater->exit(0, SIGKILL);
}
BAN::ErrorOr<BAN::UniqPtr<XHCIController>> XHCIController::initialize(PCI::Device& pci_device)
{
auto controller = TRY(BAN::UniqPtr<XHCIController>::create(pci_device));
TRY(controller->initialize_impl());
return controller;
}
BAN::ErrorOr<void> XHCIController::initialize_impl()
{
dprintln_if(DEBUG_XHCI, "XHCI controller at PCI {2H}:{2H}:{2H}", m_pci_device.bus(), m_pci_device.dev(), m_pci_device.func());
m_pci_device.enable_bus_mastering();
m_pci_device.enable_memory_space();
m_configuration_bar = TRY(m_pci_device.allocate_bar_region(0));
if (m_configuration_bar->type() != PCI::BarType::MEM)
{
dwarnln("XHCI controller with non-memory configuration space");
return BAN::Error::from_errno(EINVAL);
}
if (auto ret = reset_controller(); ret.is_error())
{
dwarnln("Could not reset XHCI Controller: {}", ret.error());
return ret.release_error();
}
auto& capabilities = capability_regs();
dprintln_if(DEBUG_XHCI, " version {H}.{H}.{H}",
+capabilities.major_revision,
capabilities.minor_revision >> 4,
capabilities.minor_revision & 0x0F
);
dprintln_if(DEBUG_XHCI, " max slots {}", +capabilities.hcsparams1.max_slots);
dprintln_if(DEBUG_XHCI, " max intrs {}", +capabilities.hcsparams1.max_interrupters);
dprintln_if(DEBUG_XHCI, " max ports {}", +capabilities.hcsparams1.max_ports);
TRY(m_slots.resize(capabilities.hcsparams1.max_slots));
TRY(m_ports.resize(capabilities.hcsparams1.max_ports));
TRY(initialize_ports());
auto& operational = operational_regs();
// allocate and program dcbaa
m_dcbaa_region = TRY(DMARegion::create(capabilities.hcsparams1.max_slots * 8));
memset(reinterpret_cast<void*>(m_dcbaa_region->vaddr()), 0, m_dcbaa_region->size());
operational.dcbaap_lo = m_dcbaa_region->paddr() & 0xFFFFFFFF;
operational.dcbaap_hi = m_dcbaa_region->paddr() >> 32;
// allocate and program crcr
TRY(m_command_completions.resize(m_command_ring_trb_count));
m_command_ring_region = TRY(DMARegion::create(m_command_ring_trb_count * sizeof(XHCI::TRB)));
memset(reinterpret_cast<void*>(m_command_ring_region->vaddr()), 0, m_command_ring_region->size());
operational.crcr_lo = m_command_ring_region->paddr() | XHCI::CRCR::RingCycleState;
operational.crcr_hi = m_command_ring_region->paddr() >> 32;
TRY(initialize_primary_interrupter());
// enable the controller
operational.usbcmd.run_stop = 1;
while (operational.usbsts & XHCI::USBSTS::HCHalted)
continue;
m_port_updater = Process::create_kernel([](void* data) { reinterpret_cast<XHCIController*>(data)->port_updater_task(); }, this);
if (m_port_updater == nullptr)
return BAN::Error::from_errno(ENOMEM);
return {};
}
BAN::ErrorOr<void> XHCIController::initialize_ports()
{
auto& capabilities = capability_regs();
uint8_t max_ports = capabilities.hcsparams1.max_ports;
ASSERT(m_ports.size() == max_ports);
{
uint16_t ext_offset = capabilities.hccparams1.xhci_extended_capabilities_pointer;
if (ext_offset == 0)
{
dwarnln("XHCI controller does not have extended capabilities");
return BAN::Error::from_errno(EFAULT);
}
vaddr_t ext_addr = m_configuration_bar->vaddr() + ext_offset * 4;
while (true)
{
auto& ext_cap = *reinterpret_cast<volatile XHCI::ExtendedCap*>(ext_addr);
if (ext_cap.capability_id == XHCI::ExtendedCapabilityID::SupportedProtocol)
{
auto& protocol = reinterpret_cast<volatile XHCI::SupportedPrococolCap&>(ext_cap);
if (protocol.name_string != *reinterpret_cast<const uint32_t*>("USB "))
{
dwarnln("Invalid port protocol name string");
return BAN::Error::from_errno(EFAULT);
}
if (protocol.compatible_port_offset == 0 || protocol.compatible_port_offset + protocol.compatible_port_count - 1 > max_ports)
{
dwarnln("Invalid port specified in SupportedProtocols");
return BAN::Error::from_errno(EFAULT);
}
for (size_t i = 0; i < protocol.compatible_port_count; i++)
{
auto& port = m_ports[protocol.compatible_port_offset + i - 1];
port.revision_major = protocol.major_revision;
port.revision_minor = protocol.minor_revision;
port.slot_type = protocol.protocol_slot_type;
for (size_t j = 0; j < protocol.protocol_speed_id_count; j++)
{
uint32_t speed_info = reinterpret_cast<const volatile uint32_t*>(ext_addr + sizeof(XHCI::SupportedPrococolCap))[j];
uint32_t port_speed = speed_info >> 16;
for (size_t exp = 0; exp < ((speed_info >> 4) & 0x03); exp++)
port_speed *= 1000;
port.speed_id_to_speed[speed_info & 0x0F] = port_speed;
}
}
}
if (ext_cap.next_capability == 0)
break;
ext_addr += ext_cap.next_capability * 4;
}
}
// set max slots enabled
auto& operational = operational_regs();
operational.config.max_device_slots_enabled = capabilities.hcsparams1.max_slots;
return {};
}
BAN::ErrorOr<void> XHCIController::initialize_primary_interrupter()
{
TRY(m_pci_device.reserve_irqs(1));
auto& runtime = runtime_regs();
static constexpr size_t event_ring_table_offset = m_event_ring_trb_count * sizeof(XHCI::TRB);
m_event_ring_region = TRY(DMARegion::create(m_event_ring_trb_count * sizeof(XHCI::TRB) + sizeof(XHCI::EventRingTableEntry)));
memset(reinterpret_cast<void*>(m_event_ring_region->vaddr()), 0, m_event_ring_region->size());
auto& event_ring_table_entry = *reinterpret_cast<XHCI::EventRingTableEntry*>(m_event_ring_region->vaddr() + event_ring_table_offset);
event_ring_table_entry.rsba = m_event_ring_region->paddr();
event_ring_table_entry.rsz = m_event_ring_trb_count;
auto& primary_interrupter = runtime.irs[0];
primary_interrupter.erstsz = 1;
primary_interrupter.erdp = m_event_ring_region->paddr();
primary_interrupter.erstba = m_event_ring_region->paddr() + event_ring_table_offset;
auto& operational = operational_regs();
operational.usbcmd.interrupter_enable = 1;
primary_interrupter.iman = primary_interrupter.iman | XHCI::IMAN::InterruptPending | XHCI::IMAN::InterruptEnable;
set_irq(m_pci_device.get_irq(0));
enable_interrupt();
return {};
}
static Mutex s_port_mutex;
void XHCIController::port_updater_task()
{
// allow initial pass of port iteration because controller
// does not send Port Status Change event for already
// attached ports
m_port_changed = true;
while (true)
{
{
bool expected { true };
while (!m_port_changed.compare_exchange(expected, false))
{
m_port_semaphore.block_with_timeout(100);
expected = true;
}
}
for (size_t i = 0; i < m_ports.size(); i++)
{
LockGuard _(s_port_mutex);
auto& my_port = m_ports[i];
if (my_port.revision_major == 0)
continue;
auto& op_port = operational_regs().ports[i];
if (!(op_port.portsc & XHCI::PORTSC::PP))
continue;
// read and clear needed change flags
const bool reset_change = op_port.portsc & XHCI::PORTSC::PRC;
const bool connection_change = op_port.portsc & XHCI::PORTSC::CSC;
op_port.portsc = XHCI::PORTSC::CSC | XHCI::PORTSC::PRC | XHCI::PORTSC::PP;
if (!(op_port.portsc & XHCI::PORTSC::CCS))
{
// if device detached, clear the port
if (my_port.slot_id != 0)
{
m_slots[my_port.slot_id - 1].clear();
my_port.slot_id = 0;
}
continue;
}
switch (my_port.revision_major)
{
case 2:
if (!reset_change)
{
if (connection_change)
op_port.portsc = XHCI::PORTSC::PR | XHCI::PORTSC::PP;
continue;
}
break;
case 3:
if (!connection_change)
continue;
dprintln_if(DEBUG_XHCI, "USB 3 devices not supported");
continue;
default:
continue;
}
if (auto ret = initialize_slot(i); ret.is_error())
{
dwarnln("Could not initialize USB {H}.{H} device: {}",
my_port.revision_major,
my_port.revision_minor >> 4,
ret.error()
);
}
}
}
}
BAN::ErrorOr<void> XHCIController::initialize_slot(int port_index)
{
auto& my_port = m_ports[port_index];
XHCI::TRB enable_slot { .enable_slot_command {} };
enable_slot.enable_slot_command.trb_type = XHCI::TRBType::EnableSlotCommand;
enable_slot.enable_slot_command.slot_type = my_port.slot_type;
auto result = TRY(send_command(enable_slot));
uint8_t slot_id = result.command_completion_event.slot_id;
if (slot_id == 0 || slot_id > capability_regs().hcsparams1.max_slots)
{
dwarnln("EnableSlot gave an invalid slot {}", slot_id);
return BAN::Error::from_errno(EFAULT);
}
dprintln_if(DEBUG_XHCI, "allocated slot {} for port {}", slot_id, port_index + 1);
m_slots[slot_id - 1] = TRY(XHCIDevice::create(*this, port_index + 1, slot_id));
if (auto ret = m_slots[slot_id - 1]->initialize(); ret.is_error())
{
dwarnln("Could not initialize device on slot {}: {}", slot_id, ret.error());
m_slots[slot_id - 1].clear();
return ret.release_error();
}
my_port.slot_id = slot_id;
dprintln_if(DEBUG_XHCI, "device on slot {} initialized", slot_id);
return {};
}
BAN::ErrorOr<void> XHCIController::reset_controller()
{
auto& operational = operational_regs();
const uint64_t timeout_ms = SystemTimer::get().ms_since_boot() + 500;
// wait until controller not ready clears
while (operational.usbsts & XHCI::USBSTS::ControllerNotReady)
if (SystemTimer::get().ms_since_boot() > timeout_ms)
return BAN::Error::from_errno(ETIMEDOUT);
// issue software reset and wait for it to clear
operational.usbcmd.host_controller_reset = 1;
while (operational.usbcmd.host_controller_reset)
if (SystemTimer::get().ms_since_boot() > timeout_ms)
return BAN::Error::from_errno(ETIMEDOUT);
return {};
}
BAN::ErrorOr<XHCI::TRB> XHCIController::send_command(const XHCI::TRB& trb)
{
LockGuard _(m_mutex);
auto& command_trb = reinterpret_cast<volatile XHCI::TRB*>(m_command_ring_region->vaddr())[m_command_enqueue];
command_trb.raw.dword0 = trb.raw.dword0;
command_trb.raw.dword1 = trb.raw.dword1;
command_trb.raw.dword2 = trb.raw.dword2;
command_trb.raw.dword3 = trb.raw.dword3;
command_trb.cycle = m_command_cycle;
auto& completion_trb = const_cast<volatile XHCI::TRB&>(m_command_completions[m_command_enqueue]);
completion_trb.raw.dword0 = 0;
completion_trb.raw.dword1 = 0;
completion_trb.raw.dword2 = 0;
completion_trb.raw.dword3 = 0;
advance_command_enqueue();
doorbell_reg(0) = 0;
uint64_t timeout_ms = SystemTimer::get().ms_since_boot() + 1000;
while ((__atomic_load_n(&completion_trb.raw.dword2, __ATOMIC_SEQ_CST) >> 24) == 0)
if (SystemTimer::get().ms_since_boot() > timeout_ms)
return BAN::Error::from_errno(ETIMEDOUT);
if (completion_trb.command_completion_event.completion_code != 1)
{
dwarnln("Completion error: {}", +completion_trb.command_completion_event.completion_code);
return BAN::Error::from_errno(EFAULT);
}
return BAN::bit_cast<XHCI::TRB>(completion_trb);
}
void XHCIController::advance_command_enqueue()
{
m_command_enqueue++;
if (m_command_enqueue < m_command_ring_trb_count - 1)
return;
auto& link_trb = reinterpret_cast<volatile XHCI::TRB*>(m_command_ring_region->vaddr())[m_command_enqueue].link_trb;
link_trb.trb_type = XHCI::TRBType::Link;
link_trb.ring_segment_ponter = m_command_ring_region->paddr();
link_trb.interrupter_target = 0;
link_trb.cycle_bit = m_command_cycle;
link_trb.toggle_cycle = 1;
link_trb.chain_bit = 0;
link_trb.interrupt_on_completion = 0;
m_command_enqueue = 0;
m_command_cycle = !m_command_cycle;
}
void XHCIController::handle_irq()
{
auto& operational = operational_regs();
if (!(operational.usbsts & XHCI::USBSTS::EventInterrupt))
return;
operational.usbsts = XHCI::USBSTS::EventInterrupt;
auto& primary_interrupter = runtime_regs().irs[0];
primary_interrupter.iman = primary_interrupter.iman | XHCI::IMAN::InterruptPending | XHCI::IMAN::InterruptEnable;
if (current_event_trb().cycle == m_event_cycle)
{
for (;;)
{
auto& trb = current_event_trb();
if (trb.cycle != m_event_cycle)
break;
switch (trb.trb_type)
{
case XHCI::TRBType::TransferEvent:
{
dprintln_if(DEBUG_XHCI, "TransferEvent");
const uint32_t slot_id = trb.transfer_event.slot_id;
if (slot_id == 0 || slot_id > m_slots.size() || !m_slots[slot_id - 1])
{
dwarnln("TransferEvent for invalid slot {}", slot_id);
dwarnln("Completion error: {}", +trb.transfer_event.completion_code);
break;
}
m_slots[slot_id - 1]->on_transfer_event(trb);
break;
}
case XHCI::TRBType::CommandCompletionEvent:
{
dprintln_if(DEBUG_XHCI, "CommandCompletionEvent");
const uint32_t trb_index = (trb.command_completion_event.command_trb_pointer - m_command_ring_region->paddr()) / sizeof(XHCI::TRB);
// NOTE: dword2 is last (and atomic) as that is what send_command is waiting for
auto& completion_trb = const_cast<volatile XHCI::TRB&>(m_command_completions[trb_index]);
completion_trb.raw.dword0 = trb.raw.dword0;
completion_trb.raw.dword1 = trb.raw.dword1;
completion_trb.raw.dword3 = trb.raw.dword3;
__atomic_store_n(&completion_trb.raw.dword2, trb.raw.dword2, __ATOMIC_SEQ_CST);
break;
}
case XHCI::TRBType::PortStatusChangeEvent:
{
dprintln_if(DEBUG_XHCI, "PortStatusChangeEvent");
uint8_t port_id = trb.port_status_chage_event.port_id;
if (port_id > capability_regs().hcsparams1.max_ports)
{
dwarnln("PortStatusChangeEvent on non-existent port {}", port_id);
break;
}
m_port_changed = true;
m_port_semaphore.unblock();
break;
}
case XHCI::TRBType::BandwidthRequestEvent:
dwarnln("Unhandled BandwidthRequestEvent");
break;
case XHCI::TRBType::DoorbellEvent:
dwarnln("Unhandled DoorbellEvent");
break;
case XHCI::TRBType::HostControllerEvent:
dwarnln("Unhandled HostControllerEvent");
break;
case XHCI::TRBType::DeviceNotificationEvent:
dwarnln("Unhandled DeviceNotificationEvent");
break;
case XHCI::TRBType::MFINDEXWrapEvent:
dwarnln("Unhandled MFINDEXWrapEvent");
break;
default:
dwarnln("Unrecognized event TRB type {}", +trb.trb_type);
break;
}
m_event_dequeue++;
if (m_event_dequeue >= m_event_ring_trb_count)
{
m_event_dequeue = 0;
m_event_cycle = !m_event_cycle;
}
}
primary_interrupter.erdp = (m_event_ring_region->paddr() + (m_event_dequeue * sizeof(XHCI::TRB))) | XHCI::ERDP::EventHandlerBusy;
}
}
volatile XHCI::CapabilityRegs& XHCIController::capability_regs()
{
return *reinterpret_cast<volatile XHCI::CapabilityRegs*>(m_configuration_bar->vaddr());
}
volatile XHCI::OperationalRegs& XHCIController::operational_regs()
{
return *reinterpret_cast<volatile XHCI::OperationalRegs*>(m_configuration_bar->vaddr() + capability_regs().caplength);
}
volatile XHCI::RuntimeRegs& XHCIController::runtime_regs()
{
return *reinterpret_cast<volatile XHCI::RuntimeRegs*>(m_configuration_bar->vaddr() + (capability_regs().rstoff & ~0x1Fu));
}
volatile uint32_t& XHCIController::doorbell_reg(uint32_t slot_id)
{
return reinterpret_cast<volatile uint32_t*>(m_configuration_bar->vaddr() + capability_regs().dboff)[slot_id];
}
const volatile XHCI::TRB& XHCIController::current_event_trb()
{
return reinterpret_cast<const volatile XHCI::TRB*>(m_event_ring_region->vaddr())[m_event_dequeue];;
}
volatile uint64_t& XHCIController::dcbaa_reg(uint32_t slot_id)
{
return reinterpret_cast<volatile uint64_t*>(m_dcbaa_region->vaddr())[slot_id];
}
}

View File

@ -1,447 +0,0 @@
#include <BAN/Bitcast.h>
#include <BAN/ByteSpan.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Timer/Timer.h>
#include <kernel/USB/XHCI/Device.h>
#define DEBUG_XHCI 0
namespace Kernel
{
BAN::ErrorOr<BAN::UniqPtr<XHCIDevice>> XHCIDevice::create(XHCIController& controller, uint32_t port_id, uint32_t slot_id)
{
return TRY(BAN::UniqPtr<XHCIDevice>::create(controller, port_id, slot_id));
}
XHCIDevice::~XHCIDevice()
{
XHCI::TRB disable_slot { .disable_slot_command {} };
disable_slot.disable_slot_command.trb_type = XHCI::TRBType::DisableSlotCommand;
disable_slot.disable_slot_command.slot_id = m_slot_id;
if (auto ret = m_controller.send_command(disable_slot); ret.is_error())
dwarnln("Could not disable slot {}: {}", m_slot_id, ret.error());
else
dprintln_if(DEBUG_XHCI, "Slot {} disabled", m_slot_id);
}
BAN::ErrorOr<void> XHCIDevice::initialize_control_endpoint()
{
const uint32_t context_size = m_controller.context_size_set() ? 64 : 32;
const uint32_t portsc = m_controller.operational_regs().ports[m_port_id - 1].portsc;
const uint32_t speed_id = (portsc >> XHCI::PORTSC::PORT_SPEED_SHIFT) & XHCI::PORTSC::PORT_SPEED_MASK;
const uint32_t bits_per_second = m_controller.port(m_port_id).speed_id_to_speed[speed_id];
const auto speed_class = determine_speed_class(bits_per_second);
m_endpoints[0].max_packet_size = 0;
switch (speed_class)
{
case USB::SpeedClass::LowSpeed:
case USB::SpeedClass::FullSpeed:
m_endpoints[0].max_packet_size = 8;
break;
case USB::SpeedClass::HighSpeed:
m_endpoints[0].max_packet_size = 64;
break;
case USB::SpeedClass::SuperSpeed:
m_endpoints[0].max_packet_size = 512;
break;
default: ASSERT_NOT_REACHED();
}
m_input_context = TRY(DMARegion::create(33 * context_size));
memset(reinterpret_cast<void*>(m_input_context->vaddr()), 0, m_input_context->size());
m_output_context = TRY(DMARegion::create(32 * context_size));
memset(reinterpret_cast<void*>(m_output_context->vaddr()), 0, m_output_context->size());
m_endpoints[0].transfer_ring = TRY(DMARegion::create(m_transfer_ring_trb_count * sizeof(XHCI::TRB)));
memset(reinterpret_cast<void*>(m_endpoints[0].transfer_ring->vaddr()), 0, m_endpoints[0].transfer_ring->size());
{
auto& input_control_context = *reinterpret_cast<XHCI::InputControlContext*>(m_input_context->vaddr() + 0 * context_size);
auto& slot_context = *reinterpret_cast<XHCI::SlotContext*> (m_input_context->vaddr() + 1 * context_size);
auto& endpoint0_context = *reinterpret_cast<XHCI::EndpointContext*> (m_input_context->vaddr() + 2 * context_size);
memset(&input_control_context, 0, context_size);
input_control_context.add_context_flags = 0b11;
memset(&slot_context, 0, context_size);
slot_context.route_string = 0;
slot_context.root_hub_port_number = m_port_id;
slot_context.context_entries = 1;
slot_context.interrupter_target = 0;
slot_context.speed = speed_id;
// FIXME: 4.5.2 hub
memset(&endpoint0_context, 0, context_size);
endpoint0_context.endpoint_type = XHCI::EndpointType::Control;
endpoint0_context.max_packet_size = m_endpoints[0].max_packet_size;
endpoint0_context.error_count = 3;
endpoint0_context.tr_dequeue_pointer = m_endpoints[0].transfer_ring->paddr() | 1;
}
m_controller.dcbaa_reg(m_slot_id) = m_output_context->paddr();
for (int i = 0; i < 2; i++)
{
XHCI::TRB address_device { .address_device_command = {} };
address_device.address_device_command.trb_type = XHCI::TRBType::AddressDeviceCommand;
address_device.address_device_command.input_context_pointer = m_input_context->paddr();
// NOTE: some legacy devices require sending request with BSR=1 before actual BSR=0
address_device.address_device_command.block_set_address_request = (i == 0);
address_device.address_device_command.slot_id = m_slot_id;
TRY(m_controller.send_command(address_device));
}
// NOTE: Full speed devices can have other max packet sizes than 8
if (speed_class == USB::SpeedClass::FullSpeed)
TRY(update_actual_max_packet_size());
return {};
}
BAN::ErrorOr<void> XHCIDevice::update_actual_max_packet_size()
{
// FIXME: This is more or less generic USB code
dprintln_if(DEBUG_XHCI, "Retrieving actual max packet size of full speed device");
BAN::Vector<uint8_t> buffer;
TRY(buffer.resize(8, 0));
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Standard | USB::RequestType::Device;
request.bRequest = USB::Request::GET_DESCRIPTOR;
request.wValue = 0x0100;
request.wIndex = 0;
request.wLength = 8;
TRY(send_request(request, kmalloc_paddr_of((vaddr_t)buffer.data()).value()));
m_endpoints[0].max_packet_size = buffer.back();
const uint32_t context_size = m_controller.context_size_set() ? 64 : 32;
{
auto& input_control_context = *reinterpret_cast<XHCI::InputControlContext*>(m_input_context->vaddr() + 0 * context_size);
auto& slot_context = *reinterpret_cast<XHCI::SlotContext*> (m_input_context->vaddr() + 1 * context_size);
auto& endpoint0_context = *reinterpret_cast<XHCI::EndpointContext*> (m_input_context->vaddr() + 2 * context_size);
memset(&input_control_context, 0, context_size);
input_control_context.add_context_flags = 0b11;
memset(&slot_context, 0, context_size);
slot_context.max_exit_latency = 0; // FIXME:
slot_context.interrupter_target = 0;
memset(&endpoint0_context, 0, context_size);
endpoint0_context.endpoint_type = XHCI::EndpointType::Control;
endpoint0_context.max_packet_size = m_endpoints[0].max_packet_size;
endpoint0_context.error_count = 3;
endpoint0_context.tr_dequeue_pointer = m_endpoints[0].transfer_ring->paddr() | 1;
}
XHCI::TRB evaluate_context { .address_device_command = {} };
evaluate_context.address_device_command.trb_type = XHCI::TRBType::EvaluateContextCommand;
evaluate_context.address_device_command.input_context_pointer = m_input_context->paddr();
evaluate_context.address_device_command.block_set_address_request = 0;
evaluate_context.address_device_command.slot_id = m_slot_id;
TRY(m_controller.send_command(evaluate_context));
dprintln_if(DEBUG_XHCI, "successfully updated max packet size to {}", m_endpoints[0].max_packet_size);
return {};
}
BAN::ErrorOr<void> XHCIDevice::initialize_endpoint(const USBEndpointDescriptor& endpoint_descriptor)
{
const uint32_t endpoint_id = (endpoint_descriptor.bEndpointAddress & 0x0F) * 2 + !!(endpoint_descriptor.bEndpointAddress & 0x80);
auto& endpoint = m_endpoints[endpoint_id - 1];
ASSERT(!endpoint.transfer_ring);
uint32_t last_valid_endpoint_id = endpoint_id;
for (size_t i = endpoint_id; i < m_endpoints.size(); i++)
if (m_endpoints[i].transfer_ring)
last_valid_endpoint_id = i + 1;
endpoint.transfer_ring = TRY(DMARegion::create(m_transfer_ring_trb_count * sizeof(XHCI::TRB)));
endpoint.max_packet_size = endpoint_descriptor.wMaxPacketSize & 0x07FF;
endpoint.dequeue_index = 0;
endpoint.enqueue_index = 0;
endpoint.cycle_bit = 1;
endpoint.callback = &XHCIDevice::on_interrupt_endpoint_event;
endpoint.data_region = TRY(DMARegion::create(endpoint.max_packet_size));
memset(reinterpret_cast<void*>(endpoint.transfer_ring->vaddr()), 0, endpoint.transfer_ring->size());
{
const uint32_t context_size = m_controller.context_size_set() ? 64 : 32;
auto& input_control_context = *reinterpret_cast<XHCI::InputControlContext*>(m_input_context->vaddr());
auto& slot_context = *reinterpret_cast<XHCI::SlotContext*> (m_input_context->vaddr() + context_size);
auto& endpoint_context = *reinterpret_cast<XHCI::EndpointContext*> (m_input_context->vaddr() + (endpoint_id + 1) * context_size);
memset(&input_control_context, 0, context_size);
input_control_context.add_context_flags = (1u << endpoint_id) | 1;
memset(&slot_context, 0, context_size);
slot_context.context_entries = last_valid_endpoint_id;
// FIXME: 4.5.2 hub
ASSERT(endpoint_descriptor.bEndpointAddress & 0x80);
ASSERT((endpoint_descriptor.bmAttributes & 0x03) == 3);
ASSERT(m_controller.port(m_port_id).revision_major == 2);
memset(&endpoint_context, 0, context_size);
endpoint_context.endpoint_type = XHCI::EndpointType::InterruptIn;
endpoint_context.max_packet_size = endpoint.max_packet_size;
endpoint_context.max_burst_size = (endpoint_descriptor.wMaxPacketSize >> 11) & 0x0003;
endpoint_context.mult = 0;
endpoint_context.error_count = 3;
endpoint_context.tr_dequeue_pointer = endpoint.transfer_ring->paddr() | 1;
const uint32_t max_esit_payload = endpoint_context.max_packet_size * (endpoint_context.max_burst_size + 1);
endpoint_context.max_esit_payload_lo = max_esit_payload & 0xFFFF;
endpoint_context.max_esit_payload_hi = max_esit_payload >> 16;
}
XHCI::TRB configure_endpoint { .configure_endpoint_command = {} };
configure_endpoint.configure_endpoint_command.trb_type = XHCI::TRBType::ConfigureEndpointCommand;
configure_endpoint.configure_endpoint_command.input_context_pointer = m_input_context->paddr();
configure_endpoint.configure_endpoint_command.deconfigure = 0;
configure_endpoint.configure_endpoint_command.slot_id = m_slot_id;
TRY(m_controller.send_command(configure_endpoint));
auto& trb = *reinterpret_cast<volatile XHCI::TRB*>(endpoint.transfer_ring->vaddr());
memset(const_cast<XHCI::TRB*>(&trb), 0, sizeof(XHCI::TRB));
trb.normal.trb_type = XHCI::TRBType::Normal;
trb.normal.data_buffer_pointer = endpoint.data_region->paddr();
trb.normal.trb_transfer_length = endpoint.data_region->size();
trb.normal.td_size = 0;
trb.normal.interrupt_target = 0;
trb.normal.cycle_bit = 1;
trb.normal.interrupt_on_completion = 1;
trb.normal.interrupt_on_short_packet = 1;
advance_endpoint_enqueue(endpoint, false);
m_controller.doorbell_reg(m_slot_id) = endpoint_id;
return {};
}
void XHCIDevice::on_interrupt_endpoint_event(XHCI::TRB trb)
{
ASSERT(trb.trb_type == XHCI::TRBType::TransferEvent);
if (trb.transfer_event.completion_code != 1 && trb.transfer_event.completion_code != 13)
{
dwarnln("Interrupt endpoint got transfer event with completion code {}", +trb.transfer_event.completion_code);
return;
}
const uint32_t endpoint_id = trb.transfer_event.endpoint_id;
auto& endpoint = m_endpoints[endpoint_id - 1];
ASSERT(endpoint.transfer_ring && endpoint.data_region);
const uint32_t transfer_length = endpoint.max_packet_size - trb.transfer_event.trb_transfer_length;
auto received_data = BAN::ConstByteSpan(reinterpret_cast<uint8_t*>(endpoint.data_region->vaddr()), transfer_length);
handle_input_data(received_data, endpoint_id);
auto& new_trb = *reinterpret_cast<volatile XHCI::TRB*>(endpoint.transfer_ring->vaddr() + endpoint.enqueue_index * sizeof(XHCI::TRB));
memset(const_cast<XHCI::TRB*>(&new_trb), 0, sizeof(XHCI::TRB));
new_trb.normal.trb_type = XHCI::TRBType::Normal;
new_trb.normal.data_buffer_pointer = endpoint.data_region->paddr();
new_trb.normal.trb_transfer_length = endpoint.max_packet_size;
new_trb.normal.td_size = 0;
new_trb.normal.interrupt_target = 0;
new_trb.normal.cycle_bit = endpoint.cycle_bit;
new_trb.normal.interrupt_on_completion = 1;
new_trb.normal.interrupt_on_short_packet = 1;
advance_endpoint_enqueue(endpoint, false);
m_controller.doorbell_reg(m_slot_id) = endpoint_id;
}
void XHCIDevice::on_transfer_event(const volatile XHCI::TRB& trb)
{
ASSERT(trb.trb_type == XHCI::TRBType::TransferEvent);
if (trb.transfer_event.endpoint_id == 0)
{
dwarnln("TransferEvent for endpoint id 0");
return;
}
auto& endpoint = m_endpoints[trb.transfer_event.endpoint_id - 1];
if (endpoint.callback)
{
XHCI::TRB copy;
copy.raw.dword0 = trb.raw.dword0;
copy.raw.dword1 = trb.raw.dword1;
copy.raw.dword2 = trb.raw.dword2;
copy.raw.dword3 = trb.raw.dword3;
(this->*endpoint.callback)(copy);
return;
}
// Get received bytes from short packet
if (trb.transfer_event.completion_code == 13)
{
auto* transfer_trb_arr = reinterpret_cast<volatile XHCI::TRB*>(endpoint.transfer_ring->vaddr());
const uint32_t trb_index = (trb.transfer_event.trb_pointer - endpoint.transfer_ring->paddr()) / sizeof(XHCI::TRB);
const uint32_t full_trbs_transferred = (trb_index >= endpoint.dequeue_index)
? trb_index - 1 - endpoint.dequeue_index
: trb_index + m_transfer_ring_trb_count - 2 - endpoint.dequeue_index;
const uint32_t full_trb_data = full_trbs_transferred * endpoint.max_packet_size;
const uint32_t short_data = transfer_trb_arr[trb_index].data_stage.trb_transfer_length - trb.transfer_event.trb_transfer_length;
endpoint.transfer_count = full_trb_data + short_data;
ASSERT(trb_index >= endpoint.dequeue_index);
return;
}
// NOTE: dword2 is last (and atomic) as that is what send_request is waiting for
auto& completion_trb = endpoint.completion_trb;
completion_trb.raw.dword0 = trb.raw.dword0;
completion_trb.raw.dword1 = trb.raw.dword1;
completion_trb.raw.dword3 = trb.raw.dword3;
__atomic_store_n(&completion_trb.raw.dword2, trb.raw.dword2, __ATOMIC_SEQ_CST);
}
BAN::ErrorOr<size_t> XHCIDevice::send_request(const USBDeviceRequest& request, paddr_t buffer_paddr)
{
// FIXME: This is more or less generic USB code
auto& endpoint = m_endpoints[0];
// minus 3: Setup, Status, Link (this is probably too generous and will result in STALL)
if (request.wLength > (m_transfer_ring_trb_count - 3) * endpoint.max_packet_size)
return BAN::Error::from_errno((ENOBUFS));
LockGuard _(endpoint.mutex);
uint8_t transfer_type =
[&request]() -> uint8_t
{
if (request.wLength == 0)
return 0;
if (request.bmRequestType & USB::RequestType::DeviceToHost)
return 3;
return 2;
}();
auto* transfer_trb_arr = reinterpret_cast<volatile XHCI::TRB*>(endpoint.transfer_ring->vaddr());
{
auto& trb = transfer_trb_arr[endpoint.enqueue_index];
memset(const_cast<XHCI::TRB*>(&trb), 0, sizeof(XHCI::TRB));
trb.setup_stage.trb_type = XHCI::TRBType::SetupStage;
trb.setup_stage.transfer_type = transfer_type;
trb.setup_stage.trb_transfer_length = 8;
trb.setup_stage.interrupt_on_completion = 0;
trb.setup_stage.immediate_data = 1;
trb.setup_stage.cycle_bit = endpoint.cycle_bit;
trb.setup_stage.bmRequestType = request.bmRequestType;
trb.setup_stage.bRequest = request.bRequest;
trb.setup_stage.wValue = request.wValue;
trb.setup_stage.wIndex = request.wIndex;
trb.setup_stage.wLength = request.wLength;
advance_endpoint_enqueue(endpoint, false);
}
const uint32_t td_packet_count = BAN::Math::div_round_up<uint32_t>(request.wLength, endpoint.max_packet_size);
uint32_t packets_transferred = 1;
uint32_t bytes_handled = 0;
while (bytes_handled < request.wLength)
{
const uint32_t to_handle = BAN::Math::min<uint32_t>(endpoint.max_packet_size, request.wLength - bytes_handled);
auto& trb = transfer_trb_arr[endpoint.enqueue_index];
memset(const_cast<XHCI::TRB*>(&trb), 0, sizeof(XHCI::TRB));
trb.data_stage.trb_type = XHCI::TRBType::DataStage;
trb.data_stage.direction = 1;
trb.data_stage.trb_transfer_length = to_handle;
trb.data_stage.td_size = BAN::Math::min<uint32_t>(td_packet_count - packets_transferred, 31);
trb.data_stage.chain_bit = (bytes_handled + to_handle < request.wLength);
trb.data_stage.interrupt_on_completion = 0;
trb.data_stage.interrupt_on_short_packet = 1;
trb.data_stage.immediate_data = 0;
trb.data_stage.data_buffer_pointer = buffer_paddr + bytes_handled;
trb.data_stage.cycle_bit = endpoint.cycle_bit;
bytes_handled += to_handle;
packets_transferred++;
advance_endpoint_enqueue(endpoint, trb.data_stage.chain_bit);
}
{
auto& trb = transfer_trb_arr[endpoint.enqueue_index];
memset(const_cast<XHCI::TRB*>(&trb), 0, sizeof(XHCI::TRB));
trb.status_stage.trb_type = XHCI::TRBType::StatusStage;
trb.status_stage.direction = 0;
trb.status_stage.chain_bit = 0;
trb.status_stage.interrupt_on_completion = 1;
trb.data_stage.cycle_bit = endpoint.cycle_bit;
advance_endpoint_enqueue(endpoint, false);
}
auto& completion_trb = endpoint.completion_trb;
completion_trb.raw.dword0 = 0;
completion_trb.raw.dword1 = 0;
completion_trb.raw.dword2 = 0;
completion_trb.raw.dword3 = 0;
endpoint.transfer_count = request.wLength;
m_controller.doorbell_reg(m_slot_id) = 1;
const uint64_t timeout_ms = SystemTimer::get().ms_since_boot() + 1000;
while ((__atomic_load_n(&completion_trb.raw.dword2, __ATOMIC_SEQ_CST) >> 24) == 0)
if (SystemTimer::get().ms_since_boot() > timeout_ms)
return BAN::Error::from_errno(ETIMEDOUT);
endpoint.dequeue_index = endpoint.enqueue_index;
if (completion_trb.transfer_event.completion_code != 1)
{
dwarnln("Completion error: {}", +completion_trb.transfer_event.completion_code);
return BAN::Error::from_errno(EFAULT);
}
return endpoint.transfer_count;
}
void XHCIDevice::advance_endpoint_enqueue(Endpoint& endpoint, bool chain)
{
endpoint.enqueue_index++;
if (endpoint.enqueue_index < m_transfer_ring_trb_count - 1)
return;
// This is the last TRB in transfer ring. Make it link to the beginning of the ring
auto& link_trb = reinterpret_cast<volatile XHCI::TRB*>(endpoint.transfer_ring->vaddr())[endpoint.enqueue_index].link_trb;
link_trb.trb_type = XHCI::TRBType::Link;
link_trb.ring_segment_ponter = endpoint.transfer_ring->paddr();
link_trb.interrupter_target = 0;
link_trb.cycle_bit = endpoint.cycle_bit;
link_trb.toggle_cycle = 1;
link_trb.chain_bit = chain;
link_trb.interrupt_on_completion = 0;
endpoint.enqueue_index = 0;
endpoint.cycle_bit = !endpoint.cycle_bit;
}
}

View File

@ -27,7 +27,6 @@
#include <kernel/Terminal/Serial.h>
#include <kernel/Terminal/VirtualTTY.h>
#include <kernel/Timer/Timer.h>
#include <kernel/USB/USBManager.h>
#include <LibInput/KeyboardLayout.h>
@ -201,23 +200,16 @@ static void init2(void*)
// Initialize empty keymap
MUST(LibInput::KeyboardLayout::initialize());
// FIXME: initialize PS/2 after USB
//if (auto res = PS2Controller::initialize(); res.is_error())
// dprintln("{}", res.error());
if (auto res = PS2Controller::initialize(); res.is_error())
dprintln("{}", res.error());
MUST(NetworkManager::initialize());
MUST(USBManager::initialize());
// NOTE: PCI devices are the last ones to be initialized
// so other devices can reserve predefined interrupts
PCI::PCIManager::get().initialize_devices();
dprintln("PCI devices initialized");
// FIXME: This is very hacky way to wait until USB stack is initialized
SystemTimer::get().sleep(500);
VirtualFileSystem::initialize(cmdline.root);
dprintln("VFS initialized");

View File

@ -31,6 +31,5 @@ qemu-system-$QEMU_ARCH \
-drive format=raw,id=disk,file=${BANAN_DISK_IMAGE_PATH},if=none \
-device e1000e,netdev=net \
-netdev user,id=net \
-device qemu-xhci -device usb-kbd \
$DISK_ARGS \
$@ \

View File

@ -36,7 +36,7 @@ BAN::Optional<BAN::String> parse_dollar(BAN::StringView command, size_t& i)
ASSERT(command[i] == '$');
if (++i >= command.size())
return BAN::String("$"_sv);
return "$"_sv;
if (command[i] == '?')
{
@ -53,8 +53,8 @@ BAN::Optional<BAN::String> parse_dollar(BAN::StringView command, size_t& i)
i += len - 1;
if (const char* value = getenv(name.data()))
return BAN::String(value);
return BAN::String();
return BAN::StringView(value);
return ""_sv;
}
else if (command[i] == '{')
{
@ -74,8 +74,8 @@ BAN::Optional<BAN::String> parse_dollar(BAN::StringView command, size_t& i)
i += len;
if (const char* value = getenv(name.data()))
return BAN::String(value);
return BAN::String();
return BAN::StringView(value);
return ""_sv;
}
else if (command[i] == '[')
{

View File

@ -158,11 +158,11 @@ int main()
MUST(LibInput::KeyboardLayout::initialize());
MUST(LibInput::KeyboardLayout::get().load_from_file("/usr/share/keymaps/us.keymap"_sv));
int keyboard_fd = open("/dev/keyboard0", O_RDONLY);
int keyboard_fd = open("/dev/input0", O_RDONLY);
if (keyboard_fd == -1)
perror("open");
int mouse_fd = open("/dev/mouse0", O_RDONLY);
int mouse_fd = open("/dev/input1", O_RDONLY);
if (mouse_fd == -1)
perror("open");

View File

@ -50,7 +50,7 @@ void cleanup()
int main(int argc, char** argv)
{
const char* fb_path = "/dev/fb0";
const char* mouse_path = "/dev/mouse0";
const char* mouse_path = "/dev/input1";
if (argc == 1)
;