From 816f8746fb3936dae84672406913c2eb2c3eae52 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Fri, 20 Mar 2020 14:14:45 +0100 Subject: [PATCH] Implement a ScancodeStream type --- Cargo.lock | 30 ++++++++++++++++++++++++++++++ Cargo.toml | 5 +++++ src/main.rs | 3 ++- src/task/keyboard.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ad1356c5..67a5ba21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,6 +25,7 @@ dependencies = [ "bootloader", "conquer-once", "crossbeam-queue", + "futures-util", "lazy_static", "linked_list_allocator", "pc-keyboard", @@ -86,6 +87,29 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "futures-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" + +[[package]] +name = "futures-task" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" + +[[package]] +name = "futures-util" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" +dependencies = [ + "futures-core", + "futures-task", + "pin-utils", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -128,6 +152,12 @@ dependencies = [ "cpuio", ] +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" + [[package]] name = "scopeguard" version = "1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 39198cd9..b0d0db9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,11 @@ features = ["alloc"] version = "0.2.0" default-features = false +[dependencies.futures-util] +version = "0.3.4" +default-features = false +features = ["alloc", "async-await"] + [package.metadata.bootimage] test-args = [ "-device", "isa-debug-exit,iobase=0xf4,iosize=0x04", "-serial", "stdio", diff --git a/src/main.rs b/src/main.rs index 40da8c06..2c0448f3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ entry_point!(kernel_main); fn kernel_main(boot_info: &'static BootInfo) -> ! { use blog_os::allocator; use blog_os::memory::{self, BootInfoFrameAllocator}; - use blog_os::task::{simple_executor::SimpleExecutor, Task}; + use blog_os::task::{simple_executor::SimpleExecutor, Task, keyboard::ScancodeStream}; use x86_64::VirtAddr; println!("Hello World{}", "!"); @@ -29,6 +29,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { let mut executor = SimpleExecutor::new(); executor.spawn(Task::new(example_task())); + executor.spawn(Task::new(ScancodeStream::new().print_keypresses())); executor.run(); #[cfg(test)] diff --git a/src/task/keyboard.rs b/src/task/keyboard.rs index 68f0029a..5f394a64 100644 --- a/src/task/keyboard.rs +++ b/src/task/keyboard.rs @@ -1,4 +1,47 @@ use conquer_once::spin::OnceCell; use crossbeam_queue::ArrayQueue; +use futures_util::stream::{Stream, StreamExt}; +use core::{pin::Pin, task::{Context, Poll}}; +use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; +use crate::print; static SCANCODE_QUEUE: OnceCell> = OnceCell::uninit(); + +pub struct ScancodeStream; + +impl ScancodeStream { + pub fn new() -> Self { + SCANCODE_QUEUE.try_init_once(|| ArrayQueue::new(100)) + .expect("ScancodeStream::new should only be called once"); + ScancodeStream + } + + pub async fn print_keypresses(mut self) { + let mut keyboard = Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::Ignore); + + while let Some(scancode) = self.next().await { + if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { + if let Some(key) = keyboard.process_keyevent(key_event) { + match key { + DecodedKey::Unicode(character) => print!("{}", character), + DecodedKey::RawKey(key) => print!("{:?}", key), + } + } + } + } + } +} + +impl Stream for ScancodeStream { + type Item = u8; + + fn poll_next(self: Pin<&mut Self>, context: &mut Context) -> Poll> { + let queue = SCANCODE_QUEUE + .try_get() + .expect("scancode queue not initialized"); + match queue.pop() { + Ok(scancode) => Poll::Ready(Some(scancode)), + Err(crossbeam_queue::PopError) => Poll::Pending, + } + } +}