summaryrefslogtreecommitdiff
path: root/Kernel/Devices
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Devices')
-rw-r--r--Kernel/Devices/PS2MouseDevice.cpp84
-rw-r--r--Kernel/Devices/PS2MouseDevice.h1
-rw-r--r--Kernel/Devices/VMWareBackdoor.cpp149
-rw-r--r--Kernel/Devices/VMWareBackdoor.h77
4 files changed, 308 insertions, 3 deletions
diff --git a/Kernel/Devices/PS2MouseDevice.cpp b/Kernel/Devices/PS2MouseDevice.cpp
index 17eccbdc93..7bd0fd5566 100644
--- a/Kernel/Devices/PS2MouseDevice.cpp
+++ b/Kernel/Devices/PS2MouseDevice.cpp
@@ -24,8 +24,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "PS2MouseDevice.h"
-#include "IO.h"
+#include <Kernel/Devices/PS2MouseDevice.h>
+#include <Kernel/Devices/VMWareBackdoor.h>
+#include <Kernel/IO.h>
#define IRQ_MOUSE 12
#define I8042_BUFFER 0x60
@@ -47,6 +48,14 @@
#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
@@ -70,8 +79,68 @@ 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
+ dbgprintf("Reset vmmouse.\n");
+#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
+ dbgprintf("Absolute Mouse: Buttons %x\n", buttons);
+ dbgprintf("Mouse: X %d, Y %d, Z %d\n", x, y, 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()
{
+
+ if (VMWareBackdoor::the().vmmouse_is_absolute()) {
+#ifdef PS2MOUSE_DEBUG
+ dbgprintf("Handling PS2 vmmouse.\n");
+#endif
+ IO::in8(I8042_BUFFER);
+ handle_vmmouse_absolute_pointer();
+ return;
+ }
+#ifdef PS2MOUSE_DEBUG
+ dbgprintf("Handling classical PS2 mouse.\n");
+#endif
for (;;) {
u8 status = IO::in8(I8042_STATUS);
if (!(((status & I8042_WHICH_BUFFER) == I8042_MOUSE_BUFFER) && (status & I8042_BUFFER_FULL)))
@@ -143,7 +212,11 @@ void PS2MouseDevice::parse_data_packet()
packet.y = y;
packet.z = z;
packet.buttons = m_data[0] & 0x07;
-
+ packet.is_relative = true;
+#ifdef PS2MOUSE_DEBUG
+ dbgprintf("PS2 Relative Mouse: Buttons %x\n", packet.buttons);
+ dbgprintf("Mouse: X %d, Y %d, Z %d\n", packet.x, packet.y, packet.z);
+#endif
m_queue.enqueue(packet);
}
@@ -296,6 +369,11 @@ ssize_t PS2MouseDevice::read(FileDescription&, u8* buffer, ssize_t size)
if ((size - nread) < (ssize_t)sizeof(MousePacket))
break;
auto packet = m_queue.dequeue();
+#ifdef PS2MOUSE_DEBUG
+ dbgprintf("PS2 Mouse Read: Buttons %x\n", packet.buttons);
+ dbgprintf("PS2 Mouse Read: X %d, Y %d, Z %d, Relative %d\n", packet.x, packet.y, packet.z, packet.buttons);
+ dbgprintf("PS2 Mouse Read: Filter packets\n");
+#endif
memcpy(buffer, &packet, sizeof(MousePacket));
nread += sizeof(MousePacket);
}
diff --git a/Kernel/Devices/PS2MouseDevice.h b/Kernel/Devices/PS2MouseDevice.h
index 6010bb6cef..6351c0adca 100644
--- a/Kernel/Devices/PS2MouseDevice.h
+++ b/Kernel/Devices/PS2MouseDevice.h
@@ -48,6 +48,7 @@ public:
private:
// ^IRQHandler
virtual void handle_irq() override;
+ void handle_vmmouse_absolute_pointer();
// ^CharacterDevice
virtual const char* class_name() const override { return "PS2MouseDevice"; }
diff --git a/Kernel/Devices/VMWareBackdoor.cpp b/Kernel/Devices/VMWareBackdoor.cpp
new file mode 100644
index 0000000000..91b3f3775f
--- /dev/null
+++ b/Kernel/Devices/VMWareBackdoor.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/Assertions.h>
+#include <Kernel/Arch/i386/CPU.h>
+#include <Kernel/Devices/VMWareBackdoor.h>
+#include <Kernel/IO.h>
+
+#define VMWARE_CMD_GETVERSION 0x0a
+
+#define VMMOUSE_READ_ID 0x45414552
+#define VMMOUSE_DISABLE 0x000000f5
+#define VMMOUSE_REQUEST_RELATIVE 0x4c455252
+#define VMMOUSE_REQUEST_ABSOLUTE 0x53424152
+
+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()) {
+ kprintf("VMWare Backdoor: Not supported!\n");
+ m_supported = false;
+ return;
+ }
+ kprintf("VMWare Backdoor: Supported.\n");
+ m_supported = true;
+}
+bool VMWareBackdoor::detect_presence()
+{
+ VMWareCommand command;
+ command.bx = ~VMWARE_MAGIC;
+ command.command = VMWARE_CMD_GETVERSION;
+ IO::vmware_out(command);
+ if (command.bx != VMWARE_MAGIC || command.ax == 0xFFFFFFFF)
+ return false;
+ return true;
+}
+
+bool VMWareBackdoor::supported()
+{
+ return m_supported;
+}
+
+bool VMWareBackdoor::detect_vmmouse()
+{
+ if (!supported())
+ return false;
+ VMWareCommand command;
+ command.bx = 0;
+ command.command = VMMOUSE_GETVERSION;
+ send(command);
+ // Apparently after a VMMOUSE_GETVERSION command, we should see that EBX register = VMWARE_MAGIC
+ if (command.bx != VMWARE_MAGIC || command.ax == 0xFFFFFFFF)
+ return false;
+ return true;
+}
+bool VMWareBackdoor::vmmouse_is_absolute()
+{
+ return m_vmmouse_absolute;
+}
+
+void VMWareBackdoor::enable_absolute_vmmouse()
+{
+ InterruptDisabler disabler;
+ if (!supported() || !detect_vmmouse())
+ return;
+ dbgprintf("Enabling vmmouse, absolute mode\n");
+
+ VMWareCommand command;
+
+ // Enable vmmouse
+ command.bx = VMMOUSE_READ_ID;
+ command.command = VMMOUSE_COMMAND;
+ send(command);
+
+ // Status
+ command.bx = 0;
+ command.command = VMMOUSE_STATUS;
+
+ send(command);
+
+ // Read Data
+ command.bx = 1;
+ command.command = VMMOUSE_DATA;
+ send(command);
+
+ // Enable absolute vmmouse
+ command.bx = VMMOUSE_REQUEST_ABSOLUTE;
+ command.command = VMMOUSE_COMMAND;
+ send(command);
+ m_vmmouse_absolute = true;
+}
+void VMWareBackdoor::disable_absolute_vmmouse()
+{
+ InterruptDisabler disabler;
+ if (!supported())
+ return;
+ VMWareCommand command;
+ command.bx = VMMOUSE_REQUEST_RELATIVE;
+ command.command = VMMOUSE_COMMAND;
+ send(command);
+ m_vmmouse_absolute = false;
+}
+
+void VMWareBackdoor::send(VMWareCommand& command)
+{
+ if (supported())
+ IO::vmware_out(command);
+}
diff --git a/Kernel/Devices/VMWareBackdoor.h b/Kernel/Devices/VMWareBackdoor.h
new file mode 100644
index 0000000000..c7803987a6
--- /dev/null
+++ b/Kernel/Devices/VMWareBackdoor.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+
+#define VMWARE_MAGIC 0x564D5868
+#define VMWARE_PORT 0x5658
+#define VMWARE_PORT_HIGHBANDWIDTH 0x5659
+
+#define VMMOUSE_GETVERSION 10
+#define VMMOUSE_DATA 39
+#define VMMOUSE_STATUS 40
+#define VMMOUSE_COMMAND 41
+
+struct VMWareCommand {
+ union {
+ u32 ax;
+ u32 magic;
+ };
+ union {
+ u32 bx;
+ u32 size;
+ };
+ union {
+ u32 cx;
+ u32 command;
+ };
+ union {
+ u32 dx;
+ u32 port;
+ };
+ u32 si;
+ u32 di;
+};
+
+class VMWareBackdoor {
+public:
+ static void initialize();
+ static VMWareBackdoor& the();
+ bool supported();
+ bool vmmouse_is_absolute();
+ void enable_absolute_vmmouse();
+ void disable_absolute_vmmouse();
+ void send(VMWareCommand& command);
+
+private:
+ VMWareBackdoor();
+ bool detect_presence();
+ bool detect_vmmouse();
+ bool m_supported;
+ bool m_vmmouse_absolute { false };
+};