[Voyageurs] Send USB keypress data to the keyboard driver.

This commit is contained in:
Drew Galbraith 2024-02-24 14:59:33 -08:00
parent 3c1e435e04
commit 02d4f8c80e
10 changed files with 79 additions and 20 deletions

View File

@ -19,4 +19,9 @@ glcr::ErrorCode PortClient::WriteByte(uint8_t byte) {
return static_cast<glcr::ErrorCode>(
ZPortSend(port_cap_, 1, &byte, 0, nullptr));
}
glcr::ErrorCode PortClient::Write(uint64_t data) {
return static_cast<glcr::ErrorCode>(
ZPortSend(port_cap_, 8, &data, 0, nullptr));
}
} // namespace mmth

View File

@ -10,6 +10,7 @@ namespace mmth {
class PortClient {
public:
PortClient() {}
PortClient(z_cap_t port_cap);
static PortClient AdoptPort(z_cap_t port_cap);
template <typename T>
@ -18,6 +19,7 @@ class PortClient {
glcr::ErrorCode WriteString(glcr::String str, z_cap_t cap);
glcr::ErrorCode WriteByte(uint8_t byte);
glcr::ErrorCode Write(uint64_t data);
z_cap_t cap() { return port_cap_; }
@ -25,8 +27,6 @@ class PortClient {
private:
z_cap_t port_cap_ = 0;
PortClient(z_cap_t port_cap);
};
template <typename T>

View File

@ -2,13 +2,24 @@
#include <mammoth/util/debug.h>
namespace {
KeyboardDriver* gKeyboardDriver = nullptr;
}
void InterruptEnter(void* void_keyboard) {
KeyboardDriver* keyboard = static_cast<KeyboardDriver*>(void_keyboard);
keyboard->InterruptLoop();
}
KeyboardDriver::KeyboardDriver() { check(ZIrqRegister(kZIrqKbd, &irq_cap_)); }
KeyboardDriver::KeyboardDriver() {
check(ZPortCreate(&port_cap_));
gKeyboardDriver = this;
}
z_cap_t KeyboardDriver::GetPortCap() { return gKeyboardDriver->port_cap_; }
void KeyboardDriver::RegisterListener(uint64_t port_cap) {
listeners_.PushFront(mmth::PortClient::AdoptPort(port_cap));
@ -21,13 +32,37 @@ Thread KeyboardDriver::StartInterruptLoop() {
void KeyboardDriver::InterruptLoop() {
dbgln("Interrupt");
while (true) {
uint8_t scancode;
uint64_t num_bytes = 1;
uint64_t scancode;
uint64_t num_bytes = 8;
uint64_t num_caps = 0;
check(ZPortRecv(irq_cap_, &num_bytes, &scancode, &num_caps, nullptr));
check(ZPortRecv(port_cap_, &num_bytes, &scancode, &num_caps, nullptr));
for (mmth::PortClient& client : listeners_) {
client.WriteByte(scancode);
}
ProcessInput(scancode);
}
}
void KeyboardDriver::ProcessInput(uint64_t input) {
uint64_t new_bitmap = 0;
for (uint8_t i = 2; i < 8; i++) {
uint8_t code = (input >> (8 * i)) & 0xFF;
if (code == 0) {
break;
}
if (code >= 64) {
dbgln("Skipping keycode: {x}", code);
}
uint64_t bit = 1 << code;
new_bitmap |= bit;
if ((bitmap_ & bit) != bit) {
SendKeypress(code);
}
}
bitmap_ = new_bitmap;
}
void KeyboardDriver::SendKeypress(uint8_t scancode) {
dbgln("{x}", scancode);
for (mmth::PortClient& client : listeners_) {
client.WriteByte(scancode);
}
}

View File

@ -11,12 +11,19 @@ class KeyboardDriver {
KeyboardDriver(const KeyboardDriver&) = delete;
KeyboardDriver(KeyboardDriver&&) = delete;
static z_cap_t GetPortCap();
void RegisterListener(uint64_t port_cap);
Thread StartInterruptLoop();
void InterruptLoop();
private:
z_cap_t irq_cap_;
z_cap_t port_cap_;
glcr::LinkedList<mmth::PortClient> listeners_;
uint64_t bitmap_ = 0;
void ProcessInput(uint64_t input);
void SendKeypress(uint8_t scancode);
};

View File

@ -15,11 +15,10 @@ uint64_t main(uint64_t init_port) {
YellowstoneClient yellowstone(gInitEndpointCap);
ASSIGN_OR_RETURN(auto xhci, XhciDriver::InitiateDriver(yellowstone));
dbgln("Initializing PS/2 Driver.");
KeyboardDriver driver;
ASSIGN_OR_RETURN(auto xhci, XhciDriver::InitiateDriver(yellowstone));
dbgln("Starting PS/2 Thread.");
Thread keyboard_thread = driver.StartInterruptLoop();

View File

@ -80,7 +80,8 @@ void DeviceSlot::TransferComplete(uint8_t endpoint_index, uint64_t trb_phys) {
check(control_completion_sempahores_.Delete(trb_phys));
}
mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(uint8_t config_value) {
mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(
uint8_t config_value, glcr::UniquePtr<mmth::PortClient> client) {
input_context_->input.add_contexts = (0x1 << 3) | 0x1;
input_context_->input.configuration_value = config_value;
// TODO: Maybe don't hardcode this.
@ -93,7 +94,8 @@ mmth::Semaphore DeviceSlot::IssueConfigureDeviceCommand(uint8_t config_value) {
input_context_->slot_context.route_speed_entries |= (max_endpoint << 27);
// TODO: Dont' hardcode this.
endpoints_[3].Initialize(input_context_->endpoint_contexts + 2);
endpoints_[3].Initialize(input_context_->endpoint_contexts + 2,
glcr::Move(client));
xhci_driver_->IssueCommand(CreateConfigureEndpointCommand(
context_phys_ + kInputSlotContextOffset, slot_index_));

View File

@ -28,7 +28,8 @@ class DeviceSlot {
XhciTrb CreateAddressDeviceCommand(uint8_t root_port, uint32_t route_string,
uint16_t max_packet_size);
mmth::Semaphore IssueConfigureDeviceCommand(uint8_t config_value);
mmth::Semaphore IssueConfigureDeviceCommand(
uint8_t config_value, glcr::UniquePtr<mmth::PortClient> client);
void SignalConfigureDeviceCompleted();
// Caller must keep the command in scope until it completes.

View File

@ -4,9 +4,11 @@
#include "xhci/trb.h"
void Endpoint::Initialize(XhciEndpointContext* context) {
void Endpoint::Initialize(XhciEndpointContext* context,
glcr::UniquePtr<mmth::PortClient> client) {
enabled_ = true;
context_ = context;
client_ = glcr::Move(client);
trb_ring_ = glcr::MakeUnique<TrbRingWriter>();
recv_mem_ = mmth::OwnedMemoryRegion::ContiguousPhysical(0x1000, &recv_phys_);
@ -23,7 +25,8 @@ void Endpoint::Initialize(XhciEndpointContext* context) {
void Endpoint::TransferComplete(uint64_t trb_phys) {
uint64_t phys_offset =
(trb_phys - trb_ring_->PhysicalAddress()) / sizeof(XhciTrb);
dbgln("Data: {x}", *((uint64_t*)recv_mem_.vaddr() + phys_offset));
uint64_t data = *((uint64_t*)recv_mem_.vaddr() + phys_offset);
client_->Write(data);
trb_ring_->EnqueueTrb(CreateNormalTrb(recv_phys_ + offset_, 8));
offset_ += 8;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <glacier/memory/unique_ptr.h>
#include <mammoth/ipc/port_client.h>
#include "xhci/trb_ring.h"
#include "xhci/xhci.h"
@ -9,7 +10,8 @@ class Endpoint {
public:
Endpoint() {}
void Initialize(XhciEndpointContext* context);
void Initialize(XhciEndpointContext* context,
glcr::UniquePtr<mmth::PortClient> client);
bool Enabled() { return enabled_; }
@ -24,4 +26,6 @@ class Endpoint {
uint64_t recv_phys_;
mmth::OwnedMemoryRegion recv_mem_;
uint64_t offset_ = 0;
glcr::UniquePtr<mmth::PortClient> client_;
};

View File

@ -5,6 +5,7 @@
#include <mammoth/util/memory_region.h>
#include <zcall.h>
#include "keyboard/keyboard_driver.h"
#include "xhci/descriptors.h"
#include "xhci/trb.h"
#include "xhci/xhci.h"
@ -75,7 +76,9 @@ void configure_device(void* void_device_slot) {
config_descriptor->configuration_value);
device_slot
->IssueConfigureDeviceCommand(config_descriptor->configuration_value)
->IssueConfigureDeviceCommand(
config_descriptor->configuration_value,
glcr::MakeUnique<mmth::PortClient>(KeyboardDriver::GetPortCap()))
.Wait();
dbgln("Configured!");