Kernel: Add ps2=<scancode set> command line argument
This allows forcing specific scancode set on broken PS/2 emulations
This commit is contained in:
parent
40c6989374
commit
42e2c15e0c
|
@ -15,7 +15,7 @@ namespace Kernel::Input
|
|||
class PS2Controller
|
||||
{
|
||||
public:
|
||||
static BAN::ErrorOr<void> initialize();
|
||||
static BAN::ErrorOr<void> 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<void> initialize_impl();
|
||||
BAN::ErrorOr<void> initialize_device(uint8_t);
|
||||
BAN::ErrorOr<void> initialize_impl(uint8_t scancode_set);
|
||||
BAN::ErrorOr<void> initialize_device(uint8_t, uint8_t scancode_set);
|
||||
|
||||
BAN::ErrorOr<uint8_t> read_byte();
|
||||
BAN::ErrorOr<void> send_byte(uint16_t port, uint8_t byte);
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Kernel::Input
|
|||
};
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> create(PS2Controller&);
|
||||
static BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> 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<uint8_t, 3> m_byte_buffer;
|
||||
uint8_t m_byte_index { 0 };
|
||||
bool m_basic { false };
|
||||
|
||||
uint8_t m_scancode_set { 0xFF };
|
||||
uint16_t m_modifiers { 0 };
|
||||
|
|
|
@ -221,14 +221,14 @@ namespace Kernel::Input
|
|||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> PS2Controller::initialize()
|
||||
BAN::ErrorOr<void> 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<void> PS2Controller::initialize_impl()
|
||||
BAN::ErrorOr<void> PS2Controller::initialize_impl(uint8_t scancode_set)
|
||||
{
|
||||
// Determine if the PS/2 Controller Exists
|
||||
auto* fadt = static_cast<const ACPI::FADT*>(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<void> PS2Controller::initialize_device(uint8_t device)
|
||||
BAN::ErrorOr<void> 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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,21 +9,41 @@
|
|||
namespace Kernel::Input
|
||||
{
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> PS2Keyboard::create(PS2Controller& controller)
|
||||
BAN::ErrorOr<BAN::RefPtr<PS2Keyboard>> PS2Keyboard::create(PS2Controller& controller, uint8_t scancode_set)
|
||||
{
|
||||
return TRY(BAN::RefPtr<PS2Keyboard>::create(controller));
|
||||
auto keyboard = TRY(BAN::RefPtr<PS2Keyboard>::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;
|
||||
|
|
|
@ -32,12 +32,15 @@
|
|||
|
||||
#include <LibInput/KeyboardLayout.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
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());
|
||||
|
|
Loading…
Reference in New Issue