#![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 { 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 { 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 { let byte = self.read_byte()?; Some(InputEvent::KeyDown(Self::byte_to_key(byte))) } fn has_event(&self) -> bool { self.regs.read::(UART_LSR_OFFSET) & 1 != 0 } }