WIP: ps2d interrupt fixes
This commit is contained in:
Generated
-1
@@ -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)",
|
||||
]
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user