1use super::common::Feature;
4use crate::hal::Hal;
5use crate::queue::VirtQueue;
6use crate::transport::Transport;
7use crate::volatile::{volread, volwrite, ReadOnly, VolatileReadable, WriteOnly};
8use crate::Error;
9use alloc::{boxed::Box, string::String};
10use core::cmp::min;
11use core::mem::size_of;
12use core::ptr::{addr_of, NonNull};
13use zerocopy::{AsBytes, FromBytes, FromZeroes};
14
15pub struct VirtIOInput<H: Hal, T: Transport> {
21 transport: T,
22 event_queue: VirtQueue<H, QUEUE_SIZE>,
23 status_queue: VirtQueue<H, QUEUE_SIZE>,
24 event_buf: Box<[InputEvent; 32]>,
25 config: NonNull<Config>,
26}
27
28impl<H: Hal, T: Transport> VirtIOInput<H, T> {
29 pub fn new(mut transport: T) -> Result<Self, Error> {
31 let mut event_buf = Box::new([InputEvent::default(); QUEUE_SIZE]);
32
33 let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
34
35 let config = transport.config_space::<Config>()?;
36
37 let mut event_queue = VirtQueue::new(
38 &mut transport,
39 QUEUE_EVENT,
40 negotiated_features.contains(Feature::RING_INDIRECT_DESC),
41 negotiated_features.contains(Feature::RING_EVENT_IDX),
42 )?;
43 let status_queue = VirtQueue::new(
44 &mut transport,
45 QUEUE_STATUS,
46 negotiated_features.contains(Feature::RING_INDIRECT_DESC),
47 negotiated_features.contains(Feature::RING_EVENT_IDX),
48 )?;
49 for (i, event) in event_buf.as_mut().iter_mut().enumerate() {
50 let token = unsafe { event_queue.add(&[], &mut [event.as_bytes_mut()])? };
52 assert_eq!(token, i as u16);
53 }
54 if event_queue.should_notify() {
55 transport.notify(QUEUE_EVENT);
56 }
57
58 transport.finish_init();
59
60 Ok(VirtIOInput {
61 transport,
62 event_queue,
63 status_queue,
64 event_buf,
65 config,
66 })
67 }
68
69 pub fn ack_interrupt(&mut self) -> bool {
71 self.transport.ack_interrupt()
72 }
73
74 pub fn pop_pending_event(&mut self) -> Option<InputEvent> {
76 if let Some(token) = self.event_queue.peek_used() {
77 let event = &mut self.event_buf[token as usize];
78 unsafe {
81 self.event_queue
82 .pop_used(token, &[], &mut [event.as_bytes_mut()])
83 .ok()?;
84 }
85 let event_saved = *event;
86 if let Ok(new_token) = unsafe { self.event_queue.add(&[], &mut [event.as_bytes_mut()]) }
89 {
90 assert_eq!(new_token, token);
94 if self.event_queue.should_notify() {
95 self.transport.notify(QUEUE_EVENT);
96 }
97 return Some(event_saved);
98 }
99 }
100 None
101 }
102
103 pub fn query_config_select(
106 &mut self,
107 select: InputConfigSelect,
108 subsel: u8,
109 out: &mut [u8],
110 ) -> u8 {
111 let size;
112 unsafe {
114 volwrite!(self.config, select, select as u8);
115 volwrite!(self.config, subsel, subsel);
116 size = volread!(self.config, size);
117 let size_to_copy = min(usize::from(size), out.len());
118 for (i, out_item) in out.iter_mut().take(size_to_copy).enumerate() {
119 *out_item = addr_of!((*self.config.as_ptr()).data[i]).vread();
120 }
121 }
122 size
123 }
124
125 fn query_config_select_alloc(
128 &mut self,
129 select: InputConfigSelect,
130 subsel: u8,
131 ) -> Result<Box<[u8]>, Error> {
132 unsafe {
134 volwrite!(self.config, select, select as u8);
135 volwrite!(self.config, subsel, subsel);
136 let size = usize::from(volread!(self.config, size));
137 if size > CONFIG_DATA_MAX_LENGTH {
138 return Err(Error::IoError);
139 }
140 let mut buf = u8::new_box_slice_zeroed(size);
141 for i in 0..size {
142 buf[i] = addr_of!((*self.config.as_ptr()).data[i]).vread();
143 }
144 Ok(buf)
145 }
146 }
147
148 fn query_config_string(
153 &mut self,
154 select: InputConfigSelect,
155 subsel: u8,
156 ) -> Result<String, Error> {
157 Ok(String::from_utf8(
158 self.query_config_select_alloc(select, subsel)?.into(),
159 )?)
160 }
161
162 pub fn name(&mut self) -> Result<String, Error> {
164 self.query_config_string(InputConfigSelect::IdName, 0)
165 }
166
167 pub fn serial_number(&mut self) -> Result<String, Error> {
169 self.query_config_string(InputConfigSelect::IdSerial, 0)
170 }
171
172 pub fn ids(&mut self) -> Result<DevIDs, Error> {
174 let mut ids = DevIDs::default();
175 let size = self.query_config_select(InputConfigSelect::IdDevids, 0, ids.as_bytes_mut());
176 if usize::from(size) == size_of::<DevIDs>() {
177 Ok(ids)
178 } else {
179 Err(Error::IoError)
180 }
181 }
182
183 pub fn prop_bits(&mut self) -> Result<Box<[u8]>, Error> {
185 self.query_config_select_alloc(InputConfigSelect::PropBits, 0)
186 }
187
188 pub fn ev_bits(&mut self, event_type: u8) -> Result<Box<[u8]>, Error> {
192 self.query_config_select_alloc(InputConfigSelect::EvBits, event_type)
193 }
194
195 pub fn abs_info(&mut self, axis: u8) -> Result<AbsInfo, Error> {
197 let mut info = AbsInfo::default();
198 let size = self.query_config_select(InputConfigSelect::AbsInfo, axis, info.as_bytes_mut());
199 if usize::from(size) == size_of::<AbsInfo>() {
200 Ok(info)
201 } else {
202 Err(Error::IoError)
203 }
204 }
205}
206
207unsafe impl<H: Hal, T: Transport + Send> Send for VirtIOInput<H, T> where
209 VirtQueue<H, QUEUE_SIZE>: Send
210{
211}
212
213unsafe impl<H: Hal, T: Transport + Sync> Sync for VirtIOInput<H, T> where
215 VirtQueue<H, QUEUE_SIZE>: Sync
216{
217}
218
219impl<H: Hal, T: Transport> Drop for VirtIOInput<H, T> {
220 fn drop(&mut self) {
221 self.transport.queue_unset(QUEUE_EVENT);
224 self.transport.queue_unset(QUEUE_STATUS);
225 }
226}
227
228const CONFIG_DATA_MAX_LENGTH: usize = 128;
229
230#[repr(u8)]
232#[derive(Debug, Clone, Copy)]
233pub enum InputConfigSelect {
234 IdName = 0x01,
236 IdSerial = 0x02,
238 IdDevids = 0x03,
240 PropBits = 0x10,
244 EvBits = 0x11,
250 AbsInfo = 0x12,
253}
254
255#[repr(C)]
256struct Config {
257 select: WriteOnly<u8>,
258 subsel: WriteOnly<u8>,
259 size: ReadOnly<u8>,
260 _reserved: [ReadOnly<u8>; 5],
261 data: [ReadOnly<u8>; CONFIG_DATA_MAX_LENGTH],
262}
263
264#[repr(C)]
266#[derive(AsBytes, Clone, Debug, Default, Eq, PartialEq, FromBytes, FromZeroes)]
267pub struct AbsInfo {
268 pub min: u32,
270 pub max: u32,
272 pub fuzz: u32,
274 pub flat: u32,
276 pub res: u32,
278}
279
280#[repr(C)]
282#[derive(AsBytes, Clone, Debug, Default, Eq, PartialEq, FromBytes, FromZeroes)]
283pub struct DevIDs {
284 pub bustype: u16,
286 pub vendor: u16,
288 pub product: u16,
290 pub version: u16,
292}
293
294#[repr(C)]
297#[derive(AsBytes, Clone, Copy, Debug, Default, FromBytes, FromZeroes)]
298pub struct InputEvent {
299 pub event_type: u16,
301 pub code: u16,
303 pub value: u32,
305}
306
307const QUEUE_EVENT: u16 = 0;
308const QUEUE_STATUS: u16 = 1;
309const SUPPORTED_FEATURES: Feature = Feature::RING_EVENT_IDX.union(Feature::RING_INDIRECT_DESC);
310
311const QUEUE_SIZE: usize = 32;
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317 use crate::{
318 hal::fake::FakeHal,
319 transport::{
320 fake::{FakeTransport, QueueStatus, State},
321 DeviceType,
322 },
323 };
324 use alloc::{sync::Arc, vec};
325 use core::convert::TryInto;
326 use std::sync::Mutex;
327
328 #[test]
329 fn config() {
330 const DEFAULT_DATA: ReadOnly<u8> = ReadOnly::new(0);
331 let mut config_space = Config {
332 select: WriteOnly::default(),
333 subsel: WriteOnly::default(),
334 size: ReadOnly::new(0),
335 _reserved: Default::default(),
336 data: [DEFAULT_DATA; 128],
337 };
338 let state = Arc::new(Mutex::new(State {
339 queues: vec![QueueStatus::default(), QueueStatus::default()],
340 ..Default::default()
341 }));
342 let transport = FakeTransport {
343 device_type: DeviceType::Block,
344 max_queue_size: QUEUE_SIZE.try_into().unwrap(),
345 device_features: 0,
346 config_space: NonNull::from(&mut config_space),
347 state: state.clone(),
348 };
349 let mut input = VirtIOInput::<FakeHal, FakeTransport<Config>>::new(transport).unwrap();
350
351 set_data(&mut config_space, "Test input device".as_bytes());
352 assert_eq!(input.name().unwrap(), "Test input device");
353 assert_eq!(config_space.select.0, InputConfigSelect::IdName as u8);
354 assert_eq!(config_space.subsel.0, 0);
355
356 set_data(&mut config_space, "Serial number".as_bytes());
357 assert_eq!(input.serial_number().unwrap(), "Serial number");
358 assert_eq!(config_space.select.0, InputConfigSelect::IdSerial as u8);
359 assert_eq!(config_space.subsel.0, 0);
360
361 let ids = DevIDs {
362 bustype: 0x4242,
363 product: 0x0067,
364 vendor: 0x1234,
365 version: 0x4321,
366 };
367 set_data(&mut config_space, ids.as_bytes());
368 assert_eq!(input.ids().unwrap(), ids);
369 assert_eq!(config_space.select.0, InputConfigSelect::IdDevids as u8);
370 assert_eq!(config_space.subsel.0, 0);
371
372 set_data(&mut config_space, &[0x12, 0x34, 0x56]);
373 assert_eq!(input.prop_bits().unwrap().as_ref(), &[0x12, 0x34, 0x56]);
374 assert_eq!(config_space.select.0, InputConfigSelect::PropBits as u8);
375 assert_eq!(config_space.subsel.0, 0);
376
377 set_data(&mut config_space, &[0x42, 0x66]);
378 assert_eq!(input.ev_bits(3).unwrap().as_ref(), &[0x42, 0x66]);
379 assert_eq!(config_space.select.0, InputConfigSelect::EvBits as u8);
380 assert_eq!(config_space.subsel.0, 3);
381
382 let abs_info = AbsInfo {
383 min: 12,
384 max: 1234,
385 fuzz: 4,
386 flat: 10,
387 res: 2,
388 };
389 set_data(&mut config_space, abs_info.as_bytes());
390 assert_eq!(input.abs_info(5).unwrap(), abs_info);
391 assert_eq!(config_space.select.0, InputConfigSelect::AbsInfo as u8);
392 assert_eq!(config_space.subsel.0, 5);
393 }
394
395 fn set_data(config_space: &mut Config, value: &[u8]) {
396 config_space.size.0 = value.len().try_into().unwrap();
397 for (i, &byte) in value.into_iter().enumerate() {
398 config_space.data[i].0 = byte;
399 }
400 }
401}