소스 검색

Add VirtIOInput::pop_pending_event(), don't pass event_buf in.

Yuekai Jia 3 년 전
부모
커밋
1d8bb3fcff
5개의 변경된 파일34개의 추가작업 그리고 69개의 파일을 삭제
  1. 1 1
      Cargo.toml
  2. 1 2
      README.md
  3. 2 2
      src/console.rs
  4. 27 63
      src/input.rs
  5. 3 1
      src/lib.rs

+ 1 - 1
Cargo.toml

@@ -10,4 +10,4 @@ description = "VirtIO guest drivers."
 [dependencies]
 volatile = "0.2"
 log = "0.4"
-bitflags = "1.2"
+bitflags = "1.3"

+ 1 - 2
README.md

@@ -2,7 +2,7 @@
 
 [![CI](https://github.com/rcore-os/virtio-drivers/workflows/CI/badge.svg?branch=master)](https://github.com/rcore-os/virtio-drivers/actions)
 
-VirtIO guest drivers in Rust. For **no_std + no_alloc** environment.
+VirtIO guest drivers in Rust. For **no_std** environment.
 
 ## Components
 
@@ -21,4 +21,3 @@ VirtIO guest drivers in Rust. For **no_std + no_alloc** environment.
 * x86_64 (TODO)
 
 * [RISCV](./examples/riscv)
-

+ 2 - 2
src/console.rs

@@ -1,7 +1,7 @@
 use super::*;
 use crate::queue::VirtQueue;
 use bitflags::*;
-use core::sync::atomic::spin_loop_hint;
+use core::hint::spin_loop;
 use log::*;
 use volatile::{ReadOnly, WriteOnly};
 
@@ -89,7 +89,7 @@ impl<'a> VirtIOConsole<'a> {
         self.transmitq.add(&[&buf], &[])?;
         self.header.notify(QUEUE_TRANSMITQ_PORT_0 as u32);
         while !self.transmitq.can_pop() {
-            spin_loop_hint();
+            spin_loop();
         }
         self.transmitq.pop_used()?;
         Ok(())

+ 27 - 63
src/input.rs

@@ -1,4 +1,5 @@
 use super::*;
+use alloc::boxed::Box;
 use bitflags::*;
 use log::*;
 use volatile::Volatile;
@@ -12,18 +13,13 @@ pub struct VirtIOInput<'a> {
     header: &'static mut VirtIOHeader,
     event_queue: VirtQueue<'a>,
     status_queue: VirtQueue<'a>,
-    event_buf: &'a mut [Event],
-    x: i32,
-    y: i32,
+    event_buf: Box<[InputEvent; 32]>,
 }
 
 impl<'a> VirtIOInput<'a> {
     /// Create a new VirtIO-Input driver.
-    pub fn new(header: &'static mut VirtIOHeader, event_buf: &'a mut [u64]) -> Result<Self> {
-        if event_buf.len() < QUEUE_SIZE {
-            return Err(Error::BufferTooSmall);
-        }
-        let event_buf: &mut [Event] = unsafe { core::mem::transmute(event_buf) };
+    pub fn new(header: &'static mut VirtIOHeader) -> Result<Self> {
+        let mut event_buf = Box::new([InputEvent::default(); QUEUE_SIZE]);
         header.begin_init(|features| {
             let features = Feature::from_bits_truncate(features);
             info!("Device features: {:?}", features);
@@ -38,7 +34,7 @@ impl<'a> VirtIOInput<'a> {
 
         let mut event_queue = VirtQueue::new(header, QUEUE_EVENT, QUEUE_SIZE as u16)?;
         let status_queue = VirtQueue::new(header, QUEUE_STATUS, QUEUE_SIZE as u16)?;
-        for (i, event) in event_buf.iter_mut().enumerate() {
+        for (i, event) in event_buf.as_mut().iter_mut().enumerate() {
             let token = event_queue.add(&[], &[event.as_buf_mut()])?;
             assert_eq!(token, i as u16);
         }
@@ -50,33 +46,24 @@ impl<'a> VirtIOInput<'a> {
             event_queue,
             status_queue,
             event_buf,
-            x: 0,
-            y: 0,
         })
     }
 
     /// Acknowledge interrupt and process events.
-    pub fn ack_interrupt(&mut self) -> Result<bool> {
-        let ack = self.header.ack_interrupt();
-        if !ack {
-            return Ok(false);
-        }
-        while let Ok((token, _)) = self.event_queue.pop_used() {
+    pub fn ack_interrupt(&mut self) -> bool {
+        self.header.ack_interrupt()
+    }
+
+    /// Pop the pending event.
+    pub fn pop_pending_event(&mut self) -> Option<InputEvent> {
+        if let Ok((token, _)) = self.event_queue.pop_used() {
             let event = &mut self.event_buf[token as usize];
-            match EventRepr::from(*event) {
-                EventRepr::RelX(dx) => self.x += dx,
-                EventRepr::RelY(dy) => self.y += dy,
-                r => warn!("{:?}", r),
-            }
             // requeue
-            self.event_queue.add(&[], &[event.as_buf_mut()])?;
+            if self.event_queue.add(&[], &[event.as_buf_mut()]).is_ok() {
+                return Some(*event);
+            }
         }
-        Ok(true)
-    }
-
-    /// Get the coordinate of mouse.
-    pub fn mouse_xy(&self) -> (i32, i32) {
-        (self.x, self.y)
+        None
     }
 }
 
@@ -121,43 +108,20 @@ struct DevIDs {
     version: u16,
 }
 
+/// Both queues use the same `virtio_input_event` struct. `type`, `code` and `value`
+/// are filled according to the Linux input layer (evdev) interface.
 #[repr(C)]
-#[derive(Clone, Copy, Default)]
-struct Event {
-    event_type: u16,
-    code: u16,
-    value: u32,
-}
-
-#[derive(Debug)]
-enum EventRepr {
-    SynReport,
-    SynUnknown(u16),
-    RelX(i32),
-    RelY(i32),
-    RelUnknown(u16),
-    Unknown(u16),
+#[derive(Clone, Copy, Debug, Default)]
+pub struct InputEvent {
+    /// Event type.
+    pub event_type: u16,
+    /// Event code.
+    pub code: u16,
+    /// Event value.
+    pub value: u32,
 }
 
-unsafe impl AsBuf for Event {}
-
-impl From<Event> for EventRepr {
-    fn from(e: Event) -> Self {
-        // linux event codes
-        match e.event_type {
-            0 => match e.code {
-                0 => EventRepr::SynReport,
-                _ => EventRepr::SynUnknown(e.code),
-            },
-            2 => match e.code {
-                0 => EventRepr::RelX(e.value as i32),
-                1 => EventRepr::RelY(e.value as i32),
-                _ => EventRepr::RelUnknown(e.code),
-            },
-            _ => EventRepr::Unknown(e.event_type),
-        }
-    }
-}
+unsafe impl AsBuf for InputEvent {}
 
 bitflags! {
     struct Feature: u64 {

+ 3 - 1
src/lib.rs

@@ -8,6 +8,8 @@
 // #[macro_use]
 extern crate log;
 
+extern crate alloc;
+
 mod blk;
 mod console;
 mod gpu;
@@ -21,7 +23,7 @@ pub use self::blk::VirtIOBlk;
 pub use self::console::VirtIOConsole;
 pub use self::gpu::VirtIOGpu;
 pub use self::header::*;
-pub use self::input::VirtIOInput;
+pub use self::input::{InputEvent, VirtIOInput};
 pub use self::net::VirtIONet;
 use self::queue::VirtQueue;
 use core::mem::size_of;