banan-os/kernel/kernel/USB/HID/Keyboard.cpp

396 lines
13 KiB
C++

#include <kernel/Timer/Timer.h>
#include <kernel/USB/HID/Keyboard.h>
#include <LibInput/KeyEvent.h>
namespace Kernel
{
static constexpr uint64_t s_repeat_initial_ms = 500;
static constexpr uint64_t s_repeat_interval_ms = 50;
static BAN::Optional<uint8_t> s_scancode_to_keycode[0x100] {};
static bool s_scancode_to_keycode_initialized = false;
static void initialize_scancode_to_keycode();
static constexpr bool is_repeatable_scancode(uint8_t scancode);
USBKeyboard::USBKeyboard(USBHIDDriver& driver, BAN::Vector<USBHID::Report>&& outputs)
: USBHIDDevice(InputDevice::Type::Keyboard)
, m_driver(driver)
, m_outputs(BAN::move(outputs))
{
set_leds(0);
}
void USBKeyboard::start_report()
{
m_lock_state = m_keyboard_lock.lock();
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.
uint16_t modifier = 0;
#define READ_MODIFIER(scancode, key_modifier) \
if (m_keyboard_state_temp[scancode]) \
modifier |= key_modifier;
READ_MODIFIER(0xE1, KeyModifier::LShift);
READ_MODIFIER(0xE5, KeyModifier::RShift);
READ_MODIFIER(0xE0, KeyModifier::LCtrl);
READ_MODIFIER(0xE4, KeyModifier::RCtrl);
READ_MODIFIER(0xE2, KeyModifier::LAlt);
READ_MODIFIER(0xE6, KeyModifier::RAlt);
#undef READ_MODIFIER
#define READ_TOGGLE(scancode, key_modifier) \
if (m_keyboard_state_temp[scancode] && !m_keyboard_state[scancode]) \
m_toggle_mask ^= key_modifier;
READ_TOGGLE(0x39, KeyModifier::CapsLock);
READ_TOGGLE(0x47, KeyModifier::ScrollLock);
READ_TOGGLE(0x53, KeyModifier::NumLock);
#undef READ_TOGGLE
modifier |= m_toggle_mask;
BAN::Optional<uint8_t> new_scancode;
for (size_t i = 0; i < m_keyboard_state.size(); i++)
{
if (m_keyboard_state[i] == m_keyboard_state_temp[i])
continue;
if (m_keyboard_state_temp[i] && is_repeatable_scancode(i))
new_scancode = i;
const bool pressed = m_keyboard_state_temp[i];
if (pressed)
dprintln_if(DEBUG_USB_KEYBOARD, "Pressed {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];
}
if (m_repeat_scancode.has_value() && !m_keyboard_state_temp[m_repeat_scancode.value()])
m_repeat_scancode.clear();
m_repeat_modifier = modifier;
if (new_scancode.has_value())
{
if (!m_repeat_scancode.has_value() || m_repeat_scancode.value() != new_scancode.value())
{
m_repeat_scancode = new_scancode;
m_next_repeat_event_ms = SystemTimer::get().ms_since_boot() + s_repeat_initial_ms;
}
}
m_keyboard_lock.unlock(m_lock_state);
}
void USBKeyboard::handle_variable(uint16_t usage_page, uint16_t usage, int64_t state)
{
ASSERT(m_keyboard_lock.current_processor_has_lock());
if (usage_page != 0x07)
{
dprintln_if(DEBUG_USB_KEYBOARD, "Unsupported keyboard usage page {2H}", usage_page);
return;
}
if (!state)
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)
{
ASSERT(m_keyboard_lock.current_processor_has_lock());
if (usage_page != 0x07)
{
dprintln_if(DEBUG_USB_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 USBKeyboard::update()
{
using KeyModifier = LibInput::KeyEvent::Modifier;
const auto toggle_mask = ({ SpinLockGuard _(m_keyboard_lock); m_toggle_mask; });
if (m_led_mask != toggle_mask)
set_leds(toggle_mask);
m_led_mask = toggle_mask;
SpinLockGuard _(m_keyboard_lock);
if (!m_repeat_scancode.has_value() || SystemTimer::get().ms_since_boot() < m_next_repeat_event_ms)
return;
auto opt_keycode = s_scancode_to_keycode[m_repeat_scancode.value()];
if (!opt_keycode.has_value())
return;
LibInput::RawKeyEvent event;
event.keycode = opt_keycode.value();
event.modifier = m_repeat_modifier | KeyModifier::Pressed;
add_event(BAN::ConstByteSpan::from(event));
m_next_repeat_event_ms += s_repeat_interval_ms;
}
void USBKeyboard::set_leds(uint16_t mask)
{
uint8_t report_ids_done[0x100 / 8] {};
for (const auto& report : m_outputs)
{
if (report.usage_page != 0x08)
continue;
const auto byte = report.report_id / 8;
const auto bit = report.report_id % 8;
if (report_ids_done[byte] & (1u << bit))
continue;
set_leds(report.report_id, mask);
report_ids_done[byte] |= (1u << bit);
}
}
void USBKeyboard::set_leds(uint8_t report_id, uint16_t mask)
{
using KeyModifier = LibInput::KeyEvent::Modifier;
size_t report_bits = 0;
for (const auto& report : m_outputs)
{
if (report.report_id != report_id)
continue;
report_bits += report.report_size * report.report_count;
}
const size_t report_bytes = (report_bits + 7) / 8;
uint8_t* data = static_cast<uint8_t*>(kmalloc(report_bytes));
if (data == nullptr)
return;
memset(data, 0, report_bytes);
size_t bit_offset = 0;
for (const auto& report : m_outputs)
{
if (report.report_id != report_id)
continue;
for (size_t i = 0; report.report_size == 1 && i < report.report_count; i++, bit_offset++)
{
const size_t usage = (report.usage_id ? report.usage_id : report.usage_minimum) + bit_offset;
switch (usage)
{
case 0x01:
if (mask & KeyModifier::NumLock)
data[bit_offset / 8] |= 1u << (bit_offset % 8);
break;
case 0x02:
if (mask & KeyModifier::CapsLock)
data[bit_offset / 8] |= 1u << (bit_offset % 8);
break;
case 0x03:
if (mask & KeyModifier::ScrollLock)
data[bit_offset / 8] |= 1u << (bit_offset % 8);
break;
}
}
bit_offset += report.report_size * report.report_count;
}
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Class | USB::RequestType::Interface;
request.bRequest = 0x09;
request.wValue = 0x0200 | report_id;
request.wIndex = m_driver.interface().descriptor.bInterfaceNumber;
request.wLength = report_bytes;
if (auto ret = m_driver.device().send_request(request, kmalloc_paddr_of(reinterpret_cast<vaddr_t>(data)).value()); ret.is_error())
dprintln_if(DEBUG_USB_KEYBOARD, "Failed to update LEDs: {}", ret.error());
kfree(data);
}
void initialize_scancode_to_keycode()
{
using LibInput::keycode_function;
using LibInput::keycode_normal;
using LibInput::keycode_numpad;
for (auto& mapping : s_scancode_to_keycode)
mapping.clear();
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, 0);
s_scancode_to_keycode[0xE3] = keycode_normal(4, 1);
s_scancode_to_keycode[0xE2] = keycode_normal(4, 2);
s_scancode_to_keycode[0x2C] = keycode_normal(4, 3);
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[0x47] = keycode_function(20);
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;
}
constexpr bool is_repeatable_scancode(uint8_t scancode)
{
switch (scancode)
{
case 0x00: // reserved
case 0x01: // error roll over
case 0x02: // post fail
case 0x03: // error undefined
case 0x29: // escape
case 0x39: // caps lock
case 0x3A: // f1
case 0x3B: // f2
case 0x3C: // f3
case 0x3D: // f4
case 0x3E: // f5
case 0x3F: // f6
case 0x40: // f7
case 0x41: // f8
case 0x42: // f9
case 0x43: // f10
case 0x44: // f11
case 0x45: // f12
case 0x47: // scroll lock
case 0x53: // num lock
case 0xE0: // left control
case 0xE1: // left shift
case 0xE2: // left alt
case 0xE3: // left super
case 0xE4: // right control
case 0xE5: // right shift
case 0xE6: // right alt
case 0xE7: // right super
return false;
default:
return true;
}
}
}