WIP: ps2d interrupt fixes

This commit is contained in:
Jeremy Soller
2020-04-19 14:27:44 -06:00
parent 55645674d3
commit 255e5fcb68
5 changed files with 87 additions and 44 deletions
Generated
-1
View File
@@ -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)",
]
-1
View File
@@ -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"
+3 -3
View File
@@ -76,9 +76,9 @@ enum MouseCommandData {
}
pub struct Ps2 {
data: Pio<u8>,
status: ReadOnly<Pio<u8>>,
command: WriteOnly<Pio<u8>>
pub data: Pio<u8>,
pub status: ReadOnly<Pio<u8>>,
pub command: WriteOnly<Pio<u8>>
}
impl Ps2 {
+77 -33
View File
@@ -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<Option<()>> {
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<Option<()>> {
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 {
+7 -6
View File
@@ -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<F: Fn(u8,bool) -> char> Ps2d<F> {
}
}
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<F: Fn(u8,bool) -> char> Ps2d<F> {
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<F: Fn(u8,bool) -> char> Ps2d<F> {
}.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];