From 255e5fcb68b4ea27358f37616cfea3b98e1a0351 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 19 Apr 2020 14:27:44 -0600 Subject: [PATCH 1/5] WIP: ps2d interrupt fixes --- Cargo.lock | 1 - ps2d/Cargo.toml | 1 - ps2d/src/controller.rs | 6 +-- ps2d/src/main.rs | 110 ++++++++++++++++++++++++++++------------- ps2d/src/state.rs | 13 ++--- 5 files changed, 87 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d93fb99f01..396b7553ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -890,7 +890,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/controller.rs b/ps2d/src/controller.rs index 1d758446be..378ecb5764 100644 --- a/ps2d/src/controller.rs +++ b/ps2d/src/controller.rs @@ -76,9 +76,9 @@ enum MouseCommandData { } pub struct Ps2 { - data: Pio, - status: ReadOnly>, - command: WriteOnly> + pub data: Pio, + pub status: ReadOnly>, + pub command: WriteOnly> } impl Ps2 { diff --git a/ps2d/src/main.rs b/ps2d/src/main.rs index 3e896a9253..56dce69f8f 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,93 @@ 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) + .custom_flags(syscall::O_NONBLOCK as i32) + .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_irq = OpenOptions::new() + .read(true) + .write(true) + .custom_flags(syscall::O_NONBLOCK as i32) + .open("irq:1") + .expect("ps2d: failed to open irq:1"); - let ps2d = Arc::new(RefCell::new(Ps2d::new(input, keymap))); + let mut key_irq_data = [0; 8]; + key_irq.read(&mut key_irq_data).expect("ps2d: failed to read irq:1"); - let mut event_queue = EventQueue::<()>::new().expect("ps2d: failed to create event queue"); + event_file.write(&syscall::Event { + id: key_irq.as_raw_fd() as usize, + flags: syscall::EVENT_READ, + data: 1 + }).expect("ps2d: failed to event irq:1"); + + key_irq.write(&key_irq_data).expect("ps2d: failed to write irq:1"); + + let mut mouse_irq = OpenOptions::new() + .read(true) + .write(true) + .open("irq:12") + .expect("ps2d: failed to open irq:12"); + + let mut mouse_irq_data = [0; 8]; + mouse_irq.read(&mut mouse_irq_data).expect("ps2d: failed to read irq:12"); + + event_file.write(&syscall::Event { + id: mouse_irq.as_raw_fd() as usize, + flags: syscall::EVENT_READ, + data: 1 + }).expect("ps2d: failed to event irq:12"); + + mouse_irq.write(&mouse_irq_data).expect("ps2d: failed to write 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)?; + 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. + // + // So, if any IRQ is returned as an event, first we check if a keyboard + // IRQ has happened. If so, we know the next byte is keyboard data. If + // not, we can read mouse data. + + 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 last_mouse_irq_data = mouse_irq_data; + mouse_irq.read(&mut mouse_irq_data).expect("ps2d: failed to read irq:12"); + let mouse_irq_change = mouse_irq_data != last_mouse_irq_data; + + let last_key_irq_data = key_irq_data; + key_irq.read(&mut key_irq_data).expect("ps2d: failed to read irq:1"); + let key_irq_change = key_irq_data != last_key_irq_data; + + if key_irq_change { + ps2d.irq(true); + key_irq.write(&key_irq_data).expect("ps2d: failed to write irq:1"); + } else if mouse_irq_change { + ps2d.irq(false); + } else { + println!("ps2d: no irq change found"); } - 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"); + if mouse_irq_change { + mouse_irq.write(&mouse_irq_data).expect("ps2d: failed to write irq:12"); + } + } } 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..0d33b2db2a 100644 --- a/ps2d/src/state.rs +++ b/ps2d/src/state.rs @@ -4,6 +4,7 @@ use std::io::Write; use std::os::unix::io::AsRawFd; use std::str; use syscall; +use syscall::Io; use crate::controller::Ps2; use crate::vm; @@ -82,13 +83,13 @@ impl char> Ps2d { } } - pub fn irq(&mut self) { - while let Some((keyboard, data)) = self.ps2.next() { - self.handle(keyboard, data); - } + pub fn irq(&mut self, keyboard: bool) { + self.handle(keyboard, self.ps2.data.read()); } pub fn handle(&mut self, keyboard: bool, data: u8) { + println!("{}{:x}", if keyboard { 'k' } else { 'm' }, data); + if keyboard { let (scancode, pressed) = if data >= 0x80 { (data - 0x80, false) @@ -174,7 +175,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]); + panic!("ps2d: mouse misalign {:X}", self.packets[0]); self.packets = [0; 4]; self.packet_i = 0; @@ -227,7 +228,7 @@ impl char> Ps2d { }.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]); + panic!("ps2d: overflow {:X} {:X} {:X} {:X}", self.packets[0], self.packets[1], self.packets[2], self.packets[3]); } self.packets = [0; 4]; From a6dbe788f69e17852ec3f5682eabf21b23ad1790 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Apr 2020 11:23:15 -0600 Subject: [PATCH 2/5] Undo some changes --- ps2d/src/controller.rs | 6 +++--- ps2d/src/state.rs | 13 ++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ps2d/src/controller.rs b/ps2d/src/controller.rs index 378ecb5764..1d758446be 100644 --- a/ps2d/src/controller.rs +++ b/ps2d/src/controller.rs @@ -76,9 +76,9 @@ enum MouseCommandData { } pub struct Ps2 { - pub data: Pio, - pub status: ReadOnly>, - pub command: WriteOnly> + data: Pio, + status: ReadOnly>, + command: WriteOnly> } impl Ps2 { diff --git a/ps2d/src/state.rs b/ps2d/src/state.rs index 0d33b2db2a..0ea9d62f03 100644 --- a/ps2d/src/state.rs +++ b/ps2d/src/state.rs @@ -4,7 +4,6 @@ use std::io::Write; use std::os::unix::io::AsRawFd; use std::str; use syscall; -use syscall::Io; use crate::controller::Ps2; use crate::vm; @@ -83,13 +82,13 @@ impl char> Ps2d { } } - pub fn irq(&mut self, keyboard: bool) { - self.handle(keyboard, self.ps2.data.read()); + 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) { - println!("{}{:x}", if keyboard { 'k' } else { 'm' }, data); - if keyboard { let (scancode, pressed) = if data >= 0x80 { (data - 0x80, false) @@ -175,7 +174,7 @@ impl char> Ps2d { let flags = MousePacketFlags::from_bits_truncate(self.packets[0]); if ! flags.contains(ALWAYS_ON) { - panic!("ps2d: mouse misalign {:X}", self.packets[0]); + println!("ps2d: mouse misalign {:X}", self.packets[0]); self.packets = [0; 4]; self.packet_i = 0; @@ -228,7 +227,7 @@ impl char> Ps2d { }.to_event()).expect("ps2d: failed to write button event"); } } else { - panic!("ps2d: overflow {:X} {:X} {:X} {:X}", self.packets[0], self.packets[1], self.packets[2], self.packets[3]); + println!("ps2d: overflow {:X} {:X} {:X} {:X}", self.packets[0], self.packets[1], self.packets[2], self.packets[3]); } self.packets = [0; 4]; From 9150f7cc8508355f5d74183f4bec8f6ff28aab41 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Apr 2020 11:23:29 -0600 Subject: [PATCH 3/5] Use serio: from kernel --- ps2d/src/main.rs | 70 +++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/ps2d/src/main.rs b/ps2d/src/main.rs index 56dce69f8f..8d00348830 100644 --- a/ps2d/src/main.rs +++ b/ps2d/src/main.rs @@ -41,49 +41,40 @@ fn daemon(input: File) { let mut event_file = OpenOptions::new() .read(true) .write(true) - .custom_flags(syscall::O_NONBLOCK as i32) .open("event:") .expect("ps2d: failed to open event:"); - let mut key_irq = OpenOptions::new() + let mut key_file = OpenOptions::new() .read(true) .write(true) .custom_flags(syscall::O_NONBLOCK as i32) - .open("irq:1") - .expect("ps2d: failed to open irq:1"); - - let mut key_irq_data = [0; 8]; - key_irq.read(&mut key_irq_data).expect("ps2d: failed to read irq:1"); + .open("serio:0") + .expect("ps2d: failed to open serio:0"); event_file.write(&syscall::Event { - id: key_irq.as_raw_fd() as usize, + id: key_file.as_raw_fd() as usize, flags: syscall::EVENT_READ, - data: 1 - }).expect("ps2d: failed to event irq:1"); + data: 0 + }).expect("ps2d: failed to event serio:0"); - key_irq.write(&key_irq_data).expect("ps2d: failed to write irq:1"); - - let mut mouse_irq = OpenOptions::new() + let mut mouse_file = OpenOptions::new() .read(true) .write(true) - .open("irq:12") - .expect("ps2d: failed to open irq:12"); - - let mut mouse_irq_data = [0; 8]; - mouse_irq.read(&mut mouse_irq_data).expect("ps2d: failed to read irq:12"); + .custom_flags(syscall::O_NONBLOCK as i32) + .open("serio:1") + .expect("ps2d: failed to open serio:1"); event_file.write(&syscall::Event { - id: mouse_irq.as_raw_fd() as usize, + id: mouse_file.as_raw_fd() as usize, flags: syscall::EVENT_READ, data: 1 }).expect("ps2d: failed to event irq:12"); - mouse_irq.write(&mouse_irq_data).expect("ps2d: failed to write irq:12"); - let mut ps2d = Ps2d::new(input, keymap); syscall::setrens(0, 0).expect("ps2d: failed to enter null namespace"); + 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 @@ -91,34 +82,29 @@ fn daemon(input: File) { // came from, but if it is even implemented it can have a race // condition causing keyboard data to be read as mouse data. // - // So, if any IRQ is returned as an event, first we check if a keyboard - // IRQ has happened. If so, we know the next byte is keyboard data. If - // not, we can read 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; } - let last_mouse_irq_data = mouse_irq_data; - mouse_irq.read(&mut mouse_irq_data).expect("ps2d: failed to read irq:12"); - let mouse_irq_change = mouse_irq_data != last_mouse_irq_data; + let (file, keyboard) = match event.data { + 0 => (&mut key_file, true), + 1 => (&mut mouse_file, false), + _ => continue, + }; - let last_key_irq_data = key_irq_data; - key_irq.read(&mut key_irq_data).expect("ps2d: failed to read irq:1"); - let key_irq_change = key_irq_data != last_key_irq_data; - - if key_irq_change { - ps2d.irq(true); - key_irq.write(&key_irq_data).expect("ps2d: failed to write irq:1"); - } else if mouse_irq_change { - ps2d.irq(false); - } else { - println!("ps2d: no irq change found"); - } - - if mouse_irq_change { - mouse_irq.write(&mouse_irq_data).expect("ps2d: failed to write irq:12"); + 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]); + } } } } From af039d9507d230812b3083b617d3fede017a462b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Apr 2020 11:24:18 -0600 Subject: [PATCH 4/5] Support relative vmmouse mode, and use by default --- ps2d/src/state.rs | 19 +++++++++++-------- ps2d/src/vm.rs | 16 ++++++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/ps2d/src/state.rs b/ps2d/src/state.rs index 0ea9d62f03..bca33b61ec 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 = 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 { 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; From 751f5490bda7c427f1adca9ab8bee4a7187586cb Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 20 Apr 2020 13:00:34 -0600 Subject: [PATCH 5/5] Disable vmmouse again, for performance --- ps2d/src/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ps2d/src/state.rs b/ps2d/src/state.rs index bca33b61ec..ec6e5d2c15 100644 --- a/ps2d/src/state.rs +++ b/ps2d/src/state.rs @@ -48,7 +48,7 @@ impl char> Ps2d { let extra_packet = ps2.init(); let vmmouse_relative = true; - let vmmouse = vm::enable(vmmouse_relative); + let vmmouse = false; //vm::enable(vmmouse_relative); let mut ps2d = Ps2d { ps2,