From c3ce3724046250111776cf91596d0540ee7bc989 Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Sat, 7 Jan 2023 23:35:11 +0800 Subject: [PATCH] add get input_dev events in user app, but still have some problems --- os/Cargo.toml | 4 +- os/src/drivers/input/mod.rs | 122 +++++++++++++++++++++++++-------- os/src/main.rs | 3 +- os/src/syscall/input.rs | 17 +++++ os/src/syscall/mod.rs | 4 ++ user/src/bin/inputdev_event.rs | 21 ++++++ user/src/lib.rs | 5 ++ user/src/syscall.rs | 5 ++ 8 files changed, 151 insertions(+), 30 deletions(-) create mode 100644 os/src/syscall/input.rs create mode 100644 user/src/bin/inputdev_event.rs diff --git a/os/Cargo.toml b/os/Cargo.toml index f4b2d80c..633ec105 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -13,7 +13,9 @@ buddy_system_allocator = "0.6" bitflags = "1.2.1" xmas-elf = "0.7.0" volatile = "0.3" -virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" } +#virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "4ee80e5" } +virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "70b5850" } + easy-fs = { path = "../easy-fs" } virtio-input-decoder = "0.1.4" embedded-graphics = "0.7.1" diff --git a/os/src/drivers/input/mod.rs b/os/src/drivers/input/mod.rs index 0db76032..76c64f7c 100644 --- a/os/src/drivers/input/mod.rs +++ b/os/src/drivers/input/mod.rs @@ -1,5 +1,8 @@ use crate::drivers::bus::virtio::VirtioHal; -use crate::sync::UPIntrFreeCell; +use crate::sync::{Condvar, UPIntrFreeCell}; +use crate::task::schedule; +use alloc::collections::BTreeMap; +use alloc::collections::VecDeque; use alloc::sync::Arc; use core::any::Any; use virtio_drivers::{VirtIOHeader, VirtIOInput}; @@ -8,50 +11,113 @@ use virtio_input_decoder::{Decoder, Key, KeyType}; const VIRTIO5: usize = 0x10005000; const VIRTIO6: usize = 0x10006000; -struct VirtIOInputWrapper(UPIntrFreeCell>); +struct VirtIOInputInner { + virtio_input: VirtIOInput<'static, VirtioHal>, + events: VecDeque, +} + +struct VirtIOInputWrapper { + inner: UPIntrFreeCell, + //condvars: BTreeMap, + //condvar: Arc:: , + condvar:Condvar, +} pub trait InputDevice: Send + Sync + Any { + fn read_event(&self) -> u64; fn handle_irq(&self); + // fn events(&self) -> &VecDeque; + fn is_empty(&self) -> bool; } lazy_static::lazy_static!( pub static ref KEYBOARD_DEVICE: Arc = Arc::new(VirtIOInputWrapper::new(VIRTIO5)); pub static ref MOUSE_DEVICE: Arc = Arc::new(VirtIOInputWrapper::new(VIRTIO6)); + // pub static ref INPUT_CONDVAR: Arc:: = Arc::new(Condvar::new()); ); +// from virtio-drivers/src/input.rs +//const QUEUE_SIZE: u16 = 32; +// pub fn read_input_event() -> u64 { +// loop { + +// //let mut inner = self.inner.exclusive_access(); +// let kb=KEYBOARD_DEVICE.clone(); +// let evs = kb.events(); +// if let Some(event) = evs.pop_front() { +// return event; +// } else { +// let task_cx_ptr = INPUT_CONDVAR.clone().wait_no_sched(); +// drop(inner); +// schedule(task_cx_ptr); +// } +// } +// } impl VirtIOInputWrapper { pub fn new(addr: usize) -> Self { - Self(unsafe { - UPIntrFreeCell::new( - VirtIOInput::::new(&mut *(addr as *mut VirtIOHeader)).unwrap(), - ) - }) + let inner = VirtIOInputInner { + virtio_input: unsafe { + VirtIOInput::::new(&mut *(addr as *mut VirtIOHeader)).unwrap() + }, + events: VecDeque::new(), + }; + + // let mut condvars = BTreeMap::new(); + // let channels = QUEUE_SIZE; + // for i in 0..channels { + // let condvar = Condvar::new(); + // condvars.insert(i, condvar); + // } + + Self { + inner: unsafe { UPIntrFreeCell::new(inner) }, + //condvar: INPUT_CONDVAR.clone(), + condvar: Condvar::new(), + } } } impl InputDevice for VirtIOInputWrapper { - fn handle_irq(&self) { - let mut input = self.0.exclusive_access(); - input.ack_interrupt(); - while let Some(event) = input.pop_pending_event() { - let dtype = match Decoder::decode( - event.event_type as usize, - event.code as usize, - event.value as usize, - ) { - Ok(dtype) => dtype, - Err(_) => break, - }; - match dtype { - virtio_input_decoder::DecodeType::Key(key, r#type) => { - if r#type == KeyType::Press { - match key { - _ => {} - } - } - } - _ => {} + fn is_empty(&self) -> bool { + self.inner.exclusive_access().events.is_empty() + } + + fn read_event(&self) -> u64 { + loop { + let mut inner = self.inner.exclusive_access(); + if let Some(event) = inner.events.pop_front() { + return event; + } else { + let task_cx_ptr = self.condvar.wait_no_sched(); + drop(inner); + schedule(task_cx_ptr); } } } + + // fn events(&self) -> &VecDeque { + // &self.inner.exclusive_access().events + // } + + fn handle_irq(&self) { + let mut count = 0; + let mut result = 0; + let mut key = 0; + self.inner.exclusive_session(|inner| { + inner.virtio_input.ack_interrupt(); + while let Some((token, event)) = inner.virtio_input.pop_pending_event() { + count += 1; + key = token; + result = (event.event_type as u64) << 48 + | (event.code as u64) << 32 + | (event.value) as u64; + inner.events.push_back(result); + println!("[KERN] inputdev_handle_irq: event: {:x}", result); + } + }); + if count > 0 { + //self.condvars.get(&key).unwrap().signal(); + self.condvar.signal(); + }; + } } diff --git a/os/src/main.rs b/os/src/main.rs index a220bd72..7e5a20ac 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -3,8 +3,8 @@ #![feature(panic_info_message)] #![feature(alloc_error_handler)] +//use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE, INPUT_CONDVAR}; use crate::drivers::{GPU_DEVICE, KEYBOARD_DEVICE, MOUSE_DEVICE}; - extern crate alloc; #[macro_use] @@ -59,6 +59,7 @@ pub fn rust_main() -> ! { UART.init(); println!("KERN: init gpu"); let _gpu = GPU_DEVICE.clone(); + //let _input_condvar = INPUT_CONDVAR.clone(); println!("KERN: init keyboard"); let _keyboard = KEYBOARD_DEVICE.clone(); println!("KERN: init mouse"); diff --git a/os/src/syscall/input.rs b/os/src/syscall/input.rs new file mode 100644 index 00000000..9f59710f --- /dev/null +++ b/os/src/syscall/input.rs @@ -0,0 +1,17 @@ +//use crate::drivers::{KEYBOARD_DEVICE,MOUSE_DEVICE,INPUT_CONDVAR,read_input_event}; +use crate::drivers::{KEYBOARD_DEVICE,MOUSE_DEVICE}; + +pub fn sys_event_get() ->isize { + let kb = KEYBOARD_DEVICE.clone(); + let mouse = MOUSE_DEVICE.clone(); + //let input=INPUT_CONDVAR.clone(); + //read_input_event() as isize + if !kb.is_empty(){ + kb.read_event() as isize + } else if !mouse.is_empty() { + mouse.read_event() as isize + } else { + 0 + } + +} \ No newline at end of file diff --git a/os/src/syscall/mod.rs b/os/src/syscall/mod.rs index 3f95b94e..729caa05 100644 --- a/os/src/syscall/mod.rs +++ b/os/src/syscall/mod.rs @@ -27,18 +27,21 @@ const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_WAIT: usize = 1032; const SYSCALL_FRAMEBUFFER: usize = 2000; const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; +const SYSCALL_EVENT_GET: usize = 3000; mod fs; mod process; mod sync; mod thread; mod gui; +mod input; use fs::*; use process::*; use sync::*; use thread::*; use gui::*; +use input::*; pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { match syscall_id { @@ -71,6 +74,7 @@ pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize { SYSCALL_CONDVAR_WAIT => sys_condvar_wait(args[0], args[1]), SYSCALL_FRAMEBUFFER => sys_framebuffer(), SYSCALL_FRAMEBUFFER_FLUSH => sys_framebuffer_flush(), + SYSCALL_EVENT_GET => sys_event_get(), _ => panic!("Unsupported syscall_id: {}", syscall_id), } } diff --git a/user/src/bin/inputdev_event.rs b/user/src/bin/inputdev_event.rs new file mode 100644 index 00000000..1e5b5a10 --- /dev/null +++ b/user/src/bin/inputdev_event.rs @@ -0,0 +1,21 @@ +#![no_std] +#![no_main] + +use user_lib::{event_get}; + +#[macro_use] +extern crate user_lib; + +#[no_mangle] +pub fn main() -> i32 { + println!("Input device event test"); + let mut event=0; + for _ in 0..3 { + while event==0 { + event = event_get(); + } + println!("event: {:?}", event); + } + + 0 +} \ No newline at end of file diff --git a/user/src/lib.rs b/user/src/lib.rs index 16d4abd8..dd7261ee 100644 --- a/user/src/lib.rs +++ b/user/src/lib.rs @@ -205,6 +205,11 @@ pub fn framebuffer_flush() -> isize { sys_framebuffer_flush() } +pub fn event_get() -> isize { + sys_event_get() +} + + #[macro_export] macro_rules! vstore { ($var_ref: expr, $value: expr) => { diff --git a/user/src/syscall.rs b/user/src/syscall.rs index 330388c2..6d97b7e7 100644 --- a/user/src/syscall.rs +++ b/user/src/syscall.rs @@ -27,6 +27,7 @@ const SYSCALL_CONDVAR_SIGNAL: usize = 1031; const SYSCALL_CONDVAR_WAIT: usize = 1032; const SYSCALL_FRAMEBUFFER: usize = 2000; const SYSCALL_FRAMEBUFFER_FLUSH: usize = 2001; +const SYSCALL_EVENT_GET: usize = 3000; fn syscall(id: usize, args: [usize; 3]) -> isize { let mut ret: isize; @@ -164,4 +165,8 @@ pub fn sys_framebuffer() -> isize { pub fn sys_framebuffer_flush() -> isize { syscall(SYSCALL_FRAMEBUFFER_FLUSH, [0, 0, 0]) +} + +pub fn sys_event_get() -> isize { + syscall(SYSCALL_EVENT_GET, [0, 0, 0]) } \ No newline at end of file