57 lines
1.7 KiB
Rust
57 lines
1.7 KiB
Rust
#![no_std]
|
|
#![forbid(unsafe_code)]
|
|
|
|
use libkos::Window;
|
|
use port_input_device::{InputDevice, InputEvent, Key};
|
|
use types::address::{ByteOffset, VirtualAddress};
|
|
|
|
const UART_VA: VirtualAddress = VirtualAddress::from_raw(0x20000);
|
|
const UART_RBR: ByteOffset = ByteOffset::new(0);
|
|
const UART_IER_OFFSET: ByteOffset = ByteOffset::new(1);
|
|
const UART_LSR_OFFSET: ByteOffset = ByteOffset::new(5);
|
|
/// IER bit: interrupt when a received byte is waiting (cleared by reading
|
|
/// it, so `acknowledge` has nothing to do).
|
|
const IER_RX_READY: u8 = 1;
|
|
|
|
/// The UART's registers, one byte each.
|
|
pub struct UartInputDevice {
|
|
regs: Window,
|
|
}
|
|
|
|
impl UartInputDevice {
|
|
/// Maps the 16550 UART whose region `mmio` names and enables its
|
|
/// receive interrupt.
|
|
pub fn new(mmio: types::bounded::CapSlot) -> Option<Self> {
|
|
let regs = libkos::device::map_mmio(mmio, UART_VA).ok()?;
|
|
regs.write(UART_IER_OFFSET, IER_RX_READY);
|
|
Some(Self { regs })
|
|
}
|
|
|
|
fn read_byte(&self) -> Option<u8> {
|
|
self.has_event().then(|| self.regs.read(UART_RBR))
|
|
}
|
|
|
|
fn byte_to_key(byte: u8) -> Key {
|
|
match byte {
|
|
b'w' | b'W' => Key::Up,
|
|
b's' | b'S' => Key::Down,
|
|
b'a' | b'A' => Key::Left,
|
|
b'd' | b'D' => Key::Right,
|
|
b'\r' | b'\n' => Key::Enter,
|
|
0x1B => Key::Escape,
|
|
c => Key::Char(c),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl InputDevice for UartInputDevice {
|
|
fn poll(&mut self) -> Option<InputEvent> {
|
|
let byte = self.read_byte()?;
|
|
Some(InputEvent::KeyDown(Self::byte_to_key(byte)))
|
|
}
|
|
|
|
fn has_event(&self) -> bool {
|
|
self.regs.read::<u8>(UART_LSR_OFFSET) & 1 != 0
|
|
}
|
|
}
|