virtio/devices/
virtio_input.rs1use kernel::utilities::cells::OptionalCell;
14
15use crate::devices::{VirtIODeviceDriver, VirtIODeviceType};
16use crate::queues::split_queue::{SplitVirtqueue, SplitVirtqueueClient, VirtqueueBuffer};
17
18const EV_SYN: u16 = 0;
20const EV_KEY: u16 = 1;
22
23pub struct VirtIOInput<'a> {
25 eventq: &'a SplitVirtqueue<'static, 'static, 3>,
27 statusq: &'a SplitVirtqueue<'static, 'static, 1>,
29 status_buffer: OptionalCell<&'static mut [u8]>,
31 keys: [OptionalCell<(u16, bool)>; 2],
33 client: OptionalCell<&'a dyn kernel::hil::keyboard::KeyboardClient>,
35}
36
37impl<'a> VirtIOInput<'a> {
38 pub fn new(
39 eventq: &'a SplitVirtqueue<'static, 'static, 3>,
40 statusq: &'a SplitVirtqueue<'static, 'static, 1>,
41 status_buffer: &'static mut [u8],
42 ) -> Self {
43 eventq.enable_used_callbacks();
44
45 Self {
46 eventq,
47 statusq,
48 status_buffer: OptionalCell::new(status_buffer),
49 keys: [const { OptionalCell::empty() }; 2],
50 client: OptionalCell::empty(),
51 }
52 }
53
54 pub fn provide_buffers(
55 &self,
56 event_buffer1: &'static mut [u8],
57 event_buffer2: &'static mut [u8],
58 event_buffer3: &'static mut [u8],
59 ) {
60 let event_buffer_len = event_buffer1.len();
63 let mut buffer_chain = [Some(VirtqueueBuffer {
64 buf: event_buffer1,
65 len: event_buffer_len,
66 device_writeable: true,
67 })];
68 self.eventq.provide_buffer_chain(&mut buffer_chain).unwrap();
69
70 let event_buffer_len = event_buffer2.len();
71 let mut buffer_chain = [Some(VirtqueueBuffer {
72 buf: event_buffer2,
73 len: event_buffer_len,
74 device_writeable: true,
75 })];
76 self.eventq.provide_buffer_chain(&mut buffer_chain).unwrap();
77
78 let event_buffer_len = event_buffer3.len();
79 let mut buffer_chain = [Some(VirtqueueBuffer {
80 buf: event_buffer3,
81 len: event_buffer_len,
82 device_writeable: true,
83 })];
84 self.eventq.provide_buffer_chain(&mut buffer_chain).unwrap();
85 }
86}
87
88impl SplitVirtqueueClient<'static> for VirtIOInput<'_> {
89 fn buffer_chain_ready(
90 &self,
91 queue_number: u32,
92 buffer_chain: &mut [Option<VirtqueueBuffer<'static>>],
93 _bytes_used: usize,
94 ) {
95 fn parse_event(buf: &[u8]) -> Result<(u16, u16, u32), ()> {
96 let event_type = u16::from_le_bytes(buf.get(0..2).ok_or(())?.try_into().or(Err(()))?);
97 let event_code = u16::from_le_bytes(buf.get(2..4).ok_or(())?.try_into().or(Err(()))?);
98 let event_value = u32::from_le_bytes(buf.get(4..8).ok_or(())?.try_into().or(Err(()))?);
99 Ok((event_type, event_code, event_value))
100 }
101
102 if queue_number == self.eventq.queue_number().unwrap() {
103 let end = if let Some(event_buffer) = &buffer_chain[0] {
108 if let Ok((event_type, event_code, event_value)) = parse_event(event_buffer.buf) {
109 if event_type == EV_KEY {
110 if self.keys[0].is_none() {
113 self.keys[0].set((event_code, event_value == 1));
114 } else {
115 if self.keys[1].is_none() {
116 self.keys[1].set((event_code, event_value == 1));
117 }
118 }
119 }
120
121 event_type == EV_SYN && event_code == 0 && event_value == 0
123 } else {
124 false
125 }
126 } else {
127 false
128 };
129
130 self.eventq.provide_buffer_chain(buffer_chain).unwrap();
131
132 if end {
133 let mut key_presses: [(u16, bool); 2] = [(0, false); 2];
135 let mut length = 0;
136 self.keys[0].take().map(|key| {
137 key_presses[length] = key;
138 length += 1;
139 });
140 self.keys[1].take().map(|key| {
141 key_presses[length] = key;
142 length += 1;
143 });
144 self.client.map(|client| {
145 client.keys_pressed(&key_presses[0..length], Ok(()));
146 });
147 }
148 } else if queue_number == self.statusq.queue_number().unwrap() {
149 let status_buffer = buffer_chain[0].take().expect("No status buffer").buf;
152
153 self.status_buffer.replace(status_buffer);
154 }
155 }
156}
157
158impl VirtIODeviceDriver for VirtIOInput<'_> {
159 fn negotiate_features(&self, _offered_features: u64) -> Option<u64> {
160 Some(0)
163 }
164
165 fn device_type(&self) -> VirtIODeviceType {
166 VirtIODeviceType::InputDevice
167 }
168}
169
170impl<'a> kernel::hil::keyboard::Keyboard<'a> for VirtIOInput<'a> {
171 fn set_client(&self, client: &'a dyn kernel::hil::keyboard::KeyboardClient) {
172 self.client.set(client);
173 }
174}