69 lines
1.5 KiB
C++
69 lines
1.5 KiB
C++
#include "keyboard/keyboard_driver.h"
|
|
|
|
#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(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));
|
|
}
|
|
|
|
Thread KeyboardDriver::StartInterruptLoop() {
|
|
return Thread(InterruptEnter, this);
|
|
}
|
|
|
|
void KeyboardDriver::InterruptLoop() {
|
|
dbgln("Interrupt");
|
|
while (true) {
|
|
uint64_t scancode;
|
|
uint64_t num_bytes = 8;
|
|
uint64_t num_caps = 0;
|
|
check(ZPortRecv(port_cap_, &num_bytes, &scancode, &num_caps, nullptr));
|
|
|
|
ProcessInput(scancode);
|
|
}
|
|
}
|
|
|
|
void KeyboardDriver::ProcessInput(uint64_t input) {
|
|
uint16_t modifiers = (input & 0xFF) << 8;
|
|
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(modifiers | code);
|
|
}
|
|
}
|
|
bitmap_ = new_bitmap;
|
|
}
|
|
|
|
void KeyboardDriver::SendKeypress(uint16_t scancode) {
|
|
for (mmth::PortClient& client : listeners_) {
|
|
client.Write(scancode);
|
|
}
|
|
}
|