diff --git a/Cargo.lock b/Cargo.lock index d36db5740f..9398d25a36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -892,7 +892,6 @@ version = "0.1.0" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (git+https://gitlab.redox-os.org/redox-os/event.git)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ps2d/Cargo.toml b/ps2d/Cargo.toml index 34ef208a98..f1da6df454 100644 --- a/ps2d/Cargo.toml +++ b/ps2d/Cargo.toml @@ -6,5 +6,4 @@ edition = "2018" [dependencies] bitflags = "0.7" orbclient = "0.3.27" -redox_event = { git = "https://gitlab.redox-os.org/redox-os/event.git" } redox_syscall = "0.1" diff --git a/ps2d/src/main.rs b/ps2d/src/main.rs index 3e896a9253..8d00348830 100644 --- a/ps2d/src/main.rs +++ b/ps2d/src/main.rs @@ -2,18 +2,15 @@ #[macro_use] extern crate bitflags; -extern crate event; extern crate orbclient; extern crate syscall; use std::{env, process}; -use std::cell::RefCell; -use std::fs::File; -use std::io::{Read, Write, Result}; +use std::fs::{File, OpenOptions}; +use std::io::{Read, Write}; +use std::os::unix::fs::OpenOptionsExt; use std::os::unix::io::AsRawFd; -use std::sync::Arc; -use event::EventQueue; use syscall::iopl; use crate::state::Ps2d; @@ -41,46 +38,79 @@ fn daemon(input: File) { None => (keymap::us::get_char) }; - let mut key_irq = File::open("irq:1").expect("ps2d: failed to open irq:1"); + let mut event_file = OpenOptions::new() + .read(true) + .write(true) + .open("event:") + .expect("ps2d: failed to open event:"); - let mut mouse_irq = File::open("irq:12").expect("ps2d: failed to open irq:12"); + let mut key_file = OpenOptions::new() + .read(true) + .write(true) + .custom_flags(syscall::O_NONBLOCK as i32) + .open("serio:0") + .expect("ps2d: failed to open serio:0"); - let ps2d = Arc::new(RefCell::new(Ps2d::new(input, keymap))); + event_file.write(&syscall::Event { + id: key_file.as_raw_fd() as usize, + flags: syscall::EVENT_READ, + data: 0 + }).expect("ps2d: failed to event serio:0"); - let mut event_queue = EventQueue::<()>::new().expect("ps2d: failed to create event queue"); + let mut mouse_file = OpenOptions::new() + .read(true) + .write(true) + .custom_flags(syscall::O_NONBLOCK as i32) + .open("serio:1") + .expect("ps2d: failed to open serio:1"); + + event_file.write(&syscall::Event { + id: mouse_file.as_raw_fd() as usize, + flags: syscall::EVENT_READ, + data: 1 + }).expect("ps2d: failed to event irq:12"); + + let mut ps2d = Ps2d::new(input, keymap); syscall::setrens(0, 0).expect("ps2d: failed to enter null namespace"); - let key_ps2d = ps2d.clone(); - event_queue.add(key_irq.as_raw_fd(), move |_event| -> Result> { - let mut irq = [0; 8]; - if key_irq.read(&mut irq)? >= irq.len() { - key_ps2d.borrow_mut().irq(); - key_irq.write(&irq)?; + let mut data = [0; 256]; + loop { + // There are some gotchas with ps/2 controllers that require this weird + // way of doing things. You read key and mouse data from the same + // place. There is a status register that may show you which the data + // came from, but if it is even implemented it can have a race + // condition causing keyboard data to be read as mouse data. + // + // Due to this, we have a kernel driver doing a small amount of work + // to grab bytes and sort them based on the source + + let mut event = syscall::Event::default(); + if event_file.read(&mut event).expect("ps2d: failed to read event file") == 0 { + break; } - Ok(None) - }).expect("ps2d: failed to poll irq:1"); - let mouse_ps2d = ps2d; - event_queue.add(mouse_irq.as_raw_fd(), move |_event| -> Result> { - let mut irq = [0; 8]; - if mouse_irq.read(&mut irq)? >= irq.len() { - mouse_ps2d.borrow_mut().irq(); - mouse_irq.write(&irq)?; + let (file, keyboard) = match event.data { + 0 => (&mut key_file, true), + 1 => (&mut mouse_file, false), + _ => continue, + }; + + loop { + let count = match file.read(&mut data) { + Ok(0) => break, + Ok(count) => count, + Err(_) => break, + }; + for i in 0..count { + ps2d.handle(keyboard, data[i]); + } } - Ok(None) - }).expect("ps2d: failed to poll irq:12"); - - event_queue.trigger_all(event::Event { - fd: 0, - flags: 0, - }).expect("ps2d: failed to trigger events"); - - event_queue.run().expect("ps2d: failed to handle events"); + } } fn main() { - match File::open("display:input") { + match OpenOptions::new().write(true).open("display:input") { Ok(input) => { // Daemonize if unsafe { syscall::clone(0).unwrap() } == 0 { diff --git a/ps2d/src/state.rs b/ps2d/src/state.rs index 13c71c0876..ec6e5d2c15 100644 --- a/ps2d/src/state.rs +++ b/ps2d/src/state.rs @@ -24,6 +24,7 @@ bitflags! { pub struct Ps2d char> { ps2: Ps2, vmmouse: bool, + vmmouse_relative: bool, input: File, width: u32, height: u32, @@ -46,12 +47,14 @@ impl char> Ps2d { let mut ps2 = Ps2::new(); let extra_packet = ps2.init(); - let vmmouse = false; //vm::enable(); + let vmmouse_relative = true; + let vmmouse = false; //vm::enable(vmmouse_relative); let mut ps2d = Ps2d { - ps2: ps2, - vmmouse: vmmouse, - input: input, + ps2, + vmmouse, + vmmouse_relative, + input, width: 0, height: 0, lshift: false, @@ -63,7 +66,7 @@ impl char> Ps2d { mouse_right: false, packets: [0; 4], packet_i: 0, - extra_packet: extra_packet, + extra_packet, get_char: keymap }; @@ -118,17 +121,17 @@ impl char> Ps2d { } if queue_length % 4 != 0 { - println!("queue length not a multiple of 4: {}", queue_length); + println!("ps2d: queue length not a multiple of 4: {}", queue_length); break; } let (status, dx, dy, dz, _, _) = unsafe { vm::cmd(vm::ABSPOINTER_DATA, 4) }; - if status & vm::RELATIVE_PACKET == vm::RELATIVE_PACKET { + if self.vmmouse_relative { if dx != 0 || dy != 0 { self.input.write(&MouseRelativeEvent { dx: dx as i32, - dy: -(dy as i32), + dy: dy as i32, }.to_event()).expect("ps2d: failed to write mouse event"); } } else { @@ -174,7 +177,7 @@ impl char> Ps2d { let flags = MousePacketFlags::from_bits_truncate(self.packets[0]); if ! flags.contains(ALWAYS_ON) { - println!("MOUSE MISALIGN {:X}", self.packets[0]); + println!("ps2d: mouse misalign {:X}", self.packets[0]); self.packets = [0; 4]; self.packet_i = 0; diff --git a/ps2d/src/vm.rs b/ps2d/src/vm.rs index a772829aaf..36dc9dce60 100644 --- a/ps2d/src/vm.rs +++ b/ps2d/src/vm.rs @@ -14,6 +14,7 @@ pub const ABSPOINTER_COMMAND: u32 = 41; pub const CMD_ENABLE: u32 = 0x45414552; pub const CMD_DISABLE: u32 = 0x000000f5; pub const CMD_REQUEST_ABSOLUTE: u32 = 0x53424152; +pub const CMD_REQUEST_RELATIVE: u32 = 0x4c455252; const VERSION: u32 = 0x3442554a; @@ -55,27 +56,30 @@ pub unsafe fn cmd(cmd: u32, arg: u32) -> (u32, u32, u32, u32, u32, u32) { (a, b, c, d, si, di) } -pub fn enable() -> bool { - println!("Enable"); +pub fn enable(relative: bool) -> bool { + println!("ps2d: Enable vmmouse"); unsafe { let _ = cmd(ABSPOINTER_COMMAND, CMD_ENABLE); let (status, _, _, _, _, _) = cmd(ABSPOINTER_STATUS, 0); if (status & 0x0000ffff) == 0 { - println!("No vmmouse"); + println!("ps2d: No vmmouse"); return false; } let (version, _, _, _, _, _) = cmd(ABSPOINTER_DATA, 1); if version != VERSION { - println!("Invalid vmmouse version: {} instead of {}", version, VERSION); + println!("ps2d: Invalid vmmouse version: {} instead of {}", version, VERSION); let _ = cmd(ABSPOINTER_COMMAND, CMD_DISABLE); return false; } - cmd(ABSPOINTER_COMMAND, CMD_REQUEST_ABSOLUTE); - + if relative { + cmd(ABSPOINTER_COMMAND, CMD_REQUEST_RELATIVE); + } else { + cmd(ABSPOINTER_COMMAND, CMD_REQUEST_ABSOLUTE); + } } return true;