diff --git a/ps2d/src/main.rs b/ps2d/src/main.rs index 7d4081a7ebb26f08e6d20409356b3627c6a6f610..085ad529afff2e47462cdc7a8e8d57b2f68fce1d 100644 --- a/ps2d/src/main.rs +++ b/ps2d/src/main.rs @@ -7,7 +7,7 @@ extern crate event; extern crate orbclient; extern crate syscall; -use std::{cmp, env, process}; +use std::{env, process}; use std::cell::RefCell; use std::fs::File; use std::io::{Read, Write, Result}; @@ -15,244 +15,15 @@ use std::os::unix::io::AsRawFd; use std::sync::Arc; use event::EventQueue; -use orbclient::{KeyEvent, MouseEvent, ButtonEvent, ScrollEvent}; use syscall::iopl; -use controller::Ps2; +use state::Ps2d; mod controller; mod keymap; +mod state; mod vm; -bitflags! { - flags MousePacketFlags: u8 { - const LEFT_BUTTON = 1, - const RIGHT_BUTTON = 1 << 1, - const MIDDLE_BUTTON = 1 << 2, - const ALWAYS_ON = 1 << 3, - const X_SIGN = 1 << 4, - const Y_SIGN = 1 << 5, - const X_OVERFLOW = 1 << 6, - const Y_OVERFLOW = 1 << 7 - } -} - -struct Ps2d char> { - ps2: Ps2, - vmmouse: bool, - input: File, - width: u32, - height: u32, - lshift: bool, - rshift: bool, - mouse_x: i32, - mouse_y: i32, - mouse_left: bool, - mouse_middle: bool, - mouse_right: bool, - packets: [u8; 4], - packet_i: usize, - extra_packet: bool, - //Keymap function - get_char: F -} - -impl char> Ps2d { - fn new(input: File, keymap: F) -> Self { - let mut ps2 = Ps2::new(); - let extra_packet = ps2.init(); - - let vmmouse = vm::enable(); - - let mut width = 0; - let mut height = 0; - { - let mut buf: [u8; 4096] = [0; 4096]; - if let Ok(count) = syscall::fpath(input.as_raw_fd() as usize, &mut buf) { - let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) }; - let res = path.split(":").nth(1).unwrap_or(""); - width = res.split("/").nth(1).unwrap_or("").parse::().unwrap_or(0); - height = res.split("/").nth(2).unwrap_or("").parse::().unwrap_or(0); - } - } - - Ps2d { - ps2: ps2, - vmmouse: vmmouse, - input: input, - width: width, - height: height, - lshift: false, - rshift: false, - mouse_x: 0, - mouse_y: 0, - mouse_left: false, - mouse_middle: false, - mouse_right: false, - packets: [0; 4], - packet_i: 0, - extra_packet: extra_packet, - get_char: keymap - } - } - - fn irq(&mut self) { - while let Some((keyboard, data)) = self.ps2.next() { - self.handle(keyboard, data); - } - } - - fn handle(&mut self, keyboard: bool, data: u8) { - if keyboard { - let (scancode, pressed) = if data >= 0x80 { - (data - 0x80, false) - } else { - (data, true) - }; - - if scancode == 0x2A { - self.lshift = pressed; - } else if scancode == 0x36 { - self.rshift = pressed; - } - - self.input.write(&KeyEvent { - character: (self.get_char)(scancode, self.lshift || self.rshift), - scancode: scancode, - pressed: pressed - }.to_event()).expect("ps2d: failed to write key event"); - } 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 queue_length = status & 0xffff; - if queue_length == 0 { - break; - } - - if queue_length % 4 != 0 { - println!("queue length not a multiple of 4: {}", queue_length); - break; - } - - let (status, dx, dy, dz, _, _) = unsafe { vm::cmd(vm::ABSPOINTER_DATA, 4) }; - - let (x, y) = if status & vm::RELATIVE_PACKET == vm::RELATIVE_PACKET { - ( - cmp::max(0, cmp::min(self.width as i32, self.mouse_x + dx as i32)), - cmp::max(0, cmp::min(self.height as i32, self.mouse_y - dy as i32)) - ) - } else { - ( - dx as i32 * self.width as i32 / 0xFFFF, - dy as i32 * self.height as i32 / 0xFFFF - ) - }; - - 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"); - } - - if dz != 0 { - self.input.write(&ScrollEvent { - x: 0, - y: -(dz as i32), - }.to_event()).expect("ps2d: failed to write scroll event"); - } - - let left = status & vm::LEFT_BUTTON == vm::LEFT_BUTTON; - let middle = status & vm::MIDDLE_BUTTON == vm::MIDDLE_BUTTON; - let right = status & vm::RIGHT_BUTTON == vm::RIGHT_BUTTON; - if left != self.mouse_left || middle != self.mouse_middle || right != self.mouse_right { - self.mouse_left = left; - self.mouse_middle = middle; - self.mouse_right = right; - self.input.write(&ButtonEvent { - left: left, - middle: middle, - right: right, - }.to_event()).expect("ps2d: failed to write button event"); - } - } - } else { - self.packets[self.packet_i] = data; - self.packet_i += 1; - - let flags = MousePacketFlags::from_bits_truncate(self.packets[0]); - if ! flags.contains(ALWAYS_ON) { - println!("MOUSE MISALIGN {:X}", self.packets[0]); - - self.packets = [0; 4]; - self.packet_i = 0; - } else if self.packet_i >= self.packets.len() || (!self.extra_packet && self.packet_i >= 3) { - if ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) { - let mut dx = self.packets[1] as i32; - if flags.contains(X_SIGN) { - dx -= 0x100; - } - - let mut dy = -(self.packets[2] as i32); - if flags.contains(Y_SIGN) { - dy += 0x100; - } - - let mut dz = 0; - if self.extra_packet { - let mut scroll = (self.packets[3] & 0xF) as i8; - if scroll & (1 << 3) == 1 << 3 { - scroll -= 16; - } - dz = -scroll as i32; - } - - let x = cmp::max(0, cmp::min(self.width as i32, self.mouse_x + dx)); - let y = cmp::max(0, cmp::min(self.height as i32, self.mouse_y + dy)); - 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"); - } - - if dz != 0 { - self.input.write(&ScrollEvent { - x: 0, - y: dz, - }.to_event()).expect("ps2d: failed to write scroll event"); - } - - let left = flags.contains(LEFT_BUTTON); - let middle = flags.contains(MIDDLE_BUTTON); - let right = flags.contains(RIGHT_BUTTON); - if left != self.mouse_left || middle != self.mouse_middle || right != self.mouse_right { - self.mouse_left = left; - self.mouse_middle = middle; - self.mouse_right = right; - self.input.write(&ButtonEvent { - left: left, - middle: middle, - right: right, - }.to_event()).expect("ps2d: failed to write button event"); - } - } else { - println!("ps2d: overflow {:X} {:X} {:X} {:X}", self.packets[0], self.packets[1], self.packets[2], self.packets[3]); - } - - self.packets = [0; 4]; - self.packet_i = 0; - } - } - } -} - fn daemon(input: File) { unsafe { iopl(3).expect("ps2d: failed to get I/O permission"); diff --git a/ps2d/src/state.rs b/ps2d/src/state.rs new file mode 100644 index 0000000000000000000000000000000000000000..11472767a0f6e10e1d84425403ea41161373fce0 --- /dev/null +++ b/ps2d/src/state.rs @@ -0,0 +1,243 @@ +use orbclient::{KeyEvent, MouseEvent, ButtonEvent, ScrollEvent}; +use std::cmp; +use std::fs::File; +use std::io::Write; +use std::os::unix::io::AsRawFd; +use syscall; + +use controller::Ps2; +use vm; + +bitflags! { + flags MousePacketFlags: u8 { + const LEFT_BUTTON = 1, + const RIGHT_BUTTON = 1 << 1, + const MIDDLE_BUTTON = 1 << 2, + const ALWAYS_ON = 1 << 3, + const X_SIGN = 1 << 4, + const Y_SIGN = 1 << 5, + const X_OVERFLOW = 1 << 6, + const Y_OVERFLOW = 1 << 7 + } +} + +pub struct Ps2d char> { + ps2: Ps2, + vmmouse: bool, + input: File, + width: u32, + height: u32, + lshift: bool, + rshift: bool, + mouse_x: i32, + mouse_y: i32, + mouse_left: bool, + mouse_middle: bool, + mouse_right: bool, + packets: [u8; 4], + packet_i: usize, + extra_packet: bool, + //Keymap function + get_char: F +} + +impl char> Ps2d { + pub fn new(input: File, keymap: F) -> Self { + let mut ps2 = Ps2::new(); + let extra_packet = ps2.init(); + + let vmmouse = vm::enable(); + + let mut ps2d = Ps2d { + ps2: ps2, + vmmouse: vmmouse, + input: input, + width: 0, + height: 0, + lshift: false, + rshift: false, + mouse_x: 0, + mouse_y: 0, + mouse_left: false, + mouse_middle: false, + mouse_right: false, + packets: [0; 4], + packet_i: 0, + extra_packet: 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 { String::from_utf8_unchecked(Vec::from(&buf[..count])) }; + let res = path.split(":").nth(1).unwrap_or(""); + self.width = res.split("/").nth(1).unwrap_or("").parse::().unwrap_or(0); + self.height = res.split("/").nth(2).unwrap_or("").parse::().unwrap_or(0); + } + } + + pub fn irq(&mut self) { + while let Some((keyboard, data)) = self.ps2.next() { + self.handle(keyboard, data); + } + } + + pub fn handle(&mut self, keyboard: bool, data: u8) { + // TODO: Improve efficiency + self.resize(); + + if keyboard { + let (scancode, pressed) = if data >= 0x80 { + (data - 0x80, false) + } else { + (data, true) + }; + + if scancode == 0x2A { + self.lshift = pressed; + } else if scancode == 0x36 { + self.rshift = pressed; + } + + self.input.write(&KeyEvent { + character: (self.get_char)(scancode, self.lshift || self.rshift), + scancode: scancode, + pressed: pressed + }.to_event()).expect("ps2d: failed to write key event"); + } 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 queue_length = status & 0xffff; + if queue_length == 0 { + break; + } + + if queue_length % 4 != 0 { + println!("queue length not a multiple of 4: {}", queue_length); + break; + } + + let (status, dx, dy, dz, _, _) = unsafe { vm::cmd(vm::ABSPOINTER_DATA, 4) }; + + let (x, y) = if status & vm::RELATIVE_PACKET == vm::RELATIVE_PACKET { + ( + cmp::max(0, cmp::min(self.width as i32, self.mouse_x + dx as i32)), + cmp::max(0, cmp::min(self.height as i32, self.mouse_y - dy as i32)) + ) + } else { + ( + dx as i32 * self.width as i32 / 0xFFFF, + dy as i32 * self.height as i32 / 0xFFFF + ) + }; + + 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"); + } + + if dz != 0 { + self.input.write(&ScrollEvent { + x: 0, + y: -(dz as i32), + }.to_event()).expect("ps2d: failed to write scroll event"); + } + + let left = status & vm::LEFT_BUTTON == vm::LEFT_BUTTON; + let middle = status & vm::MIDDLE_BUTTON == vm::MIDDLE_BUTTON; + let right = status & vm::RIGHT_BUTTON == vm::RIGHT_BUTTON; + if left != self.mouse_left || middle != self.mouse_middle || right != self.mouse_right { + self.mouse_left = left; + self.mouse_middle = middle; + self.mouse_right = right; + self.input.write(&ButtonEvent { + left: left, + middle: middle, + right: right, + }.to_event()).expect("ps2d: failed to write button event"); + } + } + } else { + self.packets[self.packet_i] = data; + self.packet_i += 1; + + let flags = MousePacketFlags::from_bits_truncate(self.packets[0]); + if ! flags.contains(ALWAYS_ON) { + println!("MOUSE MISALIGN {:X}", self.packets[0]); + + self.packets = [0; 4]; + self.packet_i = 0; + } else if self.packet_i >= self.packets.len() || (!self.extra_packet && self.packet_i >= 3) { + if ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) { + let mut dx = self.packets[1] as i32; + if flags.contains(X_SIGN) { + dx -= 0x100; + } + + let mut dy = -(self.packets[2] as i32); + if flags.contains(Y_SIGN) { + dy += 0x100; + } + + let mut dz = 0; + if self.extra_packet { + let mut scroll = (self.packets[3] & 0xF) as i8; + if scroll & (1 << 3) == 1 << 3 { + scroll -= 16; + } + dz = -scroll as i32; + } + + let x = cmp::max(0, cmp::min(self.width as i32, self.mouse_x + dx)); + let y = cmp::max(0, cmp::min(self.height as i32, self.mouse_y + dy)); + 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"); + } + + if dz != 0 { + self.input.write(&ScrollEvent { + x: 0, + y: dz, + }.to_event()).expect("ps2d: failed to write scroll event"); + } + + let left = flags.contains(LEFT_BUTTON); + let middle = flags.contains(MIDDLE_BUTTON); + let right = flags.contains(RIGHT_BUTTON); + if left != self.mouse_left || middle != self.mouse_middle || right != self.mouse_right { + self.mouse_left = left; + self.mouse_middle = middle; + self.mouse_right = right; + self.input.write(&ButtonEvent { + left: left, + middle: middle, + right: right, + }.to_event()).expect("ps2d: failed to write button event"); + } + } else { + println!("ps2d: overflow {:X} {:X} {:X} {:X}", self.packets[0], self.packets[1], self.packets[2], self.packets[3]); + } + + self.packets = [0; 4]; + self.packet_i = 0; + } + } + } +} diff --git a/vesad/src/scheme.rs b/vesad/src/scheme.rs index 3e538c27ca260e9e062fabb752a416bf014a386c..88382ea3af8505c2fa3972a0397a2753c08ebe92 100644 --- a/vesad/src/scheme.rs +++ b/vesad/src/scheme.rs @@ -236,6 +236,8 @@ impl SchemeMut for DisplayScheme { }, EventOption::Resize(resize_event) => { println!("Resizing to {}, {}", resize_event.width, resize_event.height); + self.width = resize_event.width as usize; + self.height = resize_event.height as usize; for (screen_i, screen) in self.screens.iter_mut() { screen.resize(resize_event.width as usize, resize_event.height as usize); if *screen_i == self.active {