2022-12-19 03:55:58 -08:00
|
|
|
use crate::drivers::bus::virtio::VirtioHal;
|
2023-01-07 23:35:11 +08:00
|
|
|
use crate::sync::{Condvar, UPIntrFreeCell};
|
|
|
|
use crate::task::schedule;
|
|
|
|
use alloc::collections::VecDeque;
|
2022-12-19 03:55:58 -08:00
|
|
|
use alloc::sync::Arc;
|
2022-06-18 15:23:16 +08:00
|
|
|
use core::any::Any;
|
|
|
|
use virtio_drivers::{VirtIOHeader, VirtIOInput};
|
|
|
|
|
|
|
|
const VIRTIO5: usize = 0x10005000;
|
|
|
|
const VIRTIO6: usize = 0x10006000;
|
|
|
|
|
2023-01-07 23:35:11 +08:00
|
|
|
struct VirtIOInputInner {
|
|
|
|
virtio_input: VirtIOInput<'static, VirtioHal>,
|
|
|
|
events: VecDeque<u64>,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct VirtIOInputWrapper {
|
|
|
|
inner: UPIntrFreeCell<VirtIOInputInner>,
|
2023-01-13 08:55:42 +08:00
|
|
|
condvar: Condvar,
|
2023-01-07 23:35:11 +08:00
|
|
|
}
|
2022-06-18 15:23:16 +08:00
|
|
|
|
2022-12-19 03:55:58 -08:00
|
|
|
pub trait InputDevice: Send + Sync + Any {
|
2023-01-07 23:35:11 +08:00
|
|
|
fn read_event(&self) -> u64;
|
2022-06-20 23:57:11 +08:00
|
|
|
fn handle_irq(&self);
|
2023-01-07 23:35:11 +08:00
|
|
|
fn is_empty(&self) -> bool;
|
2022-06-18 15:23:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
lazy_static::lazy_static!(
|
2022-12-19 03:55:58 -08:00
|
|
|
pub static ref KEYBOARD_DEVICE: Arc<dyn InputDevice> = Arc::new(VirtIOInputWrapper::new(VIRTIO5));
|
|
|
|
pub static ref MOUSE_DEVICE: Arc<dyn InputDevice> = Arc::new(VirtIOInputWrapper::new(VIRTIO6));
|
2022-06-18 15:23:16 +08:00
|
|
|
);
|
|
|
|
|
2022-12-19 03:55:58 -08:00
|
|
|
impl VirtIOInputWrapper {
|
2022-06-18 15:23:16 +08:00
|
|
|
pub fn new(addr: usize) -> Self {
|
2023-01-07 23:35:11 +08:00
|
|
|
let inner = VirtIOInputInner {
|
|
|
|
virtio_input: unsafe {
|
|
|
|
VirtIOInput::<VirtioHal>::new(&mut *(addr as *mut VirtIOHeader)).unwrap()
|
|
|
|
},
|
|
|
|
events: VecDeque::new(),
|
|
|
|
};
|
|
|
|
Self {
|
|
|
|
inner: unsafe { UPIntrFreeCell::new(inner) },
|
|
|
|
condvar: Condvar::new(),
|
|
|
|
}
|
2022-06-18 15:23:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-19 03:55:58 -08:00
|
|
|
impl InputDevice for VirtIOInputWrapper {
|
2023-01-07 23:35:11 +08:00
|
|
|
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);
|
2022-06-18 15:23:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-01-07 23:35:11 +08:00
|
|
|
|
|
|
|
fn handle_irq(&self) {
|
|
|
|
let mut count = 0;
|
|
|
|
let mut result = 0;
|
|
|
|
self.inner.exclusive_session(|inner| {
|
|
|
|
inner.virtio_input.ack_interrupt();
|
2023-01-13 08:55:42 +08:00
|
|
|
while let Some(event) = inner.virtio_input.pop_pending_event() {
|
2023-01-07 23:35:11 +08:00
|
|
|
count += 1;
|
|
|
|
result = (event.event_type as u64) << 48
|
|
|
|
| (event.code as u64) << 32
|
|
|
|
| (event.value) as u64;
|
|
|
|
inner.events.push_back(result);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if count > 0 {
|
|
|
|
self.condvar.signal();
|
|
|
|
};
|
|
|
|
}
|
2022-06-20 23:32:27 +08:00
|
|
|
}
|