diff --git a/kernel/include/kernel/Input/PS2/Controller.h b/kernel/include/kernel/Input/PS2/Controller.h index 0eeb695b..59a75420 100644 --- a/kernel/include/kernel/Input/PS2/Controller.h +++ b/kernel/include/kernel/Input/PS2/Controller.h @@ -15,7 +15,7 @@ namespace Kernel::Input class PS2Controller { public: - static BAN::ErrorOr initialize(); + static BAN::ErrorOr initialize(uint8_t scancode_set); static PS2Controller& get(); bool append_command_queue(PS2Device*, uint8_t command, uint8_t response_size); @@ -26,8 +26,8 @@ namespace Kernel::Input private: PS2Controller() = default; - BAN::ErrorOr initialize_impl(); - BAN::ErrorOr initialize_device(uint8_t); + BAN::ErrorOr initialize_impl(uint8_t scancode_set); + BAN::ErrorOr initialize_device(uint8_t, uint8_t scancode_set); BAN::ErrorOr read_byte(); BAN::ErrorOr send_byte(uint16_t port, uint8_t byte); diff --git a/kernel/include/kernel/Input/PS2/Keyboard.h b/kernel/include/kernel/Input/PS2/Keyboard.h index b4a07009..81c8eb02 100644 --- a/kernel/include/kernel/Input/PS2/Keyboard.h +++ b/kernel/include/kernel/Input/PS2/Keyboard.h @@ -17,7 +17,7 @@ namespace Kernel::Input }; public: - static BAN::ErrorOr> create(PS2Controller&); + static BAN::ErrorOr> create(PS2Controller&, uint8_t scancode_set); virtual void send_initialize() override; virtual void command_timedout(uint8_t* command_data, uint8_t command_size) final override; @@ -27,13 +27,14 @@ namespace Kernel::Input virtual void update() final override { m_controller.update_command_queue(); } private: - PS2Keyboard(PS2Controller& controller); + PS2Keyboard(PS2Controller& controller, bool basic); void update_leds(); private: BAN::Array m_byte_buffer; uint8_t m_byte_index { 0 }; + bool m_basic { false }; uint8_t m_scancode_set { 0xFF }; uint16_t m_modifiers { 0 }; diff --git a/kernel/kernel/Input/PS2/Controller.cpp b/kernel/kernel/Input/PS2/Controller.cpp index 6f7ce698..a16d2f6c 100644 --- a/kernel/kernel/Input/PS2/Controller.cpp +++ b/kernel/kernel/Input/PS2/Controller.cpp @@ -221,14 +221,14 @@ namespace Kernel::Input ASSERT_NOT_REACHED(); } - BAN::ErrorOr PS2Controller::initialize() + BAN::ErrorOr PS2Controller::initialize(uint8_t scancode_set) { ASSERT(s_instance == nullptr); s_instance = new PS2Controller; if (s_instance == nullptr) return BAN::Error::from_errno(ENOMEM); BAN::ScopeGuard guard([] { delete s_instance; }); - TRY(s_instance->initialize_impl()); + TRY(s_instance->initialize_impl(scancode_set)); guard.disable(); return {}; } @@ -239,7 +239,7 @@ namespace Kernel::Input return *s_instance; } - BAN::ErrorOr PS2Controller::initialize_impl() + BAN::ErrorOr PS2Controller::initialize_impl(uint8_t scancode_set) { // Determine if the PS/2 Controller Exists auto* fadt = static_cast(ACPI::ACPI::get().get_header("FACP"_sv, 0)); @@ -317,7 +317,7 @@ namespace Kernel::Input dwarnln_if(DEBUG_PS2, "PS/2 device enable failed: {}", ret.error()); continue; } - if (auto res = initialize_device(device); res.is_error()) + if (auto res = initialize_device(device, scancode_set); res.is_error()) { dwarnln_if(DEBUG_PS2, "PS/2 device initialization failed: {}", res.error()); (void)send_command(device == 0 ? PS2::Command::DISABLE_FIRST_PORT : PS2::Command::DISABLE_SECOND_PORT); @@ -368,7 +368,7 @@ namespace Kernel::Input return {}; } - BAN::ErrorOr PS2Controller::initialize_device(uint8_t device) + BAN::ErrorOr PS2Controller::initialize_device(uint8_t device, uint8_t scancode_set) { // Reset device TRY(device_send_byte_and_wait_ack(device, PS2::DeviceCommand::RESET)); @@ -411,7 +411,7 @@ namespace Kernel::Input if (index == 2 && (bytes[0] == 0xAB && (bytes[1] == 0x83 || bytes[1] == 0x41))) { dprintln_if(DEBUG_PS2, "PS/2 found keyboard"); - m_devices[device] = TRY(PS2Keyboard::create(*this)); + m_devices[device] = TRY(PS2Keyboard::create(*this, scancode_set)); return {}; } diff --git a/kernel/kernel/Input/PS2/Keyboard.cpp b/kernel/kernel/Input/PS2/Keyboard.cpp index 13ea5fd4..a0ca4b95 100644 --- a/kernel/kernel/Input/PS2/Keyboard.cpp +++ b/kernel/kernel/Input/PS2/Keyboard.cpp @@ -9,21 +9,41 @@ namespace Kernel::Input { - BAN::ErrorOr> PS2Keyboard::create(PS2Controller& controller) + BAN::ErrorOr> PS2Keyboard::create(PS2Controller& controller, uint8_t scancode_set) { - return TRY(BAN::RefPtr::create(controller)); + auto keyboard = TRY(BAN::RefPtr::create(controller, scancode_set != 0)); + if (scancode_set) + { + if (scancode_set > 3) + { + dwarnln("Invalid scancode set {}, using scan code set 2 instead", scancode_set); + scancode_set = 2; + } + keyboard->m_scancode_set = scancode_set; + keyboard->m_keymap.initialize(scancode_set); + dprintln("Skipping scancode detection, using scan code set {}", scancode_set); + } + return keyboard; } - PS2Keyboard::PS2Keyboard(PS2Controller& controller) + PS2Keyboard::PS2Keyboard(PS2Controller& controller, bool basic) : PS2Device(controller, InputDevice::Type::Keyboard) + , m_basic(basic) { } void PS2Keyboard::send_initialize() { constexpr uint8_t wanted_scancode_set = 3; - append_command_queue(Command::SET_LEDS, 0x00, 0); - append_command_queue(Command::CONFIG_SCANCODE_SET, wanted_scancode_set, 0); - append_command_queue(Command::CONFIG_SCANCODE_SET, 0, 1); + update_leds(); + if (m_scancode_set == 0xFF) + { + append_command_queue(Command::CONFIG_SCANCODE_SET, wanted_scancode_set, 0); + append_command_queue(Command::CONFIG_SCANCODE_SET, 0, 1); + } + else + { + append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING, 0); + } } void PS2Keyboard::command_timedout(uint8_t* command_data, uint8_t command_size) @@ -33,8 +53,8 @@ namespace Kernel::Input if (command_data[0] == Command::CONFIG_SCANCODE_SET && m_scancode_set >= 0xFE) { - dwarnln("Could not detect scancode set, assuming 1"); - m_scancode_set = 1; + dwarnln("Could not detect scancode set, assuming 2"); + m_scancode_set = 2; m_keymap.initialize(m_scancode_set); append_command_queue(PS2::DeviceCommand::ENABLE_SCANNING, 0); } @@ -169,6 +189,9 @@ namespace Kernel::Input { using KeyModifier = LibInput::KeyEvent::Modifier; + if (m_basic) + return; + uint8_t new_leds = 0; if (m_modifiers & +KeyModifier::ScrollLock) new_leds |= PS2::KBLeds::SCROLL_LOCK; diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index de908d96..124334d3 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -32,12 +32,15 @@ #include +#include + struct ParsedCommandLine { - bool force_pic = false; - bool disable_serial = false; - bool disable_smp = false; - bool disable_usb = false; + bool force_pic = false; + bool disable_serial = false; + bool disable_smp = false; + bool disable_usb = false; + uint8_t ps2_override = 0; BAN::StringView console = "tty0"_sv; BAN::StringView root; }; @@ -78,6 +81,12 @@ static void parse_command_line() cmdline.disable_smp = true; else if (argument == "nousb") cmdline.disable_usb = true; + else if (argument.starts_with("ps2=")) + { + if (argument.size() != 5 || !isdigit(argument[4])) + dprintln("Invalid ps2= command line argument format '{}'", argument); + cmdline.ps2_override = argument[4] - '0'; + } else if (argument.size() > 5 && argument.substring(0, 5) == "root=") cmdline.root = argument.substring(5); else if (argument.size() > 8 && argument.substring(0, 8) == "console=") @@ -221,7 +230,7 @@ static void init2(void*) // Initialize empty keymap MUST(LibInput::KeyboardLayout::initialize()); - if (auto res = PS2Controller::initialize(); res.is_error()) + if (auto res = PS2Controller::initialize(cmdline.ps2_override); res.is_error()) dprintln("{}", res.error()); MUST(NetworkManager::initialize());