diff --git a/Kernel/CommandLine.cpp b/Kernel/CommandLine.cpp index d08e1c68e0..b87879ce7e 100644 --- a/Kernel/CommandLine.cpp +++ b/Kernel/CommandLine.cpp @@ -61,6 +61,11 @@ CommandLine::CommandLine(const String& string) } } +Optional CommandLine::lookup(const String& key) const +{ + return m_params.get(key); +} + String CommandLine::get(const String& key) const { return m_params.get(key).value_or({}); diff --git a/Kernel/CommandLine.h b/Kernel/CommandLine.h index db312a59ed..a918b30e46 100644 --- a/Kernel/CommandLine.h +++ b/Kernel/CommandLine.h @@ -27,17 +27,20 @@ #pragma once #include +#include #include namespace Kernel { class CommandLine { AK_MAKE_ETERNAL; + public: static void initialize(const String&); const String& string() const { return m_string; } String get(const String& key) const; + Optional lookup(const String& key) const; bool contains(const String& key) const; private: diff --git a/Kernel/Devices/PS2MouseDevice.cpp b/Kernel/Devices/PS2MouseDevice.cpp index 6c8601769e..2eec50cc2b 100644 --- a/Kernel/Devices/PS2MouseDevice.cpp +++ b/Kernel/Devices/PS2MouseDevice.cpp @@ -51,14 +51,6 @@ namespace Kernel { #define PS2MOUSE_RESEND 0xFE #define PS2MOUSE_RESET 0xFF -#define PS2MOUSE_LEFT_CLICK 0x01 -#define PS2MOUSE_RIGHT_CLICK 0x02 -#define PS2MOUSE_MIDDLE_CLICK 0x04 - -#define VMMOUSE_LEFT_CLICK 0x20 -#define VMMOUSE_RIGHT_CLICK 0x10 -#define VMMOUSE_MIDDLE_CLICK 0x08 - #define PS2MOUSE_INTELLIMOUSE_ID 0x03 //#define PS2MOUSE_DEBUG @@ -82,68 +74,17 @@ PS2MouseDevice& PS2MouseDevice::the() return *s_the; } -void PS2MouseDevice::handle_vmmouse_absolute_pointer() -{ - VMWareCommand command; - command.bx = 0; - command.command = VMMOUSE_STATUS; - VMWareBackdoor::the().send(command); - if (command.ax == 0xFFFF0000) { -#ifdef PS2MOUSE_DEBUG - dbg() << "Reset vmmouse."; -#endif - VMWareBackdoor::the().disable_absolute_vmmouse(); - VMWareBackdoor::the().enable_absolute_vmmouse(); - return; - } - int words = command.ax & 0xFFFF; - - if (!words || words % 4) - return; - command.size = 4; - command.command = VMMOUSE_DATA; - VMWareBackdoor::the().send(command); - - int buttons = (command.ax & 0xFFFF); - int x = (command.bx); - int y = (command.cx); - int z = (command.dx); - -#ifdef PS2MOUSE_DEBUG - dbg() << "Absolute Mouse: Buttons " << String::format("%x", buttons); - dbg() << "Mouse: X " << x << ", Y " << y << ", Z " << z; -#endif - MousePacket packet; - packet.x = x; - packet.y = y; - packet.z = z; - if (buttons & VMMOUSE_LEFT_CLICK) { - packet.buttons |= PS2MOUSE_LEFT_CLICK; - } - if (buttons & VMMOUSE_RIGHT_CLICK) { - packet.buttons |= PS2MOUSE_RIGHT_CLICK; - } - if (buttons & VMMOUSE_MIDDLE_CLICK) { - packet.buttons |= PS2MOUSE_MIDDLE_CLICK; - } - packet.is_relative = false; - m_queue.enqueue(packet); -} - void PS2MouseDevice::handle_irq(const RegisterState&) { - - if (VMWareBackdoor::the().vmmouse_is_absolute()) { -#ifdef PS2MOUSE_DEBUG - dbg() << "Handling PS2 vmmouse."; -#endif - IO::in8(I8042_BUFFER); - handle_vmmouse_absolute_pointer(); - return; + if (auto* backdoor = VMWareBackdoor::the()) { + if (backdoor->vmmouse_is_absolute()) { + IO::in8(I8042_BUFFER); + auto packet = backdoor->receive_mouse_packet(); + if (packet.has_value()) + m_queue.enqueue(packet.value()); + return; + } } -#ifdef PS2MOUSE_DEBUG - dbg() << "Handling classical PS2 mouse."; -#endif for (;;) { u8 status = IO::in8(I8042_STATUS); if (!(((status & I8042_WHICH_BUFFER) == I8042_MOUSE_BUFFER) && (status & I8042_BUFFER_FULL))) diff --git a/Kernel/Devices/VMWareBackdoor.cpp b/Kernel/Devices/VMWareBackdoor.cpp index 38068e72cf..7f8237c74f 100644 --- a/Kernel/Devices/VMWareBackdoor.cpp +++ b/Kernel/Devices/VMWareBackdoor.cpp @@ -27,7 +27,9 @@ #include #include #include +#include #include +#include #include namespace Kernel { @@ -40,6 +42,9 @@ namespace Kernel { #define VMMOUSE_REQUEST_ABSOLUTE 0x53424152 #define VMMOUSE_QEMU_VERSION 0x3442554a +#define VMMOUSE_LEFT_CLICK 0x20 +#define VMMOUSE_RIGHT_CLICK 0x10 +#define VMMOUSE_MIDDLE_CLICK 0x08 #define VMWARE_MAGIC 0x564D5868 #define VMWARE_PORT 0x5658 @@ -77,34 +82,7 @@ inline void vmware_high_bandwidth_get(VMWareCommand& command) static VMWareBackdoor* s_vmware_backdoor; -static bool is_initialized() -{ - return s_vmware_backdoor != nullptr; -} - -void VMWareBackdoor::initialize() -{ - if (!is_initialized()) - s_vmware_backdoor = new VMWareBackdoor; -} - -VMWareBackdoor& VMWareBackdoor::the() -{ - ASSERT(s_vmware_backdoor != nullptr); - return *s_vmware_backdoor; -} - -VMWareBackdoor::VMWareBackdoor() -{ - if (!detect_presence()) { - klog() << "VMWare Backdoor: Not supported!"; - m_supported = false; - return; - } - klog() << "VMWare Backdoor: Supported."; - m_supported = true; -} -bool VMWareBackdoor::detect_presence() +static bool detect_presence() { VMWareCommand command; command.bx = ~VMWARE_MAGIC; @@ -115,15 +93,29 @@ bool VMWareBackdoor::detect_presence() return true; } -bool VMWareBackdoor::supported() +VMWareBackdoor* VMWareBackdoor::initialize() { - return m_supported; + if (!detect_presence()) + return nullptr; + + s_vmware_backdoor = new VMWareBackdoor; + klog() << "VMWare backdoor opened."; + return s_vmware_backdoor; +} + +VMWareBackdoor* VMWareBackdoor::the() +{ + return s_vmware_backdoor; +} + +VMWareBackdoor::VMWareBackdoor() +{ + if (kernel_command_line().lookup("vmmouse").value_or("on") == "on") + enable_absolute_vmmouse(); } bool VMWareBackdoor::detect_vmmouse() { - if (!supported()) - return false; VMWareCommand command; command.bx = VMMOUSE_READ_ID; command.command = VMMOUSE_COMMAND; @@ -135,7 +127,7 @@ bool VMWareBackdoor::detect_vmmouse() return false; return true; } -bool VMWareBackdoor::vmmouse_is_absolute() +bool VMWareBackdoor::vmmouse_is_absolute() const { return m_vmmouse_absolute; } @@ -143,9 +135,9 @@ bool VMWareBackdoor::vmmouse_is_absolute() void VMWareBackdoor::enable_absolute_vmmouse() { InterruptDisabler disabler; - if (!supported() || !detect_vmmouse()) + if (!detect_vmmouse()) return; - dbg() << "Enabling vmmouse, absolute mode"; + klog() << "VMWareBackdoor: Enabling absolute mouse mode"; VMWareCommand command; @@ -153,7 +145,7 @@ void VMWareBackdoor::enable_absolute_vmmouse() command.command = VMMOUSE_STATUS; send(command); if (command.ax == 0xFFFF0000) { - klog() << "VMMouse retuned bad status."; + klog() << "VMWareBackdoor: VMMOUSE_STATUS got bad status"; return; } @@ -166,8 +158,6 @@ void VMWareBackdoor::enable_absolute_vmmouse() void VMWareBackdoor::disable_absolute_vmmouse() { InterruptDisabler disabler; - if (!supported()) - return; VMWareCommand command; command.bx = VMMOUSE_REQUEST_RELATIVE; command.command = VMMOUSE_COMMAND; @@ -177,32 +167,72 @@ void VMWareBackdoor::disable_absolute_vmmouse() void VMWareBackdoor::send_high_bandwidth(VMWareCommand& command) { - if (supported()) { - vmware_high_bandwidth_send(command); + vmware_high_bandwidth_send(command); #ifdef VMWAREBACKDOOR_DEBUG - dbg() << "VMWareBackdoor Command High bandwidth Send Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx); + dbg() << "VMWareBackdoor Command High bandwidth Send Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx); #endif - } } void VMWareBackdoor::get_high_bandwidth(VMWareCommand& command) { - if (supported()) { - vmware_high_bandwidth_get(command); + vmware_high_bandwidth_get(command); #ifdef VMWAREBACKDOOR_DEBUG - dbg() << "VMWareBackdoor Command High bandwidth Get Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx); + dbg() << "VMWareBackdoor Command High bandwidth Get Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx); #endif - } } void VMWareBackdoor::send(VMWareCommand& command) { - if (supported()) { - vmware_out(command); + vmware_out(command); #ifdef VMWAREBACKDOOR_DEBUG - dbg() << "VMWareBackdoor Command Send Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx); + dbg() << "VMWareBackdoor Command Send Results: EAX " << String::format("%x", command.ax) << " EBX " << String::format("%x", command.bx) << " ECX " << String::format("%x", command.cx) << " EDX " << String::format("%x", command.dx); #endif +} + +Optional VMWareBackdoor::receive_mouse_packet() +{ + VMWareCommand command; + command.bx = 0; + command.command = VMMOUSE_STATUS; + send(command); + if (command.ax == 0xFFFF0000) { +#ifdef PS2MOUSE_DEBUG + klog() << "PS2MouseDevice: Resetting VMWare mouse"; +#endif + disable_absolute_vmmouse(); + enable_absolute_vmmouse(); + return {}; } + int words = command.ax & 0xFFFF; + + if (!words || words % 4) + return {}; + command.size = 4; + command.command = VMMOUSE_DATA; + send(command); + + int buttons = (command.ax & 0xFFFF); + int x = (command.bx); + int y = (command.cx); + int z = (command.dx); + +#ifdef PS2MOUSE_DEBUG + dbg() << "Absolute Mouse: Buttons " << String::format("%x", buttons); + dbg() << "Mouse: X " << x << ", Y " << y << ", Z " << z; +#endif + MousePacket packet; + packet.x = x; + packet.y = y; + packet.z = z; + if (buttons & VMMOUSE_LEFT_CLICK) + packet.buttons |= MousePacket::LeftButton; + if (buttons & VMMOUSE_RIGHT_CLICK) + packet.buttons |= MousePacket::RightButton; + if (buttons & VMMOUSE_MIDDLE_CLICK) + packet.buttons |= MousePacket::MiddleButton; + + packet.is_relative = false; + return packet; } } diff --git a/Kernel/Devices/VMWareBackdoor.h b/Kernel/Devices/VMWareBackdoor.h index 279ff4a8c8..7e9b878f27 100644 --- a/Kernel/Devices/VMWareBackdoor.h +++ b/Kernel/Devices/VMWareBackdoor.h @@ -26,8 +26,10 @@ #pragma once +#include #include #include +#include namespace Kernel { @@ -61,21 +63,21 @@ class VMWareBackdoor { AK_MAKE_ETERNAL; public: - static void initialize(); - static VMWareBackdoor& the(); - bool supported(); - bool vmmouse_is_absolute(); + static VMWareBackdoor* the(); + + static VMWareBackdoor* initialize(); + bool vmmouse_is_absolute() const; void enable_absolute_vmmouse(); void disable_absolute_vmmouse(); void send(VMWareCommand& command); + Optional receive_mouse_packet(); + private: void send_high_bandwidth(VMWareCommand& command); void get_high_bandwidth(VMWareCommand& command); VMWareBackdoor(); - bool detect_presence(); bool detect_vmmouse(); - bool m_supported; bool m_vmmouse_absolute { false }; }; diff --git a/Kernel/MousePacket.h b/Kernel/MousePacket.h index d5d6e8311a..bdec7914f7 100644 --- a/Kernel/MousePacket.h +++ b/Kernel/MousePacket.h @@ -32,6 +32,13 @@ struct MousePacket { int x { 0 }; int y { 0 }; int z { 0 }; + + enum Button { + LeftButton = 0x01, + RightButton = 0x02, + MiddleButton = 0x04, + }; + unsigned char buttons { 0 }; bool is_relative { true }; }; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 2c46189715..d66b52a114 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -66,10 +66,10 @@ #include #include #include -#include -#include #include #include +#include +#include #include #include @@ -86,7 +86,6 @@ namespace Kernel { [[noreturn]] static void init_stage2(); static void setup_serial_debug(); static void setup_acpi(); -static void setup_vmmouse(); static void setup_pci(); static void setup_interrupts(); static void setup_time_management(); @@ -130,7 +129,6 @@ extern "C" [[noreturn]] void init() new VFS; new KeyboardDevice; new PS2MouseDevice; - setup_vmmouse(); new Console; klog() << "Starting SerenityOS..."; @@ -198,6 +196,7 @@ void init_stage2() new RandomDevice; new PTYMultiplexer; new SB16; + VMWareBackdoor::initialize(); bool dmi_unreliable = kernel_command_line().contains("dmi_unreliable"); if (dmi_unreliable) { @@ -390,24 +389,6 @@ void setup_acpi() hang(); } -void setup_vmmouse() -{ - VMWareBackdoor::initialize(); - if (!kernel_command_line().contains("vmmouse")) { - VMWareBackdoor::the().enable_absolute_vmmouse(); - return; - } - auto vmmouse = kernel_command_line().get("vmmouse"); - if (vmmouse == "off") - return; - if (vmmouse == "on") { - VMWareBackdoor::the().enable_absolute_vmmouse(); - return; - } - klog() << "vmmouse boot argmuent has an invalid value."; - hang(); -} - void setup_pci() { if (!kernel_command_line().contains("pci_mmio")) {