Merge branch 'fix_absolute_mouse_events' into 'master'

Switch to absolute mouse events by default when running in a VM

See merge request redox-os/drivers!126
This commit is contained in:
Jeremy Soller
2024-01-12 17:58:50 +00:00
2 changed files with 40 additions and 80 deletions
+20 -41
View File
@@ -26,8 +26,6 @@ pub struct Ps2d<F: Fn(u8,bool) -> char> {
vmmouse: bool,
vmmouse_relative: bool,
input: File,
width: u32,
height: u32,
extended: bool,
lshift: bool,
rshift: bool,
@@ -48,16 +46,15 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
let mut ps2 = Ps2::new();
let extra_packet = ps2.init().expect("ps2d: failed to initialize");
let vmmouse_relative = true;
// FIXME add an option for orbital to disable this when an app captures the mouse.
let vmmouse_relative = false;
let vmmouse = vm::enable(vmmouse_relative);
let mut ps2d = Ps2d {
Ps2d {
ps2,
vmmouse,
vmmouse_relative,
input,
width: 0,
height: 0,
extended: false,
lshift: false,
rshift: false,
@@ -70,20 +67,6 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
packet_i: 0,
extra_packet,
get_char: keymap
};
ps2d.resize();
ps2d
}
pub fn resize(&mut self) {
let mut buf: [u8; 4096] = [0; 4096];
if let Ok(count) = syscall::fpath(self.input.as_raw_fd() as usize, &mut buf) {
let path = unsafe { str::from_utf8_unchecked(&buf[..count]) };
let res = path.split(":").nth(1).unwrap_or("");
self.width = res.split("/").nth(1).unwrap_or("").parse::<u32>().unwrap_or(0);
self.height = res.split("/").nth(2).unwrap_or("").parse::<u32>().unwrap_or(0);
}
}
@@ -253,20 +236,20 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
}
} else if self.vmmouse {
for _i in 0..256 {
let (status, _, _, _, _, _) = unsafe { vm::cmd(vm::ABSPOINTER_STATUS, 0) };
//TODO if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR)
let (status, _, _, _, _, _) = unsafe { vm::cmd(vm::ABSPOINTER_STATUS, 0) };
//TODO if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR)
let queue_length = status & 0xffff;
if queue_length == 0 {
break;
let queue_length = status & 0xffff;
if queue_length == 0 {
break;
}
if queue_length % 4 != 0 {
eprintln!("ps2d: queue length not a multiple of 4: {}", queue_length);
break;
}
if queue_length % 4 != 0 {
eprintln!("ps2d: queue length not a multiple of 4: {}", queue_length);
break;
}
let (status, dx, dy, dz, _, _) = unsafe { vm::cmd(vm::ABSPOINTER_DATA, 4) };
let (status, dx, dy, dz, _, _) = unsafe { vm::cmd(vm::ABSPOINTER_DATA, 4) };
if self.vmmouse_relative {
if dx != 0 || dy != 0 {
@@ -275,21 +258,17 @@ impl<F: Fn(u8,bool) -> char> Ps2d<F> {
dy: dy as i32,
}.to_event()).expect("ps2d: failed to write mouse event");
}
} else {
// TODO: Improve efficiency
self.resize();
let x = dx as i32 * self.width as i32 / 0xFFFF;
let y = dy as i32 * self.height as i32 / 0xFFFF;
} else {
let x = dx as i32;
let y = dy as i32;
if x != self.mouse_x || y != self.mouse_y {
self.mouse_x = x;
self.mouse_y = y;
self.input.write(&MouseEvent {
x: x,
y: y,
}.to_event()).expect("ps2d: failed to write mouse event");
self.input
.write(&MouseEvent { x, y }.to_event())
.expect("ps2d: failed to write mouse event");
}
};
};
if dz != 0 {
self.input.write(&ScrollEvent {
+20 -39
View File
@@ -4,7 +4,7 @@
// As well as the Linux implementation here:
// http://elixir.free-electrons.com/linux/v4.1/source/drivers/input/mouse/vmmouse.c
use core::arch::global_asm;
use core::arch::asm;
const MAGIC: u32 = 0x564D5868;
const PORT: u16 = 0x5658;
@@ -27,49 +27,30 @@ pub const LEFT_BUTTON: u32 = 0x20;
pub const RIGHT_BUTTON: u32 = 0x10;
pub const MIDDLE_BUTTON: u32 = 0x08;
#[cfg(target_arch = "x86_64")]
global_asm!("
.globl cmd_inner
cmd_inner:
mov r8, rdi
// 2nd argument `cmd` as per sysv64.
mov ecx, esi
// 3rd argument `arg` as per sysv64.
mov ebx, edx
mov eax, {MAGIC}
mov dx, {PORT}
in eax, dx
xchg rdi, r8
mov DWORD PTR [rdi + 0x00], eax
mov DWORD PTR [rdi + 0x04], ebx
mov DWORD PTR [rdi + 0x08], ecx
mov DWORD PTR [rdi + 0x0C], edx
mov DWORD PTR [rdi + 0x10], esi
mov DWORD PTR [rdi + 0x14], r8d
ret
",
MAGIC = const MAGIC,
PORT = const PORT,
);
#[cfg(target_arch = "x86_64")]
pub unsafe fn cmd(cmd: u32, arg: u32) -> (u32, u32, u32, u32, u32, u32) {
extern "sysv64" {
fn cmd_inner(array_ptr: *mut u32, cmd: u32, arg: u32);
}
let a: u32;
let b: u32;
let c: u32;
let d: u32;
let si: u32;
let di: u32;
let mut array = [0_u32; 6];
// ebx can't be used as input or output constraint in rust as LLVM reserves it.
// Use xchg to pass it through r9 instead while restoring the original value in
// rbx when leaving the inline asm block.
asm!(
"xchg r9, rbx; in eax, dx; xchg r9, rbx",
inout("eax") MAGIC => a,
inout("r9") arg => b,
inout("ecx") cmd => c,
inout("edx") PORT as u32 => d,
out("esi") si,
out("edi") di,
);
cmd_inner(array.as_mut_ptr(), cmd, arg);
(a, b, c, d, si, di)
let [a, b, c, d, e, f] = array;
(a, b, c, d, e, f)
}
//TODO: is it possible to enable this on non-x86_64?