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];