From 02d4f8c80e5e167e3a9bfa7fb0f6aeb5bb546e81 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Sat, 24 Feb 2024 14:59:33 -0800 Subject: [PATCH] [Voyageurs] Send USB keypress data to the keyboard driver. --- lib/mammoth/ipc/port_client.cpp | 5 +++ lib/mammoth/ipc/port_client.h | 4 +- sys/voyageurs/keyboard/keyboard_driver.cpp | 49 ++++++++++++++++++---- sys/voyageurs/keyboard/keyboard_driver.h | 9 +++- sys/voyageurs/voyageurs.cpp | 5 +-- sys/voyageurs/xhci/device_slot.cpp | 6 ++- sys/voyageurs/xhci/device_slot.h | 3 +- sys/voyageurs/xhci/endpoint.cpp | 7 +++- sys/voyageurs/xhci/endpoint.h | 6 ++- sys/voyageurs/xhci/xhci_driver.cpp | 5 ++- 10 files changed, 79 insertions(+), 20 deletions(-) diff --git a/lib/mammoth/ipc/port_client.cpp b/lib/mammoth/ipc/port_client.cpp index 3c9f909..8bf1156 100644 --- a/lib/mammoth/ipc/port_client.cpp +++ b/lib/mammoth/ipc/port_client.cpp @@ -19,4 +19,9 @@ glcr::ErrorCode PortClient::WriteByte(uint8_t byte) { return static_cast( ZPortSend(port_cap_, 1, &byte, 0, nullptr)); } + +glcr::ErrorCode PortClient::Write(uint64_t data) { + return static_cast( + ZPortSend(port_cap_, 8, &data, 0, nullptr)); +} } // namespace mmth diff --git a/lib/mammoth/ipc/port_client.h b/lib/mammoth/ipc/port_client.h index 80571a3..c4fc222 100644 --- a/lib/mammoth/ipc/port_client.h +++ b/lib/mammoth/ipc/port_client.h @@ -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 @@ -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 diff --git a/sys/voyageurs/keyboard/keyboard_driver.cpp b/sys/voyageurs/keyboard/keyboard_driver.cpp index f96a3ad..43f921f 100644 --- a/sys/voyageurs/keyboard/keyboard_driver.cpp +++ b/sys/voyageurs/keyboard/keyboard_driver.cpp @@ -2,13 +2,24 @@ #include +namespace { + +KeyboardDriver* gKeyboardDriver = nullptr; + +} + void InterruptEnter(void* void_keyboard) { KeyboardDriver* keyboard = static_cast(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); } } diff --git a/sys/voyageurs/keyboard/keyboard_driver.h b/sys/voyageurs/keyboard/keyboard_driver.h index b38af0e..84715e1 100644 --- a/sys/voyageurs/keyboard/keyboard_driver.h +++ b/sys/voyageurs/keyboard/keyboard_driver.h @@ -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 listeners_; + + uint64_t bitmap_ = 0; + + void ProcessInput(uint64_t input); + void SendKeypress(uint8_t scancode); }; diff --git a/sys/voyageurs/voyageurs.cpp b/sys/voyageurs/voyageurs.cpp index 660f2b5..663d972 100644 --- a/sys/voyageurs/voyageurs.cpp +++ b/sys/voyageurs/voyageurs.cpp @@ -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(); diff --git a/sys/voyageurs/xhci/device_slot.cpp b/sys/voyageurs/xhci/device_slot.cpp index ba6f29a..e9fc3b4 100644 --- a/sys/voyageurs/xhci/device_slot.cpp +++ b/sys/voyageurs/xhci/device_slot.cpp @@ -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 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_)); diff --git a/sys/voyageurs/xhci/device_slot.h b/sys/voyageurs/xhci/device_slot.h index b228ba7..473d1c5 100644 --- a/sys/voyageurs/xhci/device_slot.h +++ b/sys/voyageurs/xhci/device_slot.h @@ -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 client); void SignalConfigureDeviceCompleted(); // Caller must keep the command in scope until it completes. diff --git a/sys/voyageurs/xhci/endpoint.cpp b/sys/voyageurs/xhci/endpoint.cpp index 3cfb568..6583953 100644 --- a/sys/voyageurs/xhci/endpoint.cpp +++ b/sys/voyageurs/xhci/endpoint.cpp @@ -4,9 +4,11 @@ #include "xhci/trb.h" -void Endpoint::Initialize(XhciEndpointContext* context) { +void Endpoint::Initialize(XhciEndpointContext* context, + glcr::UniquePtr client) { enabled_ = true; context_ = context; + client_ = glcr::Move(client); trb_ring_ = glcr::MakeUnique(); 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; } diff --git a/sys/voyageurs/xhci/endpoint.h b/sys/voyageurs/xhci/endpoint.h index 920620a..fd4a4d0 100644 --- a/sys/voyageurs/xhci/endpoint.h +++ b/sys/voyageurs/xhci/endpoint.h @@ -1,6 +1,7 @@ #pragma once #include +#include #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 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 client_; }; diff --git a/sys/voyageurs/xhci/xhci_driver.cpp b/sys/voyageurs/xhci/xhci_driver.cpp index 78f6d70..ce1a128 100644 --- a/sys/voyageurs/xhci/xhci_driver.cpp +++ b/sys/voyageurs/xhci/xhci_driver.cpp @@ -5,6 +5,7 @@ #include #include +#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(KeyboardDriver::GetPortCap())) .Wait(); dbgln("Configured!");