Files
RedBear-OS/input/ps2d/src/main.rs
T
bjorn3 e973f89139 Remove unnecessary feature gates
Some of these have been stabilized while others were likely no longer
used at all.
2025-02-22 14:38:33 +01:00

136 lines
3.8 KiB
Rust

#[macro_use]
extern crate bitflags;
extern crate orbclient;
extern crate syscall;
use std::fs::OpenOptions;
use std::io::Read;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::{env, process};
use event::{user_data, EventQueue};
use inputd::ProducerHandle;
use log::info;
use syscall::call::iopl;
use crate::state::Ps2d;
mod controller;
mod keymap;
mod state;
mod vm;
fn daemon(daemon: redox_daemon::Daemon) -> ! {
common::setup_logging(
"misc",
"ps2",
"ps2",
log::LevelFilter::Info,
log::LevelFilter::Info,
);
unsafe {
iopl(3).expect("ps2d: failed to get I/O permission");
}
let (keymap, keymap_name): (fn(u8, bool) -> char, &str) = match env::args().skip(1).next() {
Some(k) => match k.to_lowercase().as_ref() {
"dvorak" => (keymap::dvorak::get_char, "dvorak"),
"us" => (keymap::us::get_char, "us"),
"gb" => (keymap::gb::get_char, "gb"),
"azerty" => (keymap::azerty::get_char, "azerty"),
"bepo" => (keymap::bepo::get_char, "bepo"),
"it" => (keymap::it::get_char, "it"),
&_ => (keymap::us::get_char, "us"),
},
None => (keymap::us::get_char, "us"),
};
info!("ps2d: using keymap '{}'", keymap_name);
let input = ProducerHandle::new().expect("ps2d: failed to open input producer");
user_data! {
enum Source {
Keyboard,
Mouse,
}
}
let event_queue: EventQueue<Source> =
EventQueue::new().expect("ps2d: failed to create event queue");
let mut key_file = OpenOptions::new()
.read(true)
.write(true)
.custom_flags(syscall::O_NONBLOCK as i32)
.open("/scheme/serio/0")
.expect("ps2d: failed to open /scheme/serio/0");
event_queue
.subscribe(
key_file.as_raw_fd() as usize,
Source::Keyboard,
event::EventFlags::READ,
)
.unwrap();
let mut mouse_file = OpenOptions::new()
.read(true)
.write(true)
.custom_flags(syscall::O_NONBLOCK as i32)
.open("/scheme/serio/1")
.expect("ps2d: failed to open /scheme/serio/1");
event_queue
.subscribe(
mouse_file.as_raw_fd() as usize,
Source::Mouse,
event::EventFlags::READ,
)
.unwrap();
libredox::call::setrens(0, 0).expect("ps2d: failed to enter null namespace");
daemon
.ready()
.expect("ps2d: failed to mark daemon as ready");
let mut ps2d = Ps2d::new(input, keymap);
let mut data = [0; 256];
for event in event_queue.map(|e| e.expect("ps2d: failed to get next event").user_data) {
// 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 (file, keyboard) = match event {
Source::Keyboard => (&mut key_file, true),
Source::Mouse => (&mut mouse_file, false),
};
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]);
}
}
}
process::exit(0);
}
fn main() {
redox_daemon::Daemon::new(daemon).expect("ps2d: failed to create daemon");
}