1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:57:43 +00:00

Kernel: Add support for vmmouse

We add this feature together with the VMWareBackdoor class.
VMWareBackdoor class is responsible for enabling the vmmouse, and then
controlling it from the PS2 mouse IRQ handler.
This commit is contained in:
Liav A 2020-02-04 03:00:50 +02:00 committed by Andreas Kling
parent 44ddfd2bf5
commit 47978a5828
8 changed files with 328 additions and 3 deletions

View file

@ -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);
}