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;
|
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' '),
|
||||||
|
];
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue