1pub static SCANCODE_QUEUE: OnceCell<ArrayQueue<u8>> = OnceCell::uninit();
2pub static KEYBOARD_WAKER: AtomicWaker = AtomicWaker::new();
3
4pub fn add_scancode(scancode: u8) {
8 if let Ok(queue) = SCANCODE_QUEUE.try_get() {
9 if let Err(_) = queue.push(scancode) {
10 log::warn!("scancode queue full; dropping keyboard input");
11 } else {
12 KEYBOARD_WAKER.wake();
13 }
14 } else {
15 log::warn!("scancode queue uninitialised");
16 }
17}
18
19pub struct ScancodeStream {
20 _private: (),
21}
22
23impl ScancodeStream {
24 pub fn new() -> Self {
25 SCANCODE_QUEUE.try_init_once(|| ArrayQueue::new(100))
26 .expect("ScancodeStream initializer should only be called once");
27 return ScancodeStream{ _private: () };
28 }
29}
30
31impl Stream for ScancodeStream {
32 type Item = u8;
33
34 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
35 let queue = SCANCODE_QUEUE
36 .try_get()
37 .expect("scancode queue not initialized");
38
39 if let Some(scancode) = queue.pop() {
41 return Poll::Ready(Some(scancode));
42 }
43
44 KEYBOARD_WAKER.register(&cx.waker());
45 match queue.pop() {
46 Some(scancode) => {
47 KEYBOARD_WAKER.take();
48 Poll::Ready(Some(scancode))
49 }
50 None => Poll::Pending,
51 }
52 }
53}
54
55pub async fn print_keypresses() {
56 let mut scancodes = ScancodeStream::new();
57 let mut keyboard = Keyboard::new(ScancodeSet1::new(), layouts::Us104Key, HandleControl::Ignore);
58
59 while let Some(scancode) = scancodes.next().await {
60 if let Ok(Some(event)) = keyboard.add_byte(scancode) {
61 if let Some(key) = keyboard.process_keyevent(event) {
62 match key {
63 DecodedKey::Unicode(character) => print!("{}", character),
64 DecodedKey::RawKey(key) => print!("{:?}", key)
65 }
66 }
67 }
68 }
69}
70
71use {
74 crate::print,
75 core::{
76 pin::Pin,
77 task::{Context, Poll},
78 },
79 conquer_once::spin::OnceCell,
80 crossbeam_queue::ArrayQueue,
81 futures_util::{
82 stream::{Stream, StreamExt},
83 task::AtomicWaker,
84 },
85 pc_keyboard::{
86 layouts,
87 DecodedKey,
88 HandleControl,
89 Keyboard,
90 ScancodeSet1,
91 },
92};