feat(userspace): terminal server + shell desktop; US keymap w/ shift; libkos allocator multi-page fix; panics print
This commit is contained in:
56
crates/drivers/input/virtio/src/keymap.rs
Normal file
56
crates/drivers/input/virtio/src/keymap.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
//! Linux key codes (what virtio-input reports) to keys, US layout.
|
||||
|
||||
use port_input_device::Key;
|
||||
|
||||
pub const LEFT_SHIFT: u16 = 42;
|
||||
pub const RIGHT_SHIFT: u16 = 54;
|
||||
|
||||
/// Rows of the main block: the first key's code, then each key unshifted
|
||||
/// and shifted.
|
||||
const ROWS: [(u16, &[u8], &[u8]); 4] = [
|
||||
(2, b"1234567890-=", b"!@#$%^&*()_+"),
|
||||
(16, b"qwertyuiop[]", b"QWERTYUIOP{}"),
|
||||
(30, b"asdfghjkl;'`", b"ASDFGHJKL:\"~"),
|
||||
(44, b"zxcvbnm,./", b"ZXCVBNM<>?"),
|
||||
];
|
||||
|
||||
pub fn key(code: u16, shift: bool) -> Option<Key> {
|
||||
let named = match code {
|
||||
1 => Some(Key::Escape),
|
||||
14 => Some(Key::Backspace),
|
||||
15 => Some(Key::Tab),
|
||||
28 => Some(Key::Enter),
|
||||
57 => Some(Key::Space),
|
||||
103 => Some(Key::Up),
|
||||
108 => Some(Key::Down),
|
||||
105 => Some(Key::Left),
|
||||
106 => Some(Key::Right),
|
||||
43 => Some(Key::Char(if shift { b'|' } else { b'\\' })),
|
||||
_ => None,
|
||||
};
|
||||
named.or_else(|| {
|
||||
ROWS.iter().find_map(|(first, plain, shifted)| {
|
||||
let i = usize::from(code.checked_sub(*first)?);
|
||||
let row = if shift { shifted } else { plain };
|
||||
row.get(i).map(|c| Key::Char(*c))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn letters_digits_and_shift() {
|
||||
assert_eq!(key(35, false), Some(Key::Char(b'h')));
|
||||
assert_eq!(key(35, true), Some(Key::Char(b'H')));
|
||||
assert_eq!(key(11, false), Some(Key::Char(b'0')));
|
||||
assert_eq!(key(12, true), Some(Key::Char(b'_')));
|
||||
assert_eq!(key(53, false), Some(Key::Char(b'/')));
|
||||
assert_eq!(key(41, true), Some(Key::Char(b'~')));
|
||||
assert_eq!(key(28, false), Some(Key::Enter));
|
||||
assert_eq!(key(103, false), Some(Key::Up));
|
||||
assert_eq!(key(29, false), None, "left ctrl is not a character");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
#![no_std]
|
||||
|
||||
mod keymap;
|
||||
|
||||
use hw_virtio::mmio::MmioAccess;
|
||||
use port_input_device::{InputDevice, InputEvent, Key};
|
||||
|
||||
@@ -28,6 +30,7 @@ pub struct VirtioInputDevice {
|
||||
last_used: u16,
|
||||
next_avail: u16,
|
||||
evbuf_pa: usize,
|
||||
shift: bool,
|
||||
}
|
||||
|
||||
impl VirtioInputDevice {
|
||||
@@ -45,7 +48,7 @@ impl VirtioInputDevice {
|
||||
let evbuf_pa = libkos::device::dma(1, EVBUF_VA).ok()?;
|
||||
hw_virtio::mmio::init_legacy_device(®s, vq_pa, QUEUE_SIZE as u32);
|
||||
|
||||
let mut dev = Self { last_used: 0, next_avail: 0, evbuf_pa };
|
||||
let mut dev = Self { last_used: 0, next_avail: 0, evbuf_pa, shift: false };
|
||||
dev.fill_queue();
|
||||
Some(dev)
|
||||
}
|
||||
@@ -118,25 +121,6 @@ impl VirtioInputDevice {
|
||||
}
|
||||
}
|
||||
|
||||
fn linux_keycode_to_key(code: u16) -> Option<Key> {
|
||||
match code {
|
||||
17 => Some(Key::Up), // KEY_W
|
||||
31 => Some(Key::Down), // KEY_S
|
||||
30 => Some(Key::Left), // KEY_A
|
||||
32 => Some(Key::Right), // KEY_D
|
||||
103 => Some(Key::Up), // KEY_UP
|
||||
108 => Some(Key::Down), // KEY_DOWN
|
||||
105 => Some(Key::Left), // KEY_LEFT
|
||||
106 => Some(Key::Right),// KEY_RIGHT
|
||||
28 => Some(Key::Enter), // KEY_ENTER
|
||||
1 => Some(Key::Escape), // KEY_ESC
|
||||
57 => Some(Key::Space), // KEY_SPACE
|
||||
14 => Some(Key::Backspace), // KEY_BACKSPACE
|
||||
15 => Some(Key::Tab), // KEY_TAB
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
impl InputDevice for VirtioInputDevice {
|
||||
fn poll(&mut self) -> Option<InputEvent> {
|
||||
loop {
|
||||
@@ -151,8 +135,12 @@ impl InputDevice for VirtioInputDevice {
|
||||
let (ev_type, ev_code, ev_value) = self.read_event(desc_idx);
|
||||
self.resubmit(desc_idx);
|
||||
|
||||
if ev_type == EV_KEY && matches!(ev_code, keymap::LEFT_SHIFT | keymap::RIGHT_SHIFT) {
|
||||
self.shift = ev_value != 0;
|
||||
continue;
|
||||
}
|
||||
if ev_type == EV_KEY {
|
||||
if let Some(key) = linux_keycode_to_key(ev_code) {
|
||||
if let Some(key) = keymap::key(ev_code, self.shift) {
|
||||
if ev_value == KEY_PRESS {
|
||||
return Some(InputEvent::KeyDown(key));
|
||||
} else if ev_value == 0 {
|
||||
|
||||
Reference in New Issue
Block a user