input.rs 7.2 KB

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