banan-os/kernel/include/kernel/Input/PS2/Controller.h

72 lines
1.8 KiB
C++

#pragma once
#include <BAN/CircularQueue.h>
#include <BAN/UniqPtr.h>
#include <kernel/Device/Device.h>
#include <kernel/Input/PS2/Config.h>
#include <kernel/InterruptController.h>
#include <kernel/Lock/Mutex.h>
namespace Kernel::Input
{
class PS2Device;
class PS2Controller
{
public:
static BAN::ErrorOr<void> initialize(uint8_t scancode_set);
static PS2Controller& get();
bool append_command_queue(PS2Device*, uint8_t command, uint8_t response_size);
bool append_command_queue(PS2Device*, uint8_t command, uint8_t data, uint8_t response_size);
void update_command_queue();
// Returns true, if byte is used as command, if returns false, byte is meant to device
bool handle_command_byte(PS2Device*, uint8_t);
private:
PS2Controller() = default;
BAN::ErrorOr<void> initialize_impl(uint8_t scancode_set);
BAN::ErrorOr<void> initialize_device(uint8_t, uint8_t scancode_set);
BAN::ErrorOr<uint8_t> read_byte();
BAN::ErrorOr<void> send_byte(uint16_t port, uint8_t byte);
BAN::ErrorOr<void> send_command(PS2::Command command);
BAN::ErrorOr<void> send_command(PS2::Command command, uint8_t data);
BAN::ErrorOr<void> device_send_byte(uint8_t device_index, uint8_t byte);
BAN::ErrorOr<void> device_send_byte_and_wait_ack(uint8_t device_index, uint8_t byte);
uint8_t get_device_index(PS2Device*) const;
private:
struct Command
{
enum class State : uint8_t
{
NotSent,
Sending,
WaitingAck,
WaitingResponse,
};
State state;
uint8_t device_index;
uint8_t out_data[2];
uint8_t out_count;
uint8_t in_count;
uint8_t send_index;
};
private:
BAN::RefPtr<PS2Device> m_devices[2];
Mutex m_mutex;
BAN::CircularQueue<Command, 128> m_command_queue;
uint64_t m_command_send_time { 0 };
RecursiveSpinLock m_command_lock;
};
}