Files
RedBear-OS/ps2d/src/main.rs
T
2020-04-20 11:23:29 -06:00

126 lines
3.5 KiB
Rust

#![feature(asm)]
#[macro_use]
extern crate bitflags;
extern crate orbclient;
extern crate syscall;
use std::{env, process};
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use syscall::iopl;
use crate::state::Ps2d;
mod controller;
mod keymap;
mod state;
mod vm;
fn daemon(input: File) {
unsafe {
iopl(3).expect("ps2d: failed to get I/O permission");
}
let keymap = match env::args().skip(1).next() {
Some(k) => match k.to_lowercase().as_ref() {
"dvorak" => (keymap::dvorak::get_char),
"us" => (keymap::us::get_char),
"gb" => (keymap::gb::get_char),
"azerty" => (keymap::azerty::get_char),
"bepo" => (keymap::bepo::get_char),
"it" => (keymap::it::get_char),
&_ => (keymap::us::get_char)
},
None => (keymap::us::get_char)
};
let mut event_file = OpenOptions::new()
.read(true)
.write(true)
.open("event:")
.expect("ps2d: failed to open event:");
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");
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 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 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;
}
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]);
}
}
}
}
fn main() {
match OpenOptions::new().write(true).open("display:input") {
Ok(input) => {
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
daemon(input);
}
},
Err(err) => {
println!("ps2d: failed to open display: {}", err);
process::exit(1);
}
}
}