keyboards are working

This commit is contained in:
husky 2025-09-11 18:06:24 -07:00
parent 3889036590
commit a65ba1e487

View file

@ -1,4 +1,11 @@
use crate::dev::virtio::{Descriptor, VirtQueue, 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, VIRTIO_MMIO_STATUS, VIRTIO_MMIO_STATUS_ACKNOWLEDGE, VIRTIO_MMIO_STATUS_DRIVER, VIRTIO_MMIO_STATUS_DRIVER_OK, VIRTIO_MMIO_STATUS_FAILED, VIRTIO_MMIO_STATUS_FEATURES_OK, VIRTIO_QUEUE_SIZE}; use core::sync::atomic::{AtomicBool, Ordering};
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,
VIRTIO_MMIO_STATUS, VIRTIO_MMIO_STATUS_ACKNOWLEDGE, VIRTIO_MMIO_STATUS_DRIVER,
VIRTIO_MMIO_STATUS_DRIVER_OK, VIRTIO_MMIO_STATUS_FAILED, VIRTIO_MMIO_STATUS_FEATURES_OK,
VIRTIO_QUEUE_SIZE, VirtQueue,
};
use crate::trafficcontrol::TrafficControl; use crate::trafficcontrol::TrafficControl;
unsafe extern "C" { unsafe extern "C" {
@ -74,7 +81,7 @@ impl VirtIoInputDevice {
// setup event queue // setup event queue
let queue_max_by_device = let queue_max_by_device =
unsafe { ((addr + VIRTIO_MMIO_QUEUE_NUM_MAX) as *const u32).read_volatile() }; unsafe { ((addr + VIRTIO_MMIO_QUEUE_NUM_MAX) as *const u32).read_volatile() };
if queue_max_by_device < VIRTIO_QUEUE_SIZE as _ { if queue_max_by_device < VIRTIO_QUEUE_SIZE as _ {
unsafe { unsafe {
((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(VIRTIO_MMIO_STATUS_FAILED); ((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(VIRTIO_MMIO_STATUS_FAILED);
@ -95,12 +102,11 @@ impl VirtIoInputDevice {
} }
} }
unsafe { unsafe {
((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile( ((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile(4096);
4096
);
} }
unsafe { unsafe {
((addr + VIRTIO_MMIO_QUEUE_PFN) as *mut u32).write_volatile(event_queue_ptr as u32 / 4096); ((addr + VIRTIO_MMIO_QUEUE_PFN) as *mut u32)
.write_volatile(event_queue_ptr as u32 / 4096);
} }
// setup status queue // setup status queue
@ -115,12 +121,11 @@ impl VirtIoInputDevice {
} }
} }
unsafe { unsafe {
((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile( ((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile(4096);
4096
);
} }
unsafe { unsafe {
((addr + VIRTIO_MMIO_QUEUE_PFN) as *mut u32).write_volatile(status_queue_ptr as u32 / 4096); ((addr + VIRTIO_MMIO_QUEUE_PFN) as *mut u32)
.write_volatile(status_queue_ptr as u32 / 4096);
} }
// all done! // all done!
@ -130,7 +135,10 @@ impl VirtIoInputDevice {
} }
let event_buffer_ptr = unsafe { let event_buffer_ptr = unsafe {
tc.memory_manager.as_mut().unwrap_unchecked().alloc_n_blocks((size_of::<Event>() * VIRTIO_INPUT_EVENTBUFFER_SIZE).div_ceil(512)) tc.memory_manager
.as_mut()
.unwrap_unchecked()
.alloc_n_blocks((size_of::<Event>() * VIRTIO_INPUT_EVENTBUFFER_SIZE).div_ceil(512))
}; };
let mut input = VirtIoInputDevice { let mut input = VirtIoInputDevice {
@ -147,7 +155,6 @@ impl VirtIoInputDevice {
input.fill_event(i); input.fill_event(i);
} }
Ok(input) Ok(input)
} }
@ -178,25 +185,44 @@ impl VirtIoInputDevice {
match event.event_type { match event.event_type {
x if x == VIRTIO_INPUT_EVENT_TYPE_KEYBOARD => { x if x == VIRTIO_INPUT_EVENT_TYPE_KEYBOARD => {
// todo: handle key events let keycode = event.code;
{ let down = event.value == 1;
let uart = crate::arch::serial_port();
if let Some(uart) = uart { // first, handle shift todo: handle more control characters
uart.putstr("keybd "); if keycode == LinuxKeycode::LeftShift as u16 || keycode == LinuxKeycode::RightShift as u16 {
uart.put_bytes(&crate::strprint::u32_hex(event.code as u32)); UPPERCASE.store(down, Ordering::Relaxed);
uart.putstr("\n"); }
// next, handle ascii characters
if !down { // write on UP
let ascii = KEYMAP_ASCII.iter().find_map(|(a, b)| {
if keycode == *a as u16 {
Some(*b)
} else {
None
}
});
if let Some(mut ascii) = ascii {
if UPPERCASE.load(Ordering::Relaxed) {
if ascii.is_ascii_alphabetic() {
ascii = ascii.to_ascii_uppercase();
} else {
// todo: handle other characters
}
}
tc.write_inbuf(ascii);
} }
} }
} }
_ => { _ => {}
}
} }
} }
// status queue // status queue
let queue = unsafe { &(*(self.status_queue as *mut VirtQueue)) }; let queue = unsafe { &(*(self.status_queue as *mut VirtQueue)) };
while self.status_queue_ack_used_idx != queue.used.idx { while self.status_queue_ack_used_idx != queue.used.idx {
let elem = &queue.used.ring[self.status_queue_ack_used_idx as usize % VIRTIO_QUEUE_SIZE]; let elem =
&queue.used.ring[self.status_queue_ack_used_idx as usize % VIRTIO_QUEUE_SIZE];
let desc = &queue.desc[elem.id as usize]; let desc = &queue.desc[elem.id as usize];
let event = unsafe { &*(desc.addr as *const Event) }; let event = unsafe { &*(desc.addr as *const Event) };
self.status_queue_ack_used_idx = self.status_queue_ack_used_idx.wrapping_add(1); self.status_queue_ack_used_idx = self.status_queue_ack_used_idx.wrapping_add(1);
@ -204,9 +230,11 @@ impl VirtIoInputDevice {
} }
} }
static UPPERCASE: AtomicBool = AtomicBool::new(false);
// linux keycodes // linux keycodes
#[repr(u32)] #[repr(u16)]
#[derive(Copy, Clone)]
pub enum LinuxKeycode { pub enum LinuxKeycode {
ESC = 1, ESC = 1,
Key1 = 2, Key1 = 2,
@ -291,4 +319,62 @@ pub enum LinuxKeycode {
KP3 = 81, KP3 = 81,
KP0 = 82, KP0 = 82,
KPDot = 83, KPDot = 83,
} }
// keys that do not map directly are handled outside of this
const KEYMAP_ASCII: &[(LinuxKeycode, u8)] = &[
(LinuxKeycode::ESC, 0x1B),
(LinuxKeycode::Key1, b'1'),
(LinuxKeycode::Key2, b'2'),
(LinuxKeycode::Key3, b'3'),
(LinuxKeycode::Key4, b'4'),
(LinuxKeycode::Key5, b'5'),
(LinuxKeycode::Key6, b'6'),
(LinuxKeycode::Key7, b'7'),
(LinuxKeycode::Key8, b'8'),
(LinuxKeycode::Key9, b'9'),
(LinuxKeycode::Key0, b'0'),
(LinuxKeycode::Minus, b'-'),
(LinuxKeycode::Equal, b'='),
(LinuxKeycode::Backspace, 0x7F),
(LinuxKeycode::Tab, 0x9),
(LinuxKeycode::Q, b'q'),
(LinuxKeycode::W, b'w'),
(LinuxKeycode::E, b'e'),
(LinuxKeycode::R, b'r'),
(LinuxKeycode::T, b't'),
(LinuxKeycode::Y, b'y'),
(LinuxKeycode::U, b'u'),
(LinuxKeycode::I, b'i'),
(LinuxKeycode::O, b'o'),
(LinuxKeycode::P, b'p'),
(LinuxKeycode::LeftBracket, b'['),
(LinuxKeycode::RightBracket, b']'),
(LinuxKeycode::Enter, b'\r'),
(LinuxKeycode::A, b'a'),
(LinuxKeycode::S, b's'),
(LinuxKeycode::D, b'd'),
(LinuxKeycode::F, b'f'),
(LinuxKeycode::G, b'g'),
(LinuxKeycode::H, b'h'),
(LinuxKeycode::J, b'j'),
(LinuxKeycode::K, b'k'),
(LinuxKeycode::L, b'l'),
(LinuxKeycode::Semicolon, b';'),
(LinuxKeycode::Apostrophe, b'\''),
(LinuxKeycode::Grave, b'`'),
(LinuxKeycode::LeftShift, b'/'),
(LinuxKeycode::Backslash, b'\\'),
(LinuxKeycode::Z, b'z'),
(LinuxKeycode::X, b'x'),
(LinuxKeycode::C, b'c'),
(LinuxKeycode::V, b'v'),
(LinuxKeycode::B, b'b'),
(LinuxKeycode::N, b'n'),
(LinuxKeycode::M, b'm'),
(LinuxKeycode::Comma, b','),
(LinuxKeycode::Dot, b'.'),
(LinuxKeycode::Slash, b'/'),
(LinuxKeycode::KPAsterisk, b'*'),
(LinuxKeycode::Space, b' '),
];