Skip to main content

base/tasks/
keyboard.rs

1pub static SCANCODE_QUEUE: OnceCell<ArrayQueue<u8>> = OnceCell::uninit();
2pub static KEYBOARD_WAKER: AtomicWaker = AtomicWaker::new();
3
4/// Called by the keyboard interrupt handler
5///
6/// Must not block or allocate.
7pub 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      // fast path
40      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
71// IMPORTS //
72
73use {
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};