Files
k-os/crates/drivers/input/uart/src/lib.rs

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
}
}