From 3d04f523b4d1cbf3cd95314e623a30a72bf1f1a4 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 14 Jan 2026 11:35:48 +0700 Subject: [PATCH] inputd: Implement keymap --- Cargo.lock | 15 +- Cargo.toml | 3 + drivers/input/ps2d/Cargo.toml | 2 +- drivers/input/ps2d/src/keymap.rs | 478 ---------------------------- drivers/input/ps2d/src/main.rs | 77 +---- drivers/input/ps2d/src/scheme.rs | 145 --------- drivers/input/ps2d/src/state.rs | 71 ++--- drivers/input/usbhidd/Cargo.toml | 2 +- drivers/input/usbhidd/src/keymap.rs | 478 ---------------------------- drivers/input/usbhidd/src/main.rs | 57 ++-- drivers/inputd/Cargo.toml | 2 +- drivers/inputd/src/keymap.rs | 439 +++++++++++++++++++++++++ drivers/inputd/src/lib.rs | 38 ++- drivers/inputd/src/main.rs | 140 ++++++-- 14 files changed, 645 insertions(+), 1302 deletions(-) delete mode 100644 drivers/input/ps2d/src/keymap.rs delete mode 100644 drivers/input/ps2d/src/scheme.rs delete mode 100644 drivers/input/usbhidd/src/keymap.rs create mode 100644 drivers/inputd/src/keymap.rs diff --git a/Cargo.lock b/Cargo.lock index 4e3a5023e6..a282a46c11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1383,13 +1383,12 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "orbclient" -version = "0.3.49" -source = "git+https://gitlab.redox-os.org/redox-os/orbclient.git#aefc8e0ceb4101325faa2293705a1ebfc4e0e63f" +version = "0.3.50" +source = "git+https://gitlab.redox-os.org/redox-os/orbclient.git#77c28e88fcb180c750175f2dcf5c7342d357ab26" dependencies = [ "libc", "libredox", "sdl2", - "sdl2-sys", ] [[package]] @@ -2069,9 +2068,9 @@ dependencies = [ [[package]] name = "sdl2" -version = "0.35.2" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7959277b623f1fb9e04aea73686c3ca52f01b2145f8ea16f4ff30d8b7623b1a" +checksum = "2d42407afc6a8ab67e36f92e80b8ba34cbdc55aaeed05249efe9a2e8d0e9feef" dependencies = [ "bitflags 1.3.2", "lazy_static", @@ -2081,9 +2080,9 @@ dependencies = [ [[package]] name = "sdl2-sys" -version = "0.35.2" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3586be2cf6c0a8099a79a12b4084357aa9b3e0b0d7980e3b67aaf7a9d55f9f0" +checksum = "3ff61407fc75d4b0bbc93dc7e4d6c196439965fbef8e4a4f003a36095823eac0" dependencies = [ "cfg-if 1.0.4", "libc", @@ -2389,7 +2388,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.4", + "cfg-if 0.1.10", "rand 0.8.5", "static_assertions", ] diff --git a/Cargo.toml b/Cargo.toml index 525c3b4b3a..167ce4a827 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,6 +72,9 @@ members = [ # Bootstrap needs it's own profile configuration exclude = ["bootstrap"] +[workspace.dependencies] +orbclient = { git = "https://gitlab.redox-os.org/redox-os/orbclient" } + [patch.crates-io] # Needs libc 0.2 backport of https://github.com/rust-lang/libc/pull/4825 libc = { git = "https://gitlab.redox-os.org/redox-os/liblibc.git", branch = "redox-0.2" } diff --git a/drivers/input/ps2d/Cargo.toml b/drivers/input/ps2d/Cargo.toml index d1716b19b9..9173c05624 100644 --- a/drivers/input/ps2d/Cargo.toml +++ b/drivers/input/ps2d/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] bitflags = "1" log = "0.4" -orbclient = "0.3.27" +orbclient = { workspace = true } redox_event = "0.4.1" redox_syscall = "0.6" redox-scheme = "0.8.3" diff --git a/drivers/input/ps2d/src/keymap.rs b/drivers/input/ps2d/src/keymap.rs deleted file mode 100644 index 46264606a7..0000000000 --- a/drivers/input/ps2d/src/keymap.rs +++ /dev/null @@ -1,478 +0,0 @@ -pub mod us { - static US: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '@'], - ['3', '#'], - ['4', '$'], - ['5', '%'], - ['6', '^'], - ['7', '&'], - ['8', '*'], - ['9', '('], - ['0', ')'], - ['-', '_'], - ['=', '+'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['q', 'Q'], - ['w', 'W'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['[', '{'], - [']', '}'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - [';', ':'], - ['\'', '"'], - ['`', '~'], - ['\0', '\0'], - ['\\', '|'], - ['z', 'Z'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - ['m', 'M'], - [',', '<'], - ['.', '>'], - ['/', '?'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = US.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod gb { - static GB: [[char; 2]; 87] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '"'], - ['3', '£'], - ['4', '$'], - ['5', '%'], - ['6', '^'], - ['7', '&'], - ['8', '*'], - ['9', '('], - ['0', ')'], - ['-', '_'], - ['=', '+'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['q', 'Q'], - ['w', 'W'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['[', '{'], - [']', '}'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - [';', ':'], - ['\'', '@'], - ['`', '¬'], - ['\0', '\0'], - ['#', '~'], - ['z', 'Z'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - ['m', 'M'], - [',', '<'], - ['.', '>'], - ['/', '?'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\\', '|'], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = GB.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod dvorak { - static DVORAK: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '@'], - ['3', '#'], - ['4', '$'], - ['5', '%'], - ['6', '^'], - ['7', '&'], - ['8', '*'], - ['9', '('], - ['0', ')'], - ['[', '{'], - [']', '}'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['\'', '"'], - [',', '<'], - ['.', '>'], - ['p', 'P'], - ['y', 'Y'], - ['f', 'F'], - ['g', 'G'], - ['c', 'C'], - ['r', 'R'], - ['l', 'L'], - ['/', '?'], - ['=', '+'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['o', 'O'], - ['e', 'E'], - ['u', 'U'], - ['i', 'I'], - ['d', 'D'], - ['h', 'H'], - ['t', 'T'], - ['n', 'N'], - ['s', 'S'], - ['-', '_'], - ['`', '~'], - ['\0', '\0'], - ['\\', '|'], - [';', ':'], - ['q', 'Q'], - ['j', 'J'], - ['k', 'K'], - ['x', 'X'], - ['b', 'B'], - ['m', 'M'], - ['w', 'W'], - ['v', 'V'], - ['z', 'Z'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = DVORAK.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod azerty { - static AZERTY: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['&', '1'], - ['é', '2'], - ['"', '3'], - ['\'', '4'], - ['(', '5'], - ['|', '6'], - ['è', '7'], - ['_', '8'], - ['ç', '9'], - ['à', '0'], - [')', '°'], - ['=', '+'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['a', 'A'], - ['z', 'Z'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['^', '¨'], - ['$', '£'], - ['\n', '\n'], - ['\0', '\0'], - ['q', 'Q'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - ['m', 'M'], - ['ù', '%'], - ['*', 'µ'], - ['\0', '\0'], - ['ê', 'Ê'], - ['w', 'W'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - [',', '?'], - [';', '.'], - [':', '/'], - ['!', '§'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = AZERTY.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod bepo { - static BEPO: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['"', '1'], - ['«', '2'], - ['»', '3'], - ['(', '4'], - [')', '5'], - ['@', '6'], - ['+', '7'], - ['-', '8'], - ['/', '9'], - ['*', '0'], - ['=', '°'], - ['%', '`'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['b', 'B'], - ['é', 'É'], - ['p', 'P'], - ['o', 'O'], - ['è', 'È'], - ['^', '!'], - ['v', 'V'], - ['d', 'D'], - ['l', 'L'], - ['j', 'J'], - ['z', 'Z'], - ['w', 'W'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['u', 'U'], - ['i', 'I'], - ['e', 'E'], - [',', ';'], - ['c', 'C'], - ['t', 'T'], - ['s', 'S'], - ['r', 'R'], - ['n', 'N'], - ['m', 'M'], - ['ç', 'Ç'], - ['\0', '\0'], - ['ê', 'Ê'], - ['à', 'À'], - ['y', 'Y'], - ['x', 'X'], - ['.', ':'], - ['k', 'K'], - ['\'', '?'], - ['q', 'Q'], - ['g', 'G'], - ['h', 'H'], - ['f', 'F'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = BEPO.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod it { - static IT: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '"'], - ['3', '£'], - ['4', '$'], - ['5', '%'], - ['6', '&'], - ['7', '/'], - ['8', '('], - ['9', ')'], - ['0', '='], - ['?', '\''], - ['ì', '^'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['q', 'Q'], - ['w', 'W'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['è', 'é'], - ['+', '*'], - ['\n', '\n'], - ['\x20', '\x20'], - ['a', 'A'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - ['ò', 'ç'], - ['à', '°'], - ['ù', '§'], - ['\0', '\0'], - ['<', '>'], - ['z', 'Z'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - ['m', 'M'], - [',', ';'], - ['.', ':'], - ['-', '_'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = IT.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} diff --git a/drivers/input/ps2d/src/main.rs b/drivers/input/ps2d/src/main.rs index 53c93fc7ed..ce044ce7ae 100644 --- a/drivers/input/ps2d/src/main.rs +++ b/drivers/input/ps2d/src/main.rs @@ -12,16 +12,10 @@ use std::{env, process}; use common::acquire_port_io_rights; use event::{user_data, EventQueue}; use inputd::ProducerHandle; -use log::info; -use redox_scheme::{RequestKind, SignalBehavior, Socket}; -use syscall::{EAGAIN, EWOULDBLOCK}; -use crate::scheme::Ps2Scheme; use crate::state::Ps2d; mod controller; -mod keymap; -mod scheme; mod state; mod vm; @@ -36,21 +30,12 @@ fn daemon(daemon: daemon::Daemon) -> ! { acquire_port_io_rights().expect("ps2d: failed to get I/O permission"); - let (mut keymap, mut keymap_name): (fn(u8, bool) -> char, &str) = - match env::args().skip(1).next() { - Some(k) => get_keymap_from_str(&k), - 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, - Scheme, } } @@ -87,26 +72,11 @@ fn daemon(daemon: daemon::Daemon) -> ! { ) .unwrap(); - let scheme_file = Socket::nonblock("ps2").expect("ps2d: failed to create ps2 scheme"); - - let mut scheme_handle = Ps2Scheme::new( - keymap_name.to_owned(), - vec!["dvorak", "us", "gb", "azerty", "bepo", "it"], - ); - - event_queue - .subscribe( - scheme_file.inner().raw(), - Source::Scheme, - event::EventFlags::READ, - ) - .unwrap(); - libredox::call::setrens(0, 0).expect("ps2d: failed to enter null namespace"); daemon.ready(); - let mut ps2d = Ps2d::new(input, keymap); + let mut ps2d = Ps2d::new(input); let mut data = [0; 256]; for event in event_queue.map(|e| e.expect("ps2d: failed to get next event").user_data) { @@ -122,39 +92,6 @@ fn daemon(daemon: daemon::Daemon) -> ! { let (file, keyboard) = match event { Source::Keyboard => (&mut key_file, true), Source::Mouse => (&mut mouse_file, false), - Source::Scheme => { - loop { - let request = match scheme_file.next_request(SignalBehavior::Interrupt) { - Ok(Some(request)) => request, - Ok(None) => { - // Scheme likely got unmounted - std::process::exit(0); - } - Err(err) if err.errno == EWOULDBLOCK || err.errno == EAGAIN => break, - Err(err) => panic!("ps2: failed to read scheme: {:?}", err), - }; - - match request.kind() { - RequestKind::Call(call) => { - let response = call.handle_sync(&mut scheme_handle); - - scheme_file - .write_response(response, SignalBehavior::Restart) - .expect("ps2: failed to write next scheme response"); - } - RequestKind::OnClose { id: _ } => {} - _ => (), - } - } - - if keymap_name != &scheme_handle.keymap { - (keymap, keymap_name) = get_keymap_from_str(&scheme_handle.keymap); - info!("ps2d: updating to new keymap '{:?}'", keymap_name); - ps2d.update_keymap(keymap); - } - - continue; - } }; loop { @@ -172,18 +109,6 @@ fn daemon(daemon: daemon::Daemon) -> ! { process::exit(0); } -fn get_keymap_from_str(k: &str) -> (fn(u8, bool) -> char, &'static str) { - 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"), - } -} - fn main() { daemon::Daemon::new(daemon); } diff --git a/drivers/input/ps2d/src/scheme.rs b/drivers/input/ps2d/src/scheme.rs deleted file mode 100644 index 058ec776c3..0000000000 --- a/drivers/input/ps2d/src/scheme.rs +++ /dev/null @@ -1,145 +0,0 @@ -use redox_scheme::scheme::SchemeSync; -use redox_scheme::{CallerCtx, OpenResult}; -use std::convert::TryFrom; -use syscall::dirent::{DirEntry, DirentBuf, DirentKind}; -use syscall::schemev2::NewFdFlags; -use syscall::{ - Error, Result, EACCES, EINVAL, EMFILE, ENOENT, ENOTDIR, MODE_DIR, MODE_FILE, O_WRONLY, -}; - -pub struct Ps2Scheme { - pub keymap: String, - pub keymap_list: String, -} - -impl Ps2Scheme { - pub fn new(keymap: String, keymap_list: Vec<&str>) -> Ps2Scheme { - let scheme = Ps2Scheme { - keymap, - keymap_list: keymap_list.join("\n"), - }; - scheme - } -} - -impl SchemeSync for Ps2Scheme { - fn open(&mut self, path_str: &str, flags: usize, ctx: &CallerCtx) -> Result { - let path = path_str.trim_start_matches('/'); - if flags & O_WRONLY != 0 { - if ctx.uid != 0 || ctx.gid != 0 { - return Err(Error::new(EACCES)); - } else if path != "keymap" { - return Err(Error::new(EINVAL)); - } - } - - match path { - "" => Ok(OpenResult::ThisScheme { - number: 0, - flags: NewFdFlags::empty(), - }), - "keymap" => Ok(OpenResult::ThisScheme { - number: 1, - flags: NewFdFlags::POSITIONED, - }), - "keymap_list" => Ok(OpenResult::ThisScheme { - number: 2, - flags: NewFdFlags::POSITIONED, - }), - _ => Err(Error::new(ENOENT)), - } - } - fn getdents<'buf>( - &mut self, - id: usize, - mut buf: DirentBuf<&'buf mut [u8]>, - opaque_offset: u64, - ) -> Result> { - if id != 0 { - return Err(Error::new(ENOTDIR)); - } - let Ok(offset) = usize::try_from(opaque_offset) else { - return Ok(buf); - }; - for (this_idx, name) in ["keymap", "keymap_list"].iter().enumerate().skip(offset) { - buf.entry(DirEntry { - inode: this_idx as u64, - next_opaque_id: this_idx as u64 + 1, - kind: DirentKind::Regular, - name, - })?; - } - Ok(buf) - } - - fn fstat(&mut self, id: usize, stat: &mut syscall::Stat, _ctx: &CallerCtx) -> Result<()> { - stat.st_size = 0; - stat.st_mode = match id { - 0 => 0o555 | MODE_DIR, - 1 => 0o644 | MODE_FILE, - 2 => 0o444 | MODE_FILE, - _ => return Err(Error::new(ENOENT)), - }; - Ok(()) - } - - fn fpath(&mut self, _id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { - let path = b"/scheme/ps2"; - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn fsync(&mut self, _id: usize, _ctx: &CallerCtx) -> Result<()> { - Ok(()) - } - - fn read( - &mut self, - id: usize, - buf: &mut [u8], - offset: u64, - _fcntl_flags: u32, - _ctx: &CallerCtx, - ) -> Result { - if offset != 0 { - return Ok(0); - } - let value = match id { - 1 => self.keymap.as_bytes(), - 2 => self.keymap_list.as_bytes(), - _ => { - return Err(Error::new(ENOENT)); - } - }; - - if buf.len() + 2 < value.len() { - return Err(Error::new(EMFILE)); - } - buf[..value.len()].copy_from_slice(value); - buf[value.len()] = b'\n'; - buf[value.len() + 1] = b'\0'; - Ok(value.len() + 2) - } - - fn write( - &mut self, - id: usize, - buf: &[u8], - offset: u64, - _fcntl_flags: u32, - _ctx: &CallerCtx, - ) -> Result { - if offset != 0 || id != 1 { - return Ok(0); - } - let new_keymap = String::from_utf8(buf.to_vec()).map_err(|_| Error::new(EINVAL))?; - self.keymap = new_keymap.trim().to_string(); - Ok(buf.len()) - } -} diff --git a/drivers/input/ps2d/src/state.rs b/drivers/input/ps2d/src/state.rs index b8126bcb1c..8443a6e1c6 100644 --- a/drivers/input/ps2d/src/state.rs +++ b/drivers/input/ps2d/src/state.rs @@ -18,14 +18,12 @@ bitflags! { } } -pub struct Ps2d char> { +pub struct Ps2d { ps2: Ps2, vmmouse: bool, vmmouse_relative: bool, input: ProducerHandle, extended: bool, - lshift: bool, - rshift: bool, mouse_x: i32, mouse_y: i32, mouse_left: bool, @@ -34,12 +32,10 @@ pub struct Ps2d char> { packets: [u8; 4], packet_i: usize, extra_packet: bool, - //Keymap function - get_char: F, } -impl char> Ps2d { - pub fn new(input: ProducerHandle, keymap: F) -> Self { +impl Ps2d { + pub fn new(input: ProducerHandle) -> Self { let mut ps2 = Ps2::new(); let extra_packet = ps2.init(); @@ -53,8 +49,6 @@ impl char> Ps2d { vmmouse_relative, input, extended: false, - lshift: false, - rshift: false, mouse_x: 0, mouse_y: 0, mouse_left: false, @@ -63,14 +57,9 @@ impl char> Ps2d { packets: [0; 4], packet_i: 0, extra_packet, - get_char: keymap, } } - pub fn update_keymap(&mut self, keymap: F) { - self.get_char = keymap; - } - pub fn irq(&mut self) { while let Some((keyboard, data)) = self.ps2.next() { self.handle(keyboard, data); @@ -91,13 +80,16 @@ impl char> Ps2d { let scancode = if self.extended { self.extended = false; match ps2_scancode { - //TODO: media keys - //TODO: 0x1C => orbclient::K_NUM_ENTER, - 0x1D => orbclient::K_CTRL, //TODO: 0x1D => orbclient::K_RIGHT_CTRL, - 0x20 => 0x80 + 0x20, //TODO: orbclient::K_VOLUME_MUTE, - 0x2E => 0x80 + 0x2E, //TODO: orbclient::K_VOLUME_DOWN, - 0x30 => 0x80 + 0x30, //TODO: orbclient::K_VOLUME_UP, - //TODO: 0x35 => orbclient::K_NUM_SLASH, + 0x1C => orbclient::K_NUM_ENTER, + 0x1D => orbclient::K_RIGHT_CTRL, + 0x20 => orbclient::K_VOLUME_TOGGLE, + 0x22 => orbclient::K_MEDIA_PLAY_PAUSE, + 0x24 => orbclient::K_MEDIA_STOP, + 0x10 => orbclient::K_MEDIA_REWIND, + 0x19 => orbclient::K_MEDIA_FAST_FORWARD, + 0x2E => orbclient::K_VOLUME_DOWN, + 0x30 => orbclient::K_VOLUME_UP, + 0x35 => orbclient::K_NUM_SLASH, 0x38 => orbclient::K_ALT_GR, 0x47 => orbclient::K_HOME, 0x48 => orbclient::K_UP, @@ -107,12 +99,13 @@ impl char> Ps2d { 0x4F => orbclient::K_END, 0x50 => orbclient::K_DOWN, 0x51 => orbclient::K_PGDN, - //TODO: 0x52 => orbclient::K_INSERT, + 0x52 => orbclient::K_INS, 0x53 => orbclient::K_DEL, - 0x5B => 0x5B, //TODO: orbclient::K_LEFT_SUPER, - //TODO: 0x5C => orbclient::K_RIGHT_SUPER, - //TODO: 0x5D => orbclient::K_APP, - //TODO power keys + 0x5B => orbclient::K_LEFT_SUPER, + 0x5C => orbclient::K_RIGHT_SUPER, + 0x5D => orbclient::K_APP, + 0x5E => orbclient::K_POWER, + 0x5F => orbclient::K_SLEEP, /* 0x80 to 0xFF used for press/release detection */ _ => { if pressed { @@ -178,7 +171,7 @@ impl char> Ps2d { 0x34 => orbclient::K_PERIOD, 0x35 => orbclient::K_SLASH, 0x36 => orbclient::K_RIGHT_SHIFT, - //TODO: 0x37 => orbclient::K_NUM_ASTERISK, + 0x37 => orbclient::K_NUM_ASTERISK, 0x38 => orbclient::K_ALT, 0x39 => orbclient::K_SPACE, 0x3A => orbclient::K_CAPS, @@ -192,22 +185,23 @@ impl char> Ps2d { 0x42 => orbclient::K_F8, 0x43 => orbclient::K_F9, 0x44 => orbclient::K_F10, - //TODO: 0x45 => orbclient::K_NUM_LOCK, - //TODO: 0x46 => orbclient::K_SCROLL_LOCK, + 0x45 => orbclient::K_NUM, + 0x46 => orbclient::K_SCROLL, 0x47 => orbclient::K_NUM_7, 0x48 => orbclient::K_NUM_8, 0x49 => orbclient::K_NUM_9, - //TODO: 0x4A => orbclient::K_NUM_MINUS, + 0x4A => orbclient::K_NUM_MINUS, 0x4B => orbclient::K_NUM_4, 0x4C => orbclient::K_NUM_5, 0x4D => orbclient::K_NUM_6, - //TODO: 0x4E => orbclient::K_NUM_PLUS, + 0x4E => orbclient::K_NUM_PLUS, 0x4F => orbclient::K_NUM_1, 0x50 => orbclient::K_NUM_2, 0x51 => orbclient::K_NUM_3, 0x52 => orbclient::K_NUM_0, - //TODO: 0x53 => orbclient::K_NUM_PERIOD, - /* 0x54 to 0x56 unused */ + 0x53 => orbclient::K_NUM_PERIOD, + /* 0x54 to 0x55 unused */ + 0x56 => 0x56, // UK Backslash 0x57 => orbclient::K_F11, 0x58 => orbclient::K_F12, /* 0x59 to 0x7F unused */ @@ -221,20 +215,11 @@ impl char> Ps2d { } }; - if scancode == orbclient::K_LEFT_SHIFT { - self.lshift = pressed; - } else if scancode == orbclient::K_RIGHT_SHIFT { - self.rshift = pressed; - } - if scancode != 0 { self.input .write_event( KeyEvent { - character: (self.get_char)( - ps2_scancode, - self.lshift || self.rshift, - ), + character: '\0', scancode, pressed, } diff --git a/drivers/input/usbhidd/Cargo.toml b/drivers/input/usbhidd/Cargo.toml index 0e0969f10d..028f7a0ab1 100644 --- a/drivers/input/usbhidd/Cargo.toml +++ b/drivers/input/usbhidd/Cargo.toml @@ -10,7 +10,7 @@ license = "MIT" [dependencies] bitflags = "2" log = "0.4" -orbclient = "0.3.47" +orbclient = { workspace = true } redox_syscall = "0.6" rehid = { git = "https://gitlab.redox-os.org/redox-os/rehid.git" } xhcid = { path = "../../usb/xhcid" } diff --git a/drivers/input/usbhidd/src/keymap.rs b/drivers/input/usbhidd/src/keymap.rs deleted file mode 100644 index 46264606a7..0000000000 --- a/drivers/input/usbhidd/src/keymap.rs +++ /dev/null @@ -1,478 +0,0 @@ -pub mod us { - static US: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '@'], - ['3', '#'], - ['4', '$'], - ['5', '%'], - ['6', '^'], - ['7', '&'], - ['8', '*'], - ['9', '('], - ['0', ')'], - ['-', '_'], - ['=', '+'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['q', 'Q'], - ['w', 'W'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['[', '{'], - [']', '}'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - [';', ':'], - ['\'', '"'], - ['`', '~'], - ['\0', '\0'], - ['\\', '|'], - ['z', 'Z'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - ['m', 'M'], - [',', '<'], - ['.', '>'], - ['/', '?'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = US.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod gb { - static GB: [[char; 2]; 87] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '"'], - ['3', '£'], - ['4', '$'], - ['5', '%'], - ['6', '^'], - ['7', '&'], - ['8', '*'], - ['9', '('], - ['0', ')'], - ['-', '_'], - ['=', '+'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['q', 'Q'], - ['w', 'W'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['[', '{'], - [']', '}'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - [';', ':'], - ['\'', '@'], - ['`', '¬'], - ['\0', '\0'], - ['#', '~'], - ['z', 'Z'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - ['m', 'M'], - [',', '<'], - ['.', '>'], - ['/', '?'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - ['\\', '|'], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = GB.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod dvorak { - static DVORAK: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '@'], - ['3', '#'], - ['4', '$'], - ['5', '%'], - ['6', '^'], - ['7', '&'], - ['8', '*'], - ['9', '('], - ['0', ')'], - ['[', '{'], - [']', '}'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['\'', '"'], - [',', '<'], - ['.', '>'], - ['p', 'P'], - ['y', 'Y'], - ['f', 'F'], - ['g', 'G'], - ['c', 'C'], - ['r', 'R'], - ['l', 'L'], - ['/', '?'], - ['=', '+'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['o', 'O'], - ['e', 'E'], - ['u', 'U'], - ['i', 'I'], - ['d', 'D'], - ['h', 'H'], - ['t', 'T'], - ['n', 'N'], - ['s', 'S'], - ['-', '_'], - ['`', '~'], - ['\0', '\0'], - ['\\', '|'], - [';', ':'], - ['q', 'Q'], - ['j', 'J'], - ['k', 'K'], - ['x', 'X'], - ['b', 'B'], - ['m', 'M'], - ['w', 'W'], - ['v', 'V'], - ['z', 'Z'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = DVORAK.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod azerty { - static AZERTY: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['&', '1'], - ['é', '2'], - ['"', '3'], - ['\'', '4'], - ['(', '5'], - ['|', '6'], - ['è', '7'], - ['_', '8'], - ['ç', '9'], - ['à', '0'], - [')', '°'], - ['=', '+'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['a', 'A'], - ['z', 'Z'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['^', '¨'], - ['$', '£'], - ['\n', '\n'], - ['\0', '\0'], - ['q', 'Q'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - ['m', 'M'], - ['ù', '%'], - ['*', 'µ'], - ['\0', '\0'], - ['ê', 'Ê'], - ['w', 'W'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - [',', '?'], - [';', '.'], - [':', '/'], - ['!', '§'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = AZERTY.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod bepo { - static BEPO: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['"', '1'], - ['«', '2'], - ['»', '3'], - ['(', '4'], - [')', '5'], - ['@', '6'], - ['+', '7'], - ['-', '8'], - ['/', '9'], - ['*', '0'], - ['=', '°'], - ['%', '`'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['b', 'B'], - ['é', 'É'], - ['p', 'P'], - ['o', 'O'], - ['è', 'È'], - ['^', '!'], - ['v', 'V'], - ['d', 'D'], - ['l', 'L'], - ['j', 'J'], - ['z', 'Z'], - ['w', 'W'], - ['\n', '\n'], - ['\0', '\0'], - ['a', 'A'], - ['u', 'U'], - ['i', 'I'], - ['e', 'E'], - [',', ';'], - ['c', 'C'], - ['t', 'T'], - ['s', 'S'], - ['r', 'R'], - ['n', 'N'], - ['m', 'M'], - ['ç', 'Ç'], - ['\0', '\0'], - ['ê', 'Ê'], - ['à', 'À'], - ['y', 'Y'], - ['x', 'X'], - ['.', ':'], - ['k', 'K'], - ['\'', '?'], - ['q', 'Q'], - ['g', 'G'], - ['h', 'H'], - ['f', 'F'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = BEPO.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} - -pub mod it { - static IT: [[char; 2]; 58] = [ - ['\0', '\0'], - ['\x1B', '\x1B'], - ['1', '!'], - ['2', '"'], - ['3', '£'], - ['4', '$'], - ['5', '%'], - ['6', '&'], - ['7', '/'], - ['8', '('], - ['9', ')'], - ['0', '='], - ['?', '\''], - ['ì', '^'], - ['\x7F', '\x7F'], - ['\t', '\t'], - ['q', 'Q'], - ['w', 'W'], - ['e', 'E'], - ['r', 'R'], - ['t', 'T'], - ['y', 'Y'], - ['u', 'U'], - ['i', 'I'], - ['o', 'O'], - ['p', 'P'], - ['è', 'é'], - ['+', '*'], - ['\n', '\n'], - ['\x20', '\x20'], - ['a', 'A'], - ['s', 'S'], - ['d', 'D'], - ['f', 'F'], - ['g', 'G'], - ['h', 'H'], - ['j', 'J'], - ['k', 'K'], - ['l', 'L'], - ['ò', 'ç'], - ['à', '°'], - ['ù', '§'], - ['\0', '\0'], - ['<', '>'], - ['z', 'Z'], - ['x', 'X'], - ['c', 'C'], - ['v', 'V'], - ['b', 'B'], - ['n', 'N'], - ['m', 'M'], - [',', ';'], - ['.', ':'], - ['-', '_'], - ['\0', '\0'], - ['\0', '\0'], - ['\0', '\0'], - [' ', ' '], - ]; - - pub fn get_char(scancode: u8, shift: bool) -> char { - if let Some(c) = IT.get(scancode as usize) { - if shift { - c[1] - } else { - c[0] - } - } else { - '\0' - } - } -} diff --git a/drivers/input/usbhidd/src/main.rs b/drivers/input/usbhidd/src/main.rs index 8b5d5e8c2c..b6ab32d130 100644 --- a/drivers/input/usbhidd/src/main.rs +++ b/drivers/input/usbhidd/src/main.rs @@ -12,16 +12,9 @@ use xhcid_interface::{ XhciClientHandle, }; -mod keymap; mod reqs; -fn send_key_event( - display: &mut ProducerHandle, - usage_page: u16, - usage: u16, - pressed: bool, - shift_opt: Option, -) { +fn send_key_event(display: &mut ProducerHandle, usage_page: u16, usage: u16, pressed: bool) { let scancode = match usage_page { 0x07 => match usage { 0x04 => orbclient::K_A, @@ -71,6 +64,7 @@ fn send_key_event( 0x30 => orbclient::K_BRACE_CLOSE, 0x31 => orbclient::K_BACKSLASH, // 0x32 non-us # and ~ + 0x32 => 0x56, 0x33 => orbclient::K_SEMICOLON, 0x34 => orbclient::K_QUOTE, 0x35 => orbclient::K_TICK, @@ -90,10 +84,10 @@ fn send_key_event( 0x43 => orbclient::K_F10, 0x44 => orbclient::K_F11, 0x45 => orbclient::K_F12, - // 0x46 print screen - // 0x47 scroll lock + 0x46 => orbclient::K_PRTSC, + 0x47 => orbclient::K_SCROLL, // 0x48 pause - // 0x49 insert + 0x49 => orbclient::K_INS, 0x4A => orbclient::K_HOME, 0x4B => orbclient::K_PGUP, 0x4C => orbclient::K_DEL, @@ -103,12 +97,12 @@ fn send_key_event( 0x50 => orbclient::K_LEFT, 0x51 => orbclient::K_DOWN, 0x52 => orbclient::K_UP, - // 0x53 num lock - // 0x54 num / - // 0x55 num * - // 0x56 num - - // 0x57 num + - // 0x58 num enter + 0x53 => orbclient::K_NUM, + 0x54 => orbclient::K_NUM_SLASH, + 0x55 => orbclient::K_NUM_ASTERISK, + 0x56 => orbclient::K_NUM_MINUS, + 0x57 => orbclient::K_NUM_PLUS, + 0x58 => orbclient::K_NUM_ENTER, 0x59 => orbclient::K_NUM_1, 0x5A => orbclient::K_NUM_2, 0x5B => orbclient::K_NUM_3, @@ -121,18 +115,18 @@ fn send_key_event( 0x62 => orbclient::K_NUM_0, // 0x62 num . // 0x64 non-us \ and | - // 0x64 app - // 0x66 power + 0x64 => orbclient::K_APP, + 0x66 => orbclient::K_POWER, // 0x67 num = // unmapped values - 0xE0 => orbclient::K_CTRL, // TODO: left control + 0xE0 => orbclient::K_LEFT_CTRL, 0xE1 => orbclient::K_LEFT_SHIFT, 0xE2 => orbclient::K_ALT, - 0xE3 => 0x5B, // left super - 0xE4 => orbclient::K_CTRL, // TODO: right control + 0xE3 => orbclient::K_LEFT_SUPER, + 0xE4 => orbclient::K_RIGHT_CTRL, 0xE5 => orbclient::K_RIGHT_SHIFT, 0xE6 => orbclient::K_ALT_GR, - // 0xE7 right super + 0xE7 => orbclient::K_RIGHT_SUPER, // reserved values _ => { log::warn!("unknown usage_page {:#x} usage {:#x}", usage_page, usage); @@ -145,15 +139,8 @@ fn send_key_event( } }; - //TODO: other keymaps - let character = if let Some(shift) = shift_opt { - keymap::us::get_char(scancode, shift) - } else { - '\0' - }; - let key_event = OrbKeyEvent { - character, + character: '\0', scancode, pressed, }; @@ -363,13 +350,7 @@ fn main() { } else if event.usage == 0xE5 { right_shift = pressed; } - send_key_event( - &mut display, - event.usage_page, - event.usage, - pressed, - shift_opt, - ); + send_key_event(&mut display, event.usage_page, event.usage, pressed); } else if event.usage_page == UsagePage::Button as u16 { if event.usage > 0 && event.usage as usize <= buttons.len() { buttons[event.usage as usize - 1] = event.value != 0; diff --git a/drivers/inputd/Cargo.toml b/drivers/inputd/Cargo.toml index 1dd9f7bd2f..0da4b03275 100644 --- a/drivers/inputd/Cargo.toml +++ b/drivers/inputd/Cargo.toml @@ -8,7 +8,7 @@ authors = ["Anhad Singh "] anyhow = "1.0.71" log = "0.4.19" redox_syscall = { version = "0.6", features = ["std"] } -orbclient = "0.3.27" +orbclient = { workspace = true } libredox = "0.1.3" common = { path = "../common" } diff --git a/drivers/inputd/src/keymap.rs b/drivers/inputd/src/keymap.rs new file mode 100644 index 0000000000..801629cd6c --- /dev/null +++ b/drivers/inputd/src/keymap.rs @@ -0,0 +1,439 @@ +use std::collections::HashMap; +use std::fmt::Display; +use std::str::FromStr; + +mod keymaps { + pub static US: [(u8, [char; 2]); 53] = [ + (orbclient::K_ESC, ['\x1B', '\x1B']), + (orbclient::K_1, ['1', '!']), + (orbclient::K_2, ['2', '@']), + (orbclient::K_3, ['3', '#']), + (orbclient::K_4, ['4', '$']), + (orbclient::K_5, ['5', '%']), + (orbclient::K_6, ['6', '^']), + (orbclient::K_7, ['7', '&']), + (orbclient::K_8, ['8', '*']), + (orbclient::K_9, ['9', '(']), + (orbclient::K_0, ['0', ')']), + (orbclient::K_MINUS, ['-', '_']), + (orbclient::K_EQUALS, ['=', '+']), + (orbclient::K_BKSP, ['\x7F', '\x7F']), + (orbclient::K_TAB, ['\t', '\t']), + (orbclient::K_Q, ['q', 'Q']), + (orbclient::K_W, ['w', 'W']), + (orbclient::K_E, ['e', 'E']), + (orbclient::K_R, ['r', 'R']), + (orbclient::K_T, ['t', 'T']), + (orbclient::K_Y, ['y', 'Y']), + (orbclient::K_U, ['u', 'U']), + (orbclient::K_I, ['i', 'I']), + (orbclient::K_O, ['o', 'O']), + (orbclient::K_P, ['p', 'P']), + (orbclient::K_BRACE_OPEN, ['[', '{']), + (orbclient::K_BRACE_CLOSE, [']', '}']), + (orbclient::K_ENTER, ['\n', '\n']), + (orbclient::K_CTRL, ['\0', '\0']), + (orbclient::K_A, ['a', 'A']), + (orbclient::K_S, ['s', 'S']), + (orbclient::K_D, ['d', 'D']), + (orbclient::K_F, ['f', 'F']), + (orbclient::K_G, ['g', 'G']), + (orbclient::K_H, ['h', 'H']), + (orbclient::K_J, ['j', 'J']), + (orbclient::K_K, ['k', 'K']), + (orbclient::K_L, ['l', 'L']), + (orbclient::K_SEMICOLON, [';', ':']), + (orbclient::K_QUOTE, ['\'', '"']), + (orbclient::K_TICK, ['`', '~']), + (orbclient::K_BACKSLASH, ['\\', '|']), + (orbclient::K_Z, ['z', 'Z']), + (orbclient::K_X, ['x', 'X']), + (orbclient::K_C, ['c', 'C']), + (orbclient::K_V, ['v', 'V']), + (orbclient::K_B, ['b', 'B']), + (orbclient::K_N, ['n', 'N']), + (orbclient::K_M, ['m', 'M']), + (orbclient::K_COMMA, [',', '<']), + (orbclient::K_PERIOD, ['.', '>']), + (orbclient::K_SLASH, ['/', '?']), + (orbclient::K_SPACE, [' ', ' ']), + ]; + + pub static GB: [(u8, [char; 2]); 54] = [ + (orbclient::K_ESC, ['\x1B', '\x1B']), + (orbclient::K_1, ['1', '!']), + (orbclient::K_2, ['2', '"']), + (orbclient::K_3, ['3', '£']), + (orbclient::K_4, ['4', '$']), + (orbclient::K_5, ['5', '%']), + (orbclient::K_6, ['6', '^']), + (orbclient::K_7, ['7', '&']), + (orbclient::K_8, ['8', '*']), + (orbclient::K_9, ['9', '(']), + (orbclient::K_0, ['0', ')']), + (orbclient::K_MINUS, ['-', '_']), + (orbclient::K_EQUALS, ['=', '+']), + (orbclient::K_BKSP, ['\x7F', '\x7F']), + (orbclient::K_TAB, ['\t', '\t']), + (orbclient::K_Q, ['q', 'Q']), + (orbclient::K_W, ['w', 'W']), + (orbclient::K_E, ['e', 'E']), + (orbclient::K_R, ['r', 'R']), + (orbclient::K_T, ['t', 'T']), + (orbclient::K_Y, ['y', 'Y']), + (orbclient::K_U, ['u', 'U']), + (orbclient::K_I, ['i', 'I']), + (orbclient::K_O, ['o', 'O']), + (orbclient::K_P, ['p', 'P']), + (orbclient::K_BRACE_OPEN, ['[', '{']), + (orbclient::K_BRACE_CLOSE, [']', '}']), + (orbclient::K_ENTER, ['\n', '\n']), + (orbclient::K_CTRL, ['\0', '\0']), + (orbclient::K_A, ['a', 'A']), + (orbclient::K_S, ['s', 'S']), + (orbclient::K_D, ['d', 'D']), + (orbclient::K_F, ['f', 'F']), + (orbclient::K_G, ['g', 'G']), + (orbclient::K_H, ['h', 'H']), + (orbclient::K_J, ['j', 'J']), + (orbclient::K_K, ['k', 'K']), + (orbclient::K_L, ['l', 'L']), + (orbclient::K_SEMICOLON, [';', ':']), + (orbclient::K_QUOTE, ['\'', '@']), + (orbclient::K_TICK, ['`', '¬']), + (orbclient::K_BACKSLASH, ['#', '~']), + (orbclient::K_Z, ['z', 'Z']), + (orbclient::K_X, ['x', 'X']), + (orbclient::K_C, ['c', 'C']), + (orbclient::K_V, ['v', 'V']), + (orbclient::K_B, ['b', 'B']), + (orbclient::K_N, ['n', 'N']), + (orbclient::K_M, ['m', 'M']), + (orbclient::K_COMMA, [',', '<']), + (orbclient::K_PERIOD, ['.', '>']), + (orbclient::K_SLASH, ['/', '?']), + (orbclient::K_SPACE, [' ', ' ']), + // UK Backslash, doesn't exist on US keyboard + (0x56, ['\\', '|']), + ]; + + pub static DVORAK: [(u8, [char; 2]); 53] = [ + (orbclient::K_ESC, ['\x1B', '\x1B']), + (orbclient::K_1, ['1', '!']), + (orbclient::K_2, ['2', '@']), + (orbclient::K_3, ['3', '#']), + (orbclient::K_4, ['4', '$']), + (orbclient::K_5, ['5', '%']), + (orbclient::K_6, ['6', '^']), + (orbclient::K_7, ['7', '&']), + (orbclient::K_8, ['8', '*']), + (orbclient::K_9, ['9', '(']), + (orbclient::K_0, ['0', ')']), + (orbclient::K_MINUS, ['[', '{']), + (orbclient::K_EQUALS, [']', '}']), + (orbclient::K_BKSP, ['\x7F', '\x7F']), + (orbclient::K_TAB, ['\t', '\t']), + (orbclient::K_Q, ['\'', '"']), + (orbclient::K_W, [',', '<']), + (orbclient::K_E, ['.', '>']), + (orbclient::K_R, ['p', 'P']), + (orbclient::K_T, ['y', 'Y']), + (orbclient::K_Y, ['f', 'F']), + (orbclient::K_U, ['g', 'G']), + (orbclient::K_I, ['c', 'C']), + (orbclient::K_O, ['r', 'R']), + (orbclient::K_P, ['l', 'L']), + (orbclient::K_BRACE_OPEN, ['/', '?']), + (orbclient::K_BRACE_CLOSE, ['=', '+']), + (orbclient::K_ENTER, ['\n', '\n']), + (orbclient::K_CTRL, ['\0', '\0']), + (orbclient::K_A, ['a', 'A']), + (orbclient::K_S, ['o', 'O']), + (orbclient::K_D, ['e', 'E']), + (orbclient::K_F, ['u', 'U']), + (orbclient::K_G, ['i', 'I']), + (orbclient::K_H, ['d', 'D']), + (orbclient::K_J, ['h', 'H']), + (orbclient::K_K, ['t', 'T']), + (orbclient::K_L, ['n', 'N']), + (orbclient::K_SEMICOLON, ['s', 'S']), + (orbclient::K_QUOTE, ['-', '_']), + (orbclient::K_TICK, ['`', '~']), + (orbclient::K_BACKSLASH, ['\\', '|']), + (orbclient::K_Z, [';', ':']), + (orbclient::K_X, ['q', 'Q']), + (orbclient::K_C, ['j', 'J']), + (orbclient::K_V, ['k', 'K']), + (orbclient::K_B, ['x', 'X']), + (orbclient::K_N, ['b', 'B']), + (orbclient::K_M, ['m', 'M']), + (orbclient::K_COMMA, ['w', 'W']), + (orbclient::K_PERIOD, ['v', 'V']), + (orbclient::K_SLASH, ['z', 'Z']), + (orbclient::K_SPACE, [' ', ' ']), + ]; + + pub static AZERTY: [(u8, [char; 2]); 53] = [ + (orbclient::K_ESC, ['\x1B', '\x1B']), + (orbclient::K_1, ['&', '1']), + (orbclient::K_2, ['é', '2']), + (orbclient::K_3, ['"', '3']), + (orbclient::K_4, ['\'', '4']), + (orbclient::K_5, ['(', '5']), + (orbclient::K_6, ['|', '6']), + (orbclient::K_7, ['è', '7']), + (orbclient::K_8, ['_', '8']), + (orbclient::K_9, ['ç', '9']), + (orbclient::K_0, ['à', '0']), + (orbclient::K_MINUS, [')', '°']), + (orbclient::K_EQUALS, ['=', '+']), + (orbclient::K_BKSP, ['\x7F', '\x7F']), + (orbclient::K_TAB, ['\t', '\t']), + (orbclient::K_Q, ['a', 'A']), + (orbclient::K_W, ['z', 'Z']), + (orbclient::K_E, ['e', 'E']), + (orbclient::K_R, ['r', 'R']), + (orbclient::K_T, ['t', 'T']), + (orbclient::K_Y, ['y', 'Y']), + (orbclient::K_U, ['u', 'U']), + (orbclient::K_I, ['i', 'I']), + (orbclient::K_O, ['o', 'O']), + (orbclient::K_P, ['p', 'P']), + (orbclient::K_BRACE_OPEN, ['^', '¨']), + (orbclient::K_BRACE_CLOSE, ['$', '£']), + (orbclient::K_ENTER, ['\n', '\n']), + (orbclient::K_CTRL, ['\0', '\0']), + (orbclient::K_A, ['q', 'Q']), + (orbclient::K_S, ['s', 'S']), + (orbclient::K_D, ['d', 'D']), + (orbclient::K_F, ['f', 'F']), + (orbclient::K_G, ['g', 'G']), + (orbclient::K_H, ['h', 'H']), + (orbclient::K_J, ['j', 'J']), + (orbclient::K_K, ['k', 'K']), + (orbclient::K_L, ['l', 'L']), + (orbclient::K_SEMICOLON, ['m', 'M']), + (orbclient::K_QUOTE, ['ù', '%']), + (orbclient::K_TICK, ['*', 'µ']), + (orbclient::K_BACKSLASH, ['ê', 'Ê']), + (orbclient::K_Z, ['w', 'W']), + (orbclient::K_X, ['x', 'X']), + (orbclient::K_C, ['c', 'C']), + (orbclient::K_V, ['v', 'V']), + (orbclient::K_B, ['b', 'B']), + (orbclient::K_N, ['n', 'N']), + (orbclient::K_M, [',', '?']), + (orbclient::K_COMMA, [';', '.']), + (orbclient::K_PERIOD, [':', '/']), + (orbclient::K_SLASH, ['!', '§']), + (orbclient::K_SPACE, [' ', ' ']), + ]; + + pub static BEPO: [(u8, [char; 2]); 53] = [ + (orbclient::K_ESC, ['\x1B', '\x1B']), + (orbclient::K_1, ['"', '1']), + (orbclient::K_2, ['«', '2']), + (orbclient::K_3, ['»', '3']), + (orbclient::K_4, ['(', '4']), + (orbclient::K_5, [')', '5']), + (orbclient::K_6, ['@', '6']), + (orbclient::K_7, ['+', '7']), + (orbclient::K_8, ['-', '8']), + (orbclient::K_9, ['/', '9']), + (orbclient::K_0, ['*', '0']), + (orbclient::K_MINUS, ['=', '°']), + (orbclient::K_EQUALS, ['%', '`']), + (orbclient::K_BKSP, ['\x7F', '\x7F']), + (orbclient::K_TAB, ['\t', '\t']), + (orbclient::K_Q, ['b', 'B']), + (orbclient::K_W, ['é', 'É']), + (orbclient::K_E, ['p', 'P']), + (orbclient::K_R, ['o', 'O']), + (orbclient::K_T, ['è', 'È']), + (orbclient::K_Y, ['^', '!']), + (orbclient::K_U, ['v', 'V']), + (orbclient::K_I, ['d', 'D']), + (orbclient::K_O, ['l', 'L']), + (orbclient::K_P, ['j', 'J']), + (orbclient::K_BRACE_OPEN, ['z', 'Z']), + (orbclient::K_BRACE_CLOSE, ['w', 'W']), + (orbclient::K_ENTER, ['\n', '\n']), + (orbclient::K_CTRL, ['\0', '\0']), + (orbclient::K_A, ['a', 'A']), + (orbclient::K_S, ['u', 'U']), + (orbclient::K_D, ['i', 'I']), + (orbclient::K_F, ['e', 'E']), + (orbclient::K_G, [',', ';']), + (orbclient::K_H, ['c', 'C']), + (orbclient::K_J, ['t', 'T']), + (orbclient::K_K, ['s', 'S']), + (orbclient::K_L, ['r', 'R']), + (orbclient::K_SEMICOLON, ['n', 'N']), + (orbclient::K_QUOTE, ['m', 'M']), + (orbclient::K_TICK, ['ç', 'Ç']), + (orbclient::K_BACKSLASH, ['ê', 'Ê']), + (orbclient::K_Z, ['à', 'À']), + (orbclient::K_X, ['y', 'Y']), + (orbclient::K_C, ['x', 'X']), + (orbclient::K_V, ['.', ':']), + (orbclient::K_B, ['k', 'K']), + (orbclient::K_N, ['\'', '?']), + (orbclient::K_M, ['q', 'Q']), + (orbclient::K_COMMA, ['g', 'G']), + (orbclient::K_PERIOD, ['h', 'H']), + (orbclient::K_SLASH, ['f', 'F']), + (orbclient::K_SPACE, [' ', ' ']), + ]; + + pub static IT: [(u8, [char; 2]); 53] = [ + (orbclient::K_ESC, ['\x1B', '\x1B']), + (orbclient::K_1, ['1', '!']), + (orbclient::K_2, ['2', '"']), + (orbclient::K_3, ['3', '£']), + (orbclient::K_4, ['4', '$']), + (orbclient::K_5, ['5', '%']), + (orbclient::K_6, ['6', '&']), + (orbclient::K_7, ['7', '/']), + (orbclient::K_8, ['8', '(']), + (orbclient::K_9, ['9', ')']), + (orbclient::K_0, ['0', '=']), + (orbclient::K_MINUS, ['?', '\'']), + (orbclient::K_EQUALS, ['ì', '^']), + (orbclient::K_BKSP, ['\x7F', '\x7F']), + (orbclient::K_TAB, ['\t', '\t']), + (orbclient::K_Q, ['q', 'Q']), + (orbclient::K_W, ['w', 'W']), + (orbclient::K_E, ['e', 'E']), + (orbclient::K_R, ['r', 'R']), + (orbclient::K_T, ['t', 'T']), + (orbclient::K_Y, ['y', 'Y']), + (orbclient::K_U, ['u', 'U']), + (orbclient::K_I, ['i', 'I']), + (orbclient::K_O, ['o', 'O']), + (orbclient::K_P, ['p', 'P']), + (orbclient::K_BRACE_OPEN, ['è', 'é']), + (orbclient::K_BRACE_CLOSE, ['+', '*']), + (orbclient::K_ENTER, ['\n', '\n']), + (orbclient::K_CTRL, ['\x20', '\x20']), + (orbclient::K_A, ['a', 'A']), + (orbclient::K_S, ['s', 'S']), + (orbclient::K_D, ['d', 'D']), + (orbclient::K_F, ['f', 'F']), + (orbclient::K_G, ['g', 'G']), + (orbclient::K_H, ['h', 'H']), + (orbclient::K_J, ['j', 'J']), + (orbclient::K_K, ['k', 'K']), + (orbclient::K_L, ['l', 'L']), + (orbclient::K_SEMICOLON, ['ò', 'ç']), + (orbclient::K_QUOTE, ['à', '°']), + (orbclient::K_TICK, ['ù', '§']), + (orbclient::K_BACKSLASH, ['<', '>']), + (orbclient::K_Z, ['z', 'Z']), + (orbclient::K_X, ['x', 'X']), + (orbclient::K_C, ['c', 'C']), + (orbclient::K_V, ['v', 'V']), + (orbclient::K_B, ['b', 'B']), + (orbclient::K_N, ['n', 'N']), + (orbclient::K_M, ['m', 'M']), + (orbclient::K_COMMA, [',', ';']), + (orbclient::K_PERIOD, ['.', ':']), + (orbclient::K_SLASH, ['-', '_']), + (orbclient::K_SPACE, [' ', ' ']), + ]; +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(usize)] +pub enum KeymapKind { + US = 0, + GB, + Dvorak, + Azerty, + Bepo, + IT, +} + +impl From for KeymapKind { + fn from(value: usize) -> Self { + if value > (KeymapKind::IT as usize) { + KeymapKind::US + } else { + // SAFETY: Checked above + unsafe { std::mem::transmute(value) } + } + } +} + +#[allow(missing_copy_implementations)] +#[derive(Debug, PartialEq, Eq)] +pub struct ParseKeymapError(()); + +impl FromStr for KeymapKind { + type Err = ParseKeymapError; + + fn from_str(s: &str) -> Result { + let keymap = match s { + "dvorak" => KeymapKind::Dvorak, + "us" => KeymapKind::US, + "gb" => KeymapKind::GB, + "azerty" => KeymapKind::Azerty, + "bepo" => KeymapKind::Bepo, + "it" => KeymapKind::IT, + &_ => return Err(ParseKeymapError(())), + }; + + Ok(keymap) + } +} + +impl Display for KeymapKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match *self { + KeymapKind::US => "us", + KeymapKind::GB => "gb", + KeymapKind::Dvorak => "dvorak", + KeymapKind::Azerty => "azerty", + KeymapKind::Bepo => "bepo", + KeymapKind::IT => "it", + }; + f.write_str(s); + Ok(()) + } +} + +pub struct KeymapData { + pub keymap_hash: HashMap, + pub kind: KeymapKind, +} + +impl KeymapData { + pub fn new(kind: KeymapKind) -> Self { + let keymap_hash = match kind { + KeymapKind::US => HashMap::from(keymaps::US), + KeymapKind::GB => HashMap::from(keymaps::GB), + KeymapKind::Dvorak => HashMap::from(keymaps::DVORAK), + KeymapKind::Azerty => HashMap::from(keymaps::AZERTY), + KeymapKind::Bepo => HashMap::from(keymaps::BEPO), + KeymapKind::IT => HashMap::from(keymaps::IT), + }; + + Self { keymap_hash, kind } + } + + pub fn get_kind(&self) -> KeymapKind { + self.kind + } + + // TODO: AltGr, Numlock + pub fn get_char(&self, scancode: u8, shift: bool) -> char { + if let Some(c) = self.keymap_hash.get(&scancode) { + if shift { + c[1] + } else { + c[0] + } + } else { + '\0' + } + } +} diff --git a/drivers/inputd/src/lib.rs b/drivers/inputd/src/lib.rs index e7e7e47fa7..5ecf8b6600 100644 --- a/drivers/inputd/src/lib.rs +++ b/drivers/inputd/src/lib.rs @@ -23,7 +23,7 @@ fn read_to_slice( } } -unsafe fn any_as_u8_slice(p: &T) -> &[u8] { +pub unsafe fn any_as_u8_slice(p: &T) -> &[u8] { slice::from_raw_parts((p as *const T) as *const u8, size_of::()) } @@ -111,10 +111,37 @@ impl ConsumerHandle { #[derive(Debug, Clone)] #[repr(C)] +pub struct ControlEvent { + pub kind: usize, + pub data: usize, +} + +impl From for ControlEvent { + fn from(value: VtActivate) -> Self { + ControlEvent { + kind: 1, + data: value.vt, + } + } +} + +impl From for ControlEvent { + fn from(value: KeymapActivate) -> Self { + ControlEvent { + kind: 2, + data: value.keymap, + } + } +} + pub struct VtActivate { pub vt: usize, } +pub struct KeymapActivate { + pub keymap: usize, +} + pub struct DisplayHandle(File); impl DisplayHandle { @@ -160,8 +187,15 @@ impl ControlHandle { Ok(Self(File::open(path)?)) } + /// Sent to Handle::Display pub fn activate_vt(&mut self, vt: usize) -> io::Result { - let cmd = VtActivate { vt }; + let cmd = ControlEvent::from(VtActivate { vt }); + self.0.write(unsafe { any_as_u8_slice(&cmd) }) + } + + /// Sent to Handle::Producer + pub fn activate_keymap(&mut self, keymap: usize) -> io::Result { + let cmd = ControlEvent::from(KeymapActivate { keymap }); self.0.write(unsafe { any_as_u8_slice(&cmd) }) } } diff --git a/drivers/inputd/src/main.rs b/drivers/inputd/src/main.rs index 92427801d5..16c2b241a9 100644 --- a/drivers/inputd/src/main.rs +++ b/drivers/inputd/src/main.rs @@ -12,13 +12,15 @@ //! events are available. use core::mem::size_of; +use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet}; use std::mem::transmute; use std::sync::atomic::{AtomicUsize, Ordering}; -use inputd::{VtActivate, VtEvent, VtEventKind}; +use inputd::{ControlEvent, VtEvent, VtEventKind}; use libredox::errno::ESTALE; +use log::warn; use redox_scheme::scheme::SchemeSync; use redox_scheme::{CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket}; @@ -26,6 +28,12 @@ use orbclient::{Event, EventOption}; use syscall::schemev2::NewFdFlags; use syscall::{Error as SysError, EventFlags, EINVAL}; +pub mod keymap; + +use keymap::KeymapKind; + +use crate::keymap::KeymapData; + enum Handle { Producer, Consumer { @@ -58,6 +66,9 @@ struct InputScheme { vts: BTreeSet, super_key: bool, active_vt: Option, + active_keymap: KeymapData, + lshift: bool, + rshift: bool, has_new_events: bool, } @@ -74,7 +85,10 @@ impl InputScheme { vts: BTreeSet::new(), super_key: false, active_vt: None, - + // TODO: configurable init? + active_keymap: KeymapData::new(KeymapKind::US), + lshift: false, + rshift: false, has_new_events: false, } } @@ -121,6 +135,20 @@ impl InputScheme { self.active_vt = Some(new_active); } + + fn switch_keymap(&mut self, new_active: usize) { + if new_active == self.active_keymap.get_kind() as usize { + return; + } + + log::debug!( + "switching from keymap #{} to keymap #{}", + self.active_keymap.get_kind(), + KeymapKind::from(new_active), + ); + + self.active_keymap = KeymapData::new(new_active.into()); + } } impl SchemeSync for InputScheme { @@ -308,15 +336,21 @@ impl SchemeSync for InputScheme { match handle { Handle::Control => { - if buf.len() != size_of::() { + if buf.len() != size_of::() { log::error!("control tried to write incorrectly sized command"); return Err(SysError::new(EINVAL)); } // SAFETY: We have verified the size of the buffer above. - let cmd = unsafe { &*buf.as_ptr().cast::() }; + let cmd = unsafe { &*buf.as_ptr().cast::() }; - self.switch_vt(cmd.vt); + match cmd.kind { + 1 => self.switch_vt(cmd.data), + 2 => self.switch_keymap(cmd.data), + k => { + log::warn!("unknown control {}", k); + } + } return Ok(buf.len()); } @@ -336,38 +370,42 @@ impl SchemeSync for InputScheme { return Ok(1); } - let events = unsafe { + let mut events = Cow::from(unsafe { core::slice::from_raw_parts( buf.as_ptr() as *const Event, buf.len() / size_of::(), ) - }; + }); - for event in events.iter() { + for i in 0..events.len() { let mut new_active_opt = None; - match event.to_option() { - EventOption::Key(key_event) => match key_event.scancode { - f @ 0x3B..=0x44 if self.super_key => { - // F1 through F10 + match events[i].to_option() { + EventOption::Key(mut key_event) => match key_event.scancode { + f @ orbclient::K_F1..=orbclient::K_F10 if self.super_key => { new_active_opt = Some((f - 0x3A) as usize); } - - 0x57 if self.super_key => { - // F11 + orbclient::K_F11 if self.super_key => { new_active_opt = Some(11); } - - 0x58 if self.super_key => { - // F12 + orbclient::K_F12 if self.super_key => { new_active_opt = Some(12); } - - 0x5B => { - // Super + orbclient::K_SUPER => { self.super_key = key_event.pressed; } + orbclient::K_LEFT_SHIFT => { + self.lshift = key_event.pressed; + } + orbclient::K_RIGHT_SHIFT => { + self.rshift = key_event.pressed; + } - _ => (), + key => { + let shift = self.lshift | self.rshift; + let ev = self.active_keymap.get_char(key, shift); + key_event.character = ev; + events.to_mut()[i] = key_event.to_event(); + } }, EventOption::Resize(resize_event) => { @@ -408,6 +446,13 @@ impl SchemeSync for InputScheme { let handle = self.handles.get_mut(&id).ok_or(SysError::new(EINVAL))?; assert!(matches!(handle, Handle::Producer)); + let buf = unsafe { + core::slice::from_raw_parts( + (events.as_ptr()) as *const u8, + events.len() * size_of::(), + ) + }; + if let Some(active_vt) = self.active_vt { for handle in self.handles.values_mut() { match handle { @@ -571,33 +616,66 @@ fn daemon_runner(daemon: daemon::Daemon) -> ! { unreachable!(); } -fn main() { - common::setup_logging( - "input", - "inputd", - "inputd", - common::output_level(), - common::file_level(), - ); +const HELP: &str = r#" +inputd [-K keymap|-A vt|--keymaps] + -A vt : set current virtual display + -K keymap : set keyboard mapping + --keymaps : list available keyboard mappings +"#; +fn main() { let mut args = std::env::args().skip(1); if let Some(val) = args.next() { + // TODO: Get current VT or keymap match val.as_ref() { // Activates a VT. "-A" => { let vt = args.next().unwrap().parse::().unwrap(); let mut handle = - inputd::ControlHandle::new().expect("inputd: failed to open display handle"); + inputd::ControlHandle::new().expect("inputd: failed to open control handle"); handle .activate_vt(vt) .expect("inputd: failed to activate VT"); } + // Activates a keymap. + "-K" => { + let vt = args + .next() + .unwrap() + .to_ascii_lowercase() + .parse::() + .expect("inputd: unrecognized keymap code (see: inputd --keymaps)"); + + let mut handle = + inputd::ControlHandle::new().expect("inputd: failed to open control handle"); + handle + .activate_keymap(vt as usize) + .expect("inputd: failed to activate keymap"); + } + // List available keymaps + "--keymaps" => { + // TODO: configurable KeymapKind using files + for key in vec!["dvorak", "us", "gb", "azerty", "bepo", "it"] { + println!("{}", key); + } + } + "--help" => { + println!("{}", HELP); + } _ => panic!("inputd: invalid argument: {}", val), } } else { + common::setup_logging( + "input", + "inputd", + "inputd", + common::output_level(), + common::file_level(), + ); + daemon::Daemon::new(daemon_runner); } }