input.rs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. use super::*;
  2. use crate::transport::Transport;
  3. use crate::volatile::{volread, volwrite, ReadOnly, WriteOnly};
  4. use alloc::boxed::Box;
  5. use bitflags::*;
  6. use core::ptr::NonNull;
  7. use log::*;
  8. /// Virtual human interface devices such as keyboards, mice and tablets.
  9. ///
  10. /// An instance of the virtio device represents one such input device.
  11. /// Device behavior mirrors that of the evdev layer in Linux,
  12. /// making pass-through implementations on top of evdev easy.
  13. pub struct VirtIOInput<H: Hal, T: Transport> {
  14. transport: T,
  15. event_queue: VirtQueue<H>,
  16. status_queue: VirtQueue<H>,
  17. event_buf: Box<[InputEvent; 32]>,
  18. config: NonNull<Config>,
  19. }
  20. impl<H: Hal, T: Transport> VirtIOInput<H, T> {
  21. /// Create a new VirtIO-Input driver.
  22. pub fn new(mut transport: T) -> Result<Self> {
  23. let mut event_buf = Box::new([InputEvent::default(); QUEUE_SIZE]);
  24. transport.begin_init(|features| {
  25. let features = Feature::from_bits_truncate(features);
  26. info!("Device features: {:?}", features);
  27. // negotiate these flags only
  28. let supported_features = Feature::empty();
  29. (features & supported_features).bits()
  30. });
  31. let config = transport.config_space::<Config>()?;
  32. let mut event_queue = VirtQueue::new(&mut transport, QUEUE_EVENT, QUEUE_SIZE as u16)?;
  33. let status_queue = VirtQueue::new(&mut transport, QUEUE_STATUS, QUEUE_SIZE as u16)?;
  34. for (i, event) in event_buf.as_mut().iter_mut().enumerate() {
  35. let token = event_queue.add(&[], &[event.as_buf_mut()])?;
  36. assert_eq!(token, i as u16);
  37. }
  38. transport.finish_init();
  39. Ok(VirtIOInput {
  40. transport,
  41. event_queue,
  42. status_queue,
  43. event_buf,
  44. config,
  45. })
  46. }
  47. /// Acknowledge interrupt and process events.
  48. pub fn ack_interrupt(&mut self) -> bool {
  49. self.transport.ack_interrupt()
  50. }
  51. /// Pop the pending event.
  52. pub fn pop_pending_event(&mut self) -> Option<InputEvent> {
  53. if let Ok((token, _)) = self.event_queue.pop_used() {
  54. let event = &mut self.event_buf[token as usize];
  55. // requeue
  56. if let Ok(new_token) = self.event_queue.add(&[], &[event.as_buf_mut()]) {
  57. // This only works because nothing happen between `pop_used` and `add` that affects
  58. // the list of free descriptors in the queue, so `add` reuses the descriptor which
  59. // was just freed by `pop_used`.
  60. assert_eq!(new_token, token);
  61. return Some(*event);
  62. }
  63. }
  64. None
  65. }
  66. /// Query a specific piece of information by `select` and `subsel`, and write
  67. /// result to `out`, return the result size.
  68. pub fn query_config_select(
  69. &mut self,
  70. select: InputConfigSelect,
  71. subsel: u8,
  72. out: &mut [u8],
  73. ) -> u8 {
  74. let size;
  75. let data;
  76. // Safe because config points to a valid MMIO region for the config space.
  77. unsafe {
  78. volwrite!(self.config, select, select as u8);
  79. volwrite!(self.config, subsel, subsel);
  80. size = volread!(self.config, size);
  81. data = volread!(self.config, data);
  82. }
  83. out[..size as usize].copy_from_slice(&data[..size as usize]);
  84. size
  85. }
  86. }
  87. impl<H: Hal, T: Transport> Drop for VirtIOInput<H, T> {
  88. fn drop(&mut self) {
  89. // Clear any pointers pointing to DMA regions, so the device doesn't try to access them
  90. // after they have been freed.
  91. self.transport.queue_unset(QUEUE_EVENT);
  92. self.transport.queue_unset(QUEUE_STATUS);
  93. }
  94. }
  95. /// Select value used for [`VirtIOInput::query_config_select()`].
  96. #[repr(u8)]
  97. #[derive(Debug, Clone, Copy)]
  98. pub enum InputConfigSelect {
  99. /// Returns the name of the device, in u.string. subsel is zero.
  100. IdName = 0x01,
  101. /// Returns the serial number of the device, in u.string. subsel is zero.
  102. IdSerial = 0x02,
  103. /// Returns ID information of the device, in u.ids. subsel is zero.
  104. IdDevids = 0x03,
  105. /// Returns input properties of the device, in u.bitmap. subsel is zero.
  106. /// Individual bits in the bitmap correspond to INPUT_PROP_* constants used
  107. /// by the underlying evdev implementation.
  108. PropBits = 0x10,
  109. /// subsel specifies the event type using EV_* constants in the underlying
  110. /// evdev implementation. If size is non-zero the event type is supported
  111. /// and a bitmap of supported event codes is returned in u.bitmap. Individual
  112. /// bits in the bitmap correspond to implementation-defined input event codes,
  113. /// for example keys or pointing device axes.
  114. EvBits = 0x11,
  115. /// subsel specifies the absolute axis using ABS_* constants in the underlying
  116. /// evdev implementation. Information about the axis will be returned in u.abs.
  117. AbsInfo = 0x12,
  118. }
  119. #[repr(C)]
  120. struct Config {
  121. select: WriteOnly<u8>,
  122. subsel: WriteOnly<u8>,
  123. size: ReadOnly<u8>,
  124. _reversed: [ReadOnly<u8>; 5],
  125. data: ReadOnly<[u8; 128]>,
  126. }
  127. #[repr(C)]
  128. #[derive(Debug)]
  129. struct AbsInfo {
  130. min: u32,
  131. max: u32,
  132. fuzz: u32,
  133. flat: u32,
  134. res: u32,
  135. }
  136. #[repr(C)]
  137. #[derive(Debug)]
  138. struct DevIDs {
  139. bustype: u16,
  140. vendor: u16,
  141. product: u16,
  142. version: u16,
  143. }
  144. /// Both queues use the same `virtio_input_event` struct. `type`, `code` and `value`
  145. /// are filled according to the Linux input layer (evdev) interface.
  146. #[repr(C)]
  147. #[derive(Clone, Copy, Debug, Default)]
  148. pub struct InputEvent {
  149. /// Event type.
  150. pub event_type: u16,
  151. /// Event code.
  152. pub code: u16,
  153. /// Event value.
  154. pub value: u32,
  155. }
  156. unsafe impl AsBuf for InputEvent {}
  157. bitflags! {
  158. struct Feature: u64 {
  159. // device independent
  160. const NOTIFY_ON_EMPTY = 1 << 24; // legacy
  161. const ANY_LAYOUT = 1 << 27; // legacy
  162. const RING_INDIRECT_DESC = 1 << 28;
  163. const RING_EVENT_IDX = 1 << 29;
  164. const UNUSED = 1 << 30; // legacy
  165. const VERSION_1 = 1 << 32; // detect legacy
  166. // since virtio v1.1
  167. const ACCESS_PLATFORM = 1 << 33;
  168. const RING_PACKED = 1 << 34;
  169. const IN_ORDER = 1 << 35;
  170. const ORDER_PLATFORM = 1 << 36;
  171. const SR_IOV = 1 << 37;
  172. const NOTIFICATION_DATA = 1 << 38;
  173. }
  174. }
  175. const QUEUE_EVENT: u16 = 0;
  176. const QUEUE_STATUS: u16 = 1;
  177. // a parameter that can change
  178. const QUEUE_SIZE: usize = 32;