keyboards are working
This commit is contained in:
parent
3889036590
commit
a65ba1e487
1 changed files with 110 additions and 24 deletions
|
|
@ -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' '),
|
||||
];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue