diff --git a/liblbos/src/keymap.rs b/liblbos/src/keymap.rs new file mode 100644 index 0000000..bff9bb9 --- /dev/null +++ b/liblbos/src/keymap.rs @@ -0,0 +1,95 @@ +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Keymap { + pub alpha: u16, + pub beta: u32, + pub gamma: u16, + pub delta: u16, +} + +#[repr(u16)] +#[derive(Copy, Clone)] +pub enum KeymapSection { + Alpha = 1, + Beta = 2, + Gamma = 3, + Delta = 4, +} + +#[repr(u16)] +#[derive(Copy, Clone)] +pub enum KeyAlpha { + Esc = 1 << 0, + Key1 = 1 << 1, + Key2 = 1 << 2, + Key3 = 1 << 3, + Key4 = 1 << 4, + Key5 = 1 << 5, + Key6 = 1 << 6, + Key7 = 1 << 7, + Key8 = 1 << 8, + Key9 = 1 << 9, + Key0 = 1 << 10, + Minus = 1 << 11, + Equal = 1 << 12, + Backspace = 1 << 13, + Tab = 1 << 14, + Enter = 1 << 15, +} + +#[repr(u32)] +#[derive(Copy, Clone)] +pub enum KeyBeta { + A = 1 << 0, + B = 1 << 1, + C = 1 << 2, + D = 1 << 3, + E = 1 << 4, + F = 1 << 5, + G = 1 << 6, + H = 1 << 7, + I = 1 << 8, + J = 1 << 9, + K = 1 << 10, + L = 1 << 11, + M = 1 << 12, + N = 1 << 13, + O = 1 << 14, + P = 1 << 15, + Q = 1 << 16, + R = 1 << 17, + S = 1 << 18, + T = 1 << 19, + U = 1 << 20, + V = 1 << 21, + W = 1 << 22, + X = 1 << 23, + Y = 1 << 24, + Z = 1 << 25, +} + +#[repr(u16)] +#[derive(Copy, Clone)] +pub enum KeyGamma { + LeftBracket = 1 << 0, + RightBracket = 1 << 1, + Semicolon = 1 << 2, + Apostrophe = 1 << 3, + Grave = 1 << 4, + Backslash = 1 << 5, + Comma = 1 << 6, + Dot = 1 << 7, + Slash = 1 << 8, + Space = 1 << 9, + Control = 1 << 10, + Shift = 1 << 11, + Alt = 1 << 12, +} + +#[repr(u16)] +pub enum KeyDelta { + UpArrow = 1 << 0, + DownArrow = 1 << 1, + LeftArrow = 1 << 12, + RightArrow = 1 << 13, +} \ No newline at end of file diff --git a/liblbos/src/lib.rs b/liblbos/src/lib.rs index 707fad2..51de644 100644 --- a/liblbos/src/lib.rs +++ b/liblbos/src/lib.rs @@ -4,6 +4,7 @@ pub mod fs; pub mod ktask; pub mod syscalls; pub mod characters; +pub mod keymap; mod arch; #[repr(C)] diff --git a/liblbos/src/syscalls.rs b/liblbos/src/syscalls.rs index b999052..f75ac58 100644 --- a/liblbos/src/syscalls.rs +++ b/liblbos/src/syscalls.rs @@ -1,4 +1,5 @@ use crate::arch::{stall, syscall}; +use crate::keymap::Keymap; use crate::TaskSetup; #[repr(C)] @@ -80,6 +81,8 @@ pub enum SysCall { /// flushes changes done within the given rectangle to the framebuffer /// if there is no device providing a gpu, this will not do anything FlushFramebufferRect = 18, + /// fills the given struct with the current keymap info + GetCurrentKeymap = 19, /// doens't return until all other tasks besides the current task and the ktask have exited WaitUntilAlone = 333, @@ -112,6 +115,7 @@ pub fn usize2sc(u: usize) -> SysCall { 16 => SysCall::EnableFramebufferConsole, 17 => SysCall::FramebufferPointer, 18 => SysCall::FlushFramebufferRect, + 19 => SysCall::GetCurrentKeymap, 333 => SysCall::WaitUntilAlone, 666 => SysCall::InitKernel, _ => SysCall::NoAction, @@ -202,6 +206,10 @@ pub fn flush_framebuffer_rect(x: usize, y: usize, w: usize, h: usize) { syscall(SysCall::FlushFramebufferRect, x, y, w, h, 0, 0); } +pub fn get_current_keymap(keymap: &mut Keymap) { + syscall(SysCall::GetCurrentKeymap, keymap as *mut Keymap as usize, 0, 0, 0, 0, 0); +} + pub fn wait_until_alone() { syscall(SysCall::WaitUntilAlone, 0, 0, 0, 0, 0, 0); } diff --git a/src/dev/virtio/input.rs b/src/dev/virtio/input.rs index 7b788f1..9114bfd 100644 --- a/src/dev/virtio/input.rs +++ b/src/dev/virtio/input.rs @@ -1,4 +1,5 @@ use core::sync::atomic::{AtomicBool, Ordering}; +use liblbos::keymap::{KeyAlpha, KeyBeta, KeyDelta, KeyGamma, KeymapSection}; use crate::dev::virtio::{ Descriptor, VIRTIO_DESC_F_WRITE, VIRTIO_MMIO_GUEST_FEATURES, VIRTIO_MMIO_GUEST_PAGE_SIZE, VIRTIO_MMIO_QUEUE_NUM, VIRTIO_MMIO_QUEUE_NUM_MAX, VIRTIO_MMIO_QUEUE_PFN, VIRTIO_MMIO_QUEUE_SEL, @@ -187,6 +188,38 @@ impl VirtIoInputDevice { x if x == VIRTIO_INPUT_EVENT_TYPE_KEYBOARD => { let keycode = event.code; let down = event.value == 1; + + // update the TC keymap + { + let mut keymap = &mut tc.current_keymap; + if let Some(keycode) = LinuxKeycode::from_u16(keycode) { + if let Some(alpha) = keycode.to_alpha_key() { + if down { + keymap.alpha |= alpha as u16; + } else { + keymap.alpha &= !(alpha as u16); + } + } else if let Some(beta) = keycode.to_beta_key() { + if down { + keymap.beta |= beta as u32; + } else { + keymap.beta &= !(beta as u32); + } + } else if let Some(gamma) = keycode.to_gamma_key() { + if down { + keymap.gamma |= gamma as u16; + } else { + keymap.gamma &= !(gamma as u16); + } + } else if let Some(delta) = keycode.to_delta_key() { + if down { + keymap.delta |= delta as u16; + } else { + keymap.delta &= !(delta as u16); + } + } + } + } // first, handle shift todo: handle more control characters if keycode == LinuxKeycode::LeftShift as u16 || keycode == LinuxKeycode::RightShift as u16 { @@ -319,6 +352,254 @@ pub enum LinuxKeycode { KP3 = 81, KP0 = 82, KPDot = 83, + UpArrow = 103, + DownArrow = 108, + RightArrow = 106, + LeftArrow = 105, +} + +impl LinuxKeycode { + pub fn from_u16(keycode: u16) -> Option { + const KEYCODES_TO_DOT: &[LinuxKeycode] = &[ + LinuxKeycode::ESC, + LinuxKeycode::Key1, + LinuxKeycode::Key2, + LinuxKeycode::Key3, + LinuxKeycode::Key4, + LinuxKeycode::Key5, + LinuxKeycode::Key6, + LinuxKeycode::Key7, + LinuxKeycode::Key8, + LinuxKeycode::Key9, + LinuxKeycode::Key0, + LinuxKeycode::Minus, + LinuxKeycode::Equal, + LinuxKeycode::Backspace, + LinuxKeycode::Tab, + LinuxKeycode::Q, + LinuxKeycode::W, + LinuxKeycode::E, + LinuxKeycode::R, + LinuxKeycode::T, + LinuxKeycode::Y, + LinuxKeycode::U, + LinuxKeycode::I, + LinuxKeycode::O, + LinuxKeycode::P, + LinuxKeycode::LeftBracket, + LinuxKeycode::RightBracket, + LinuxKeycode::Enter, + LinuxKeycode::LeftControl, + LinuxKeycode::A, + LinuxKeycode::S, + LinuxKeycode::D, + LinuxKeycode::F, + LinuxKeycode::G, + LinuxKeycode::H, + LinuxKeycode::J, + LinuxKeycode::K, + LinuxKeycode::L, + LinuxKeycode::Semicolon, + LinuxKeycode::Apostrophe, + LinuxKeycode::Grave, + LinuxKeycode::LeftShift, + LinuxKeycode::Backslash, + LinuxKeycode::Z, + LinuxKeycode::X, + LinuxKeycode::C, + LinuxKeycode::V, + LinuxKeycode::B, + LinuxKeycode::N, + LinuxKeycode::M, + LinuxKeycode::Comma, + LinuxKeycode::Dot, + LinuxKeycode::Slash, + LinuxKeycode::RightShift, + LinuxKeycode::KPAsterisk, + LinuxKeycode::LeftAlt, + LinuxKeycode::Space, + LinuxKeycode::CapsLock, + LinuxKeycode::F1, + LinuxKeycode::F2, + LinuxKeycode::F3, + LinuxKeycode::F4, + LinuxKeycode::F5, + LinuxKeycode::F6, + LinuxKeycode::F7, + LinuxKeycode::F8, + LinuxKeycode::F9, + LinuxKeycode::F10, + LinuxKeycode::NumLock, + LinuxKeycode::ScrollLock, + LinuxKeycode::KP7, + LinuxKeycode::KP8, + LinuxKeycode::KP9, + LinuxKeycode::KPMinus, + LinuxKeycode::KP4, + LinuxKeycode::KP5, + LinuxKeycode::KP6, + LinuxKeycode::KPPlus, + LinuxKeycode::KP1, + LinuxKeycode::KP2, + LinuxKeycode::KP3, + LinuxKeycode::KP0, + LinuxKeycode::KPDot, + ]; + if keycode > 0 && keycode <= 83 { + let idx = keycode as usize - 1; + Some(KEYCODES_TO_DOT[idx]) + } else if keycode == LinuxKeycode::UpArrow as u16 { + Some(LinuxKeycode::UpArrow) + } else if keycode == LinuxKeycode::DownArrow as u16 { + Some(LinuxKeycode::DownArrow) + } else if keycode == LinuxKeycode::RightArrow as u16 { + Some(LinuxKeycode::RightArrow) + } else if keycode == LinuxKeycode::LeftArrow as u16 { + Some(LinuxKeycode::LeftArrow) + } else { + None + } + } + + pub fn is_alphabet(&self) -> bool { + // top row + (*self as u16 >= LinuxKeycode::Q as u16 && *self as u16 <= LinuxKeycode::P as u16) + || // middle row + (*self as u16 >= LinuxKeycode::A as u16 && *self as u16 <= LinuxKeycode::L as u16) + || // bottom row + (*self as u16 >= LinuxKeycode::Z as u16 && *self as u16 <= LinuxKeycode::M as u16) + } + + pub fn is_gamma(&self) -> bool { + match self { + LinuxKeycode::LeftBracket => true, + LinuxKeycode::RightBracket => true, + LinuxKeycode::Semicolon => true, + LinuxKeycode::Apostrophe => true, + LinuxKeycode::Grave => true, + LinuxKeycode::Backslash => true, + LinuxKeycode::Comma => true, + LinuxKeycode::Dot => true, + LinuxKeycode::Slash => true, + LinuxKeycode::Space => true, + LinuxKeycode::LeftControl => true, + LinuxKeycode::LeftShift => true, + LinuxKeycode::LeftAlt => true, + _ => false, + } + } + + pub fn is_delta(&self) -> bool { + match self { + LinuxKeycode::UpArrow => true, + LinuxKeycode::DownArrow => true, + LinuxKeycode::RightArrow => true, + LinuxKeycode::LeftArrow => true, + _ => false, + } + } + + pub fn to_keymap_section(&self) -> Option { + if (*self as u16 >= LinuxKeycode::ESC as u16 && *self as u16 <= LinuxKeycode::Tab as u16) || *self as u16 == LinuxKeycode::Enter as u16 { + Some(KeymapSection::Alpha) + } else if self.is_alphabet() { + Some(KeymapSection::Beta) + } else if self.is_gamma() { + Some(KeymapSection::Gamma) + } else if self.is_delta() { + Some(KeymapSection::Delta) + } else { + None + } + } + + pub fn to_alpha_key(&self) -> Option { + const KEYCODES_TO_ALPHA: &[KeyAlpha] = &[ + KeyAlpha::Esc, + KeyAlpha::Key1, + KeyAlpha::Key2, + KeyAlpha::Key3, + KeyAlpha::Key4, + KeyAlpha::Key5, + KeyAlpha::Key6, + KeyAlpha::Key7, + KeyAlpha::Key8, + KeyAlpha::Key9, + KeyAlpha::Key0, + KeyAlpha::Minus, + KeyAlpha::Equal, + KeyAlpha::Backspace, + KeyAlpha::Tab, + ]; + if *self as u16 >= LinuxKeycode::ESC as u16 && *self as u16 <= LinuxKeycode::Tab as u16 { + Some(KEYCODES_TO_ALPHA[*self as usize - 1]) + } else if *self as u16 == LinuxKeycode::Enter as u16 { + Some(KeyAlpha::Enter) + } else { + None + } + } + + pub fn to_beta_key(&self) -> Option { + match self { + LinuxKeycode::Q => Some(KeyBeta::Q), + LinuxKeycode::W => Some(KeyBeta::W), + LinuxKeycode::E => Some(KeyBeta::E), + LinuxKeycode::R => Some(KeyBeta::R), + LinuxKeycode::T => Some(KeyBeta::T), + LinuxKeycode::Y => Some(KeyBeta::Y), + LinuxKeycode::U => Some(KeyBeta::U), + LinuxKeycode::I => Some(KeyBeta::I), + LinuxKeycode::O => Some(KeyBeta::O), + LinuxKeycode::P => Some(KeyBeta::P), + LinuxKeycode::A => Some(KeyBeta::A), + LinuxKeycode::S => Some(KeyBeta::S), + LinuxKeycode::D => Some(KeyBeta::D), + LinuxKeycode::F => Some(KeyBeta::F), + LinuxKeycode::G => Some(KeyBeta::G), + LinuxKeycode::H => Some(KeyBeta::H), + LinuxKeycode::J => Some(KeyBeta::J), + LinuxKeycode::K => Some(KeyBeta::K), + LinuxKeycode::L => Some(KeyBeta::L), + LinuxKeycode::Z => Some(KeyBeta::Z), + LinuxKeycode::X => Some(KeyBeta::X), + LinuxKeycode::C => Some(KeyBeta::C), + LinuxKeycode::V => Some(KeyBeta::V), + LinuxKeycode::B => Some(KeyBeta::B), + LinuxKeycode::N => Some(KeyBeta::N), + LinuxKeycode::M => Some(KeyBeta::M), + _ => None, + } + } + + pub fn to_gamma_key(&self) -> Option { + match self { + LinuxKeycode::LeftBracket => Some(KeyGamma::LeftBracket), + LinuxKeycode::RightBracket => Some(KeyGamma::RightBracket), + LinuxKeycode::Semicolon => Some(KeyGamma::Semicolon), + LinuxKeycode::Apostrophe => Some(KeyGamma::Apostrophe), + LinuxKeycode::Grave => Some(KeyGamma::Grave), + LinuxKeycode::Backslash => Some(KeyGamma::Backslash), + LinuxKeycode::Comma => Some(KeyGamma::Comma), + LinuxKeycode::Dot => Some(KeyGamma::Dot), + LinuxKeycode::Slash => Some(KeyGamma::Slash), + LinuxKeycode::Space => Some(KeyGamma::Space), + LinuxKeycode::LeftControl => Some(KeyGamma::Control), + LinuxKeycode::LeftShift => Some(KeyGamma::Shift), + LinuxKeycode::LeftAlt => Some(KeyGamma::Alt), + _ => None, + } + } + + pub fn to_delta_key(&self) -> Option { + match self { + LinuxKeycode::UpArrow => Some(KeyDelta::UpArrow), + LinuxKeycode::DownArrow => Some(KeyDelta::DownArrow), + LinuxKeycode::RightArrow => Some(KeyDelta::RightArrow), + LinuxKeycode::LeftArrow => Some(KeyDelta::LeftArrow), + _ => None, + } + } } // keys that do not map directly are handled outside of this diff --git a/src/trafficcontrol.rs b/src/trafficcontrol.rs index 4d620f1..c441dee 100644 --- a/src/trafficcontrol.rs +++ b/src/trafficcontrol.rs @@ -1,4 +1,5 @@ use core::sync::atomic::Ordering; +use liblbos::keymap::Keymap; use liblbos::TaskSetup; use crate::arch::serial_port; use crate::memory::{BLOCK_SIZE, MemoryManager}; @@ -380,6 +381,11 @@ pub fn handle_syscall( suspend = true; 0 } + SysCall::GetCurrentKeymap => { + let keymap_ptr = unsafe { &mut *(a1 as *mut Keymap) }; + *keymap_ptr = tc.current_keymap; + 0 + } }, suspend, ) @@ -494,6 +500,7 @@ pub struct TrafficControl { pub inbuf_write: u8, pub hung_system: bool, pub use_fb_console: bool, + pub current_keymap: Keymap, } pub struct Task { @@ -528,6 +535,12 @@ impl TrafficControl { inbuf_write: 0, hung_system: false, use_fb_console: false, + current_keymap: Keymap { + alpha: 0, + beta: 0, + gamma: 0, + delta: 0, + }, } }