096a66adbb
I will try to focus on getting things working, as simply as possible
204 lines
5.3 KiB
Rust
204 lines
5.3 KiB
Rust
/* use core::{
|
|
pin::Pin,
|
|
task::{Context, Poll},
|
|
};
|
|
|
|
use pc_keyboard::{
|
|
DecodedKey, HandleControl, KeyCode, Keyboard, ScancodeSet1,
|
|
layouts::{self, Uk105Key},
|
|
};
|
|
use spin::{Lazy, Mutex, Once};
|
|
|
|
// static KBD_QUEUE: Once<ArrayQueue<u8>> = Once::new();
|
|
// static WAKER: AtomicWaker = AtomicWaker::new();
|
|
|
|
pub static KEYBOARD: Lazy<Mutex<Keyboard<Uk105Key, ScancodeSet1>>> = Lazy::new(|| {
|
|
Mutex::new(Keyboard::new(
|
|
ScancodeSet1::new(),
|
|
// TODO: Expose an API to change the default KB layout.
|
|
layouts::Uk105Key,
|
|
HandleControl::Ignore,
|
|
))
|
|
});
|
|
pub static SCANCODE_STREAM: Lazy<Mutex<ScancodeStream>> =
|
|
Lazy::new(|| Mutex::new(ScancodeStream::new()));
|
|
|
|
pub fn add_scancode(scancode: u8) {
|
|
if let Some(queue) = KBD_QUEUE.get() {
|
|
if queue.push(scancode).is_err() {
|
|
// println!("WARNING: scancode queue full; dropping keyboard input");
|
|
} else {
|
|
WAKER.wake();
|
|
}
|
|
} else {
|
|
// println!("WARNING: scancode queue not initialized");
|
|
}
|
|
}
|
|
|
|
pub struct ScancodeStream {
|
|
_private: (),
|
|
}
|
|
|
|
impl ScancodeStream {
|
|
pub fn new() -> Self {
|
|
KBD_QUEUE.call_once(|| ArrayQueue::new(5));
|
|
Self { _private: () }
|
|
}
|
|
|
|
pub fn try_next(&mut self) -> Option<u8> {
|
|
KBD_QUEUE.get().and_then(|queue| queue.pop())
|
|
}
|
|
}
|
|
|
|
impl Default for ScancodeStream {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Stream for ScancodeStream {
|
|
type Item = u8;
|
|
|
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
let queue = KBD_QUEUE.get().unwrap();
|
|
|
|
if let Some(scancode) = queue.pop() {
|
|
return Poll::Ready(Some(scancode));
|
|
}
|
|
|
|
WAKER.register(cx.waker());
|
|
WAKER.register(cx.waker());
|
|
|
|
queue.pop().map_or(Poll::Pending, |scancode| {
|
|
WAKER.take();
|
|
Poll::Ready(Some(scancode))
|
|
})
|
|
}
|
|
}
|
|
|
|
pub async fn get_keystroke_async() -> KeyStroke {
|
|
loop {
|
|
if let Some(scancode) = SCANCODE_STREAM.lock().next().await {
|
|
if let Ok(keystroke) = KeyStroke::try_from(scancode) {
|
|
return keystroke;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn get_keystroke_optional() -> Option<KeyStroke> {
|
|
if let Some(scancode) = SCANCODE_STREAM.lock().try_next() {
|
|
if let Ok(keystroke) = KeyStroke::try_from(scancode) {
|
|
return Some(keystroke);
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum KeyStroke {
|
|
Char(char),
|
|
Ctrl,
|
|
RCtrl,
|
|
Alt,
|
|
RAlt,
|
|
Shift,
|
|
RShift,
|
|
Meta,
|
|
RMeta,
|
|
Backspace,
|
|
Left,
|
|
Right,
|
|
Up,
|
|
Down,
|
|
None,
|
|
Enter,
|
|
Escape,
|
|
Del,
|
|
}
|
|
|
|
impl KeyStroke {
|
|
pub const fn from_keycode(key: KeyCode) -> Self {
|
|
match key {
|
|
KeyCode::LControl => Self::Ctrl,
|
|
KeyCode::RControl => Self::RCtrl,
|
|
KeyCode::LAlt => Self::Alt,
|
|
KeyCode::RAlt2 => Self::RAlt,
|
|
KeyCode::LShift => Self::Shift,
|
|
KeyCode::RShift => Self::RShift,
|
|
KeyCode::LWin => Self::Meta,
|
|
KeyCode::RWin => Self::RMeta,
|
|
KeyCode::Backspace => Self::Backspace,
|
|
KeyCode::ArrowLeft => Self::Left,
|
|
KeyCode::ArrowRight => Self::Right,
|
|
KeyCode::ArrowUp => Self::Up,
|
|
KeyCode::ArrowDown => Self::Down,
|
|
KeyCode::Return => Self::Enter,
|
|
KeyCode::Escape => Self::Escape,
|
|
KeyCode::Delete => Self::Del,
|
|
_ => Self::None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<u8> for KeyStroke {
|
|
type Error = ();
|
|
|
|
fn try_from(code: u8) -> Result<Self, Self::Error> {
|
|
let mut keyboard = KEYBOARD.lock();
|
|
|
|
let key = match keyboard.add_byte(code) {
|
|
Ok(Some(event)) => match keyboard.process_keyevent(event) {
|
|
Some(key) => key,
|
|
_ => return Err(()),
|
|
},
|
|
_ => return Err(()),
|
|
};
|
|
|
|
match key {
|
|
DecodedKey::Unicode(ch) => Ok(Self::Char(ch)),
|
|
DecodedKey::RawKey(key) => match Self::from_keycode(key) {
|
|
Self::None => Err(()),
|
|
key => Ok(key),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryInto<char> for KeyStroke {
|
|
type Error = ();
|
|
|
|
fn try_into(self) -> Result<char, Self::Error> {
|
|
match self {
|
|
Self::Char(c) => Ok(c),
|
|
_ => Err(()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl core::fmt::Display for KeyStroke {
|
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
match self {
|
|
Self::Char(c) => write!(f, "{}", c),
|
|
Self::Ctrl => write!(f, "CTRL"),
|
|
Self::RCtrl => write!(f, "RCtrl"),
|
|
Self::Alt => write!(f, "ALT"),
|
|
Self::RAlt => write!(f, "RAlt"),
|
|
Self::Shift => write!(f, "SHIFT"),
|
|
Self::RShift => write!(f, "RShift"),
|
|
Self::Meta => write!(f, "META"),
|
|
Self::RMeta => write!(f, "RMeta"),
|
|
Self::Backspace => write!(f, "BACKSPACE"),
|
|
Self::Left => write!(f, "LEFT"),
|
|
Self::Right => write!(f, "RIGHT"),
|
|
Self::Up => write!(f, "UP"),
|
|
Self::Down => write!(f, "DOWN"),
|
|
Self::Enter => write!(f, "ENTER"),
|
|
Self::Escape => write!(f, "ESCAPE"),
|
|
Self::None => write!(f, "NONE"),
|
|
Self::Del => write!(f, "DEL"),
|
|
}
|
|
}
|
|
}
|
|
*/
|