Skip to main content

tg_rcore_tutorial_driver/
input.rs

1/// This provides keyboard and mouse input
2
3use core::any::Any;
4use spin::Mutex;
5use virtio_drivers::{Hal, MmioTransport, VirtIOInput};
6
7use crate::{buffer::RingBuffer, clock, devices::Device};
8
9#[repr(C)]
10#[derive(Debug, Clone, Copy)]
11pub struct InputEvent {
12    pub timestamp: u64,
13    pub event_type: u16,
14    pub code: u16,
15    pub value: u32,
16}
17
18struct VirtIOInputInner<H: Hal> {
19    virtio_input: VirtIOInput<H, MmioTransport>,
20    events: RingBuffer<InputEvent, 128>, // TODO: configurable
21}
22
23pub struct VirtIOInputWrapper<H: Hal> {
24    inner: Mutex<VirtIOInputInner<H>>,
25}
26
27pub trait InputDevice: Device + Send + Sync + Any {
28    fn read_event(&self) -> Option<InputEvent>;
29    fn is_empty(&self) -> bool;
30}
31
32impl<H: Hal> VirtIOInputWrapper<H> {
33    pub fn new(transport: MmioTransport, buffer_overflow_strategy: crate::buffer::OverflowStrategy) -> Result<Self, virtio_drivers::Error> {
34        let inner = VirtIOInputInner {
35            virtio_input: VirtIOInput::new(transport)?,
36            events: RingBuffer::new(buffer_overflow_strategy),
37        };
38        Ok(Self {
39            inner: Mutex::new(inner),
40        })
41    }
42}
43
44unsafe impl<H: Hal> Send for VirtIOInputWrapper<H> {}
45unsafe impl<H: Hal> Sync for VirtIOInputWrapper<H> {}
46
47impl<H: Hal + 'static> InputDevice for VirtIOInputWrapper<H> {
48    fn is_empty(&self) -> bool {
49        self.inner.lock().events.is_empty()
50    }
51
52    fn read_event(&self) -> Option<InputEvent> {
53        self.inner.lock().events.pop()
54    }
55}
56
57impl<H: Hal + 'static> Device for VirtIOInputWrapper<H> {
58    fn handle_irq(&self) {
59        // TODO: exclusive_session?
60        let mut inner = self.inner.lock();
61
62        inner.virtio_input.ack_interrupt();
63        while let Some(event) = inner.virtio_input.pop_pending_event() {
64            let result = InputEvent {
65                timestamp: clock::get_time_us() as u64,
66                event_type: event.event_type,
67                code: event.code,
68                value: event.value
69            };
70            let _ = inner.events.push(result);
71        }
72    }
73}