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;
unsafe extern "C" {
@ -95,12 +102,11 @@ impl VirtIoInputDevice {
}
}
unsafe {
((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile(
4096
);
((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile(4096);
}
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
@ -115,12 +121,11 @@ impl VirtIoInputDevice {
}
}
unsafe {
((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile(
4096
);
((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile(4096);
}
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!
@ -130,7 +135,10 @@ impl VirtIoInputDevice {
}
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 {
@ -147,7 +155,6 @@ impl VirtIoInputDevice {
input.fill_event(i);
}
Ok(input)
}
@ -178,25 +185,44 @@ impl VirtIoInputDevice {
match event.event_type {
x if x == VIRTIO_INPUT_EVENT_TYPE_KEYBOARD => {
// todo: handle key events
{
let uart = crate::arch::serial_port();
if let Some(uart) = uart {
uart.putstr("keybd ");
uart.put_bytes(&crate::strprint::u32_hex(event.code as u32));
uart.putstr("\n");
let keycode = event.code;
let down = event.value == 1;
// first, handle shift todo: handle more control characters
if keycode == LinuxKeycode::LeftShift as u16 || keycode == LinuxKeycode::RightShift as u16 {
UPPERCASE.store(down, Ordering::Relaxed);
}
// 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
let queue = unsafe { &(*(self.status_queue as *mut VirtQueue)) };
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 event = unsafe { &*(desc.addr as *const Event) };
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
#[repr(u32)]
#[repr(u16)]
#[derive(Copy, Clone)]
pub enum LinuxKeycode {
ESC = 1,
Key1 = 2,
@ -292,3 +320,61 @@ pub enum LinuxKeycode {
KP0 = 82,
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' '),
];