|
@@ -1,4 +1,5 @@
|
|
use super::*;
|
|
use super::*;
|
|
|
|
+use alloc::boxed::Box;
|
|
use bitflags::*;
|
|
use bitflags::*;
|
|
use log::*;
|
|
use log::*;
|
|
use volatile::Volatile;
|
|
use volatile::Volatile;
|
|
@@ -12,18 +13,13 @@ pub struct VirtIOInput<'a> {
|
|
header: &'static mut VirtIOHeader,
|
|
header: &'static mut VirtIOHeader,
|
|
event_queue: VirtQueue<'a>,
|
|
event_queue: VirtQueue<'a>,
|
|
status_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> {
|
|
impl<'a> VirtIOInput<'a> {
|
|
/// Create a new VirtIO-Input driver.
|
|
/// 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| {
|
|
header.begin_init(|features| {
|
|
let features = Feature::from_bits_truncate(features);
|
|
let features = Feature::from_bits_truncate(features);
|
|
info!("Device features: {:?}", 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 mut event_queue = VirtQueue::new(header, QUEUE_EVENT, QUEUE_SIZE as u16)?;
|
|
let status_queue = VirtQueue::new(header, QUEUE_STATUS, 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()])?;
|
|
let token = event_queue.add(&[], &[event.as_buf_mut()])?;
|
|
assert_eq!(token, i as u16);
|
|
assert_eq!(token, i as u16);
|
|
}
|
|
}
|
|
@@ -50,33 +46,24 @@ impl<'a> VirtIOInput<'a> {
|
|
event_queue,
|
|
event_queue,
|
|
status_queue,
|
|
status_queue,
|
|
event_buf,
|
|
event_buf,
|
|
- x: 0,
|
|
|
|
- y: 0,
|
|
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
/// Acknowledge interrupt and process events.
|
|
/// 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];
|
|
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
|
|
// 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,
|
|
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)]
|
|
#[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! {
|
|
bitflags! {
|
|
struct Feature: u64 {
|
|
struct Feature: u64 {
|