1extern crate alloc;
10
11use alloc::boxed::Box;
12use alloc::string::ToString;
13use alloc::sync::Arc;
14use alloc::vec;
15use alloc::vec::Vec;
16use core::mem::size_of;
17use spin::Mutex;
18
19use crate::device::input::event_device::EventDevice;
20use crate::device::manager::DeviceManager;
21use crate::drivers::virtio::device::{DeviceStatus, Register, VirtioDevice};
22use crate::drivers::virtio::queue::{DescriptorFlag, VirtQueue};
23use crate::early_println;
24
25#[repr(C)]
27#[derive(Debug, Clone, Copy, Default)]
28struct VirtioInputEvent {
29 type_: u16,
30 code: u16,
31 value: i32,
32}
33
34impl VirtioInputEvent {
35 const fn size() -> usize {
36 size_of::<Self>()
37 }
38}
39
40#[repr(C)]
42#[derive(Debug, Clone, Copy)]
43struct VirtioInputConfig {
44 select: u8,
45 subsel: u8,
46 size: u8,
47 reserved: [u8; 5],
48 data: [u8; 128],
49}
50
51mod config_select {
53 pub const VIRTIO_INPUT_CFG_UNSET: u8 = 0x00;
54 pub const VIRTIO_INPUT_CFG_ID_NAME: u8 = 0x01;
55 pub const VIRTIO_INPUT_CFG_ID_SERIAL: u8 = 0x02;
56 pub const VIRTIO_INPUT_CFG_ID_DEVIDS: u8 = 0x03;
57 pub const VIRTIO_INPUT_CFG_PROP_BITS: u8 = 0x10;
58 pub const VIRTIO_INPUT_CFG_EV_BITS: u8 = 0x11;
59 pub const VIRTIO_INPUT_CFG_ABS_INFO: u8 = 0x12;
60}
61
62pub struct VirtioInputDevice {
64 base_addr: usize,
65 eventq: Mutex<VirtQueue<'static>>, statusq: Mutex<VirtQueue<'static>>, event_device: Arc<EventDevice>,
68 initialized: Mutex<bool>,
69 event_buffers: Mutex<Vec<Box<[u8]>>>,
70 interrupt_id: Mutex<Option<u32>>,
71}
72
73impl VirtioInputDevice {
74 fn read8_config(&self, offset: usize) -> u8 {
76 unsafe {
77 let addr = self.base_addr + Register::DeviceConfig as usize + offset;
78 core::ptr::read_volatile(addr as *const u8)
79 }
80 }
81
82 fn write8_config(&self, offset: usize, value: u8) {
84 unsafe {
85 let addr = self.base_addr + Register::DeviceConfig as usize + offset;
86 core::ptr::write_volatile(addr as *mut u8, value);
87 }
88 }
89
90 fn read_device_name(&self) -> Option<alloc::string::String> {
92 use config_select::*;
93
94 self.write8_config(0, VIRTIO_INPUT_CFG_ID_NAME);
96 self.write8_config(1, 0); let size = self.read8_config(2);
100 if size == 0 || size > 128 {
101 return None;
102 }
103
104 let mut name_bytes = alloc::vec::Vec::new();
106 for i in 0..size {
107 let byte = self.read8_config(8 + i as usize);
108 if byte == 0 {
109 break;
110 }
111 name_bytes.push(byte);
112 }
113
114 alloc::string::String::from_utf8(name_bytes).ok()
115 }
116
117 fn determine_device_type(name: &str) -> &'static str {
119 let name_lower = name.to_lowercase();
120 if name_lower.contains("keyboard") || name_lower.contains("kbd") {
121 "keyboard"
122 } else if name_lower.contains("mouse") {
123 "mouse"
124 } else if name_lower.contains("tablet") {
125 "tablet"
126 } else {
127 "input"
128 }
129 }
130
131 pub fn new(base_addr: usize) -> Self {
141 let temp_device = Self {
143 base_addr,
144 eventq: Mutex::new(VirtQueue::new(8)),
145 statusq: Mutex::new(VirtQueue::new(8)),
146 event_device: Arc::new(EventDevice::new("input")),
147 initialized: Mutex::new(false),
148 event_buffers: Mutex::new(Vec::new()),
149 interrupt_id: Mutex::new(None),
150 };
151
152 let virtio_name = temp_device
154 .read_device_name()
155 .unwrap_or_else(|| "Unknown Device".to_string());
156
157 let device_type = Self::determine_device_type(&virtio_name);
159
160 early_println!(
161 "[virtio-input] Device at {:#x}: \"{}\"",
162 base_addr,
163 virtio_name
164 );
165
166 let event_device = Arc::new(EventDevice::new(device_type));
168 let device_name = event_device.get_name();
169
170 early_println!("[virtio-input] Registered as /dev/{}", device_name);
171
172 let mut device = Self {
173 base_addr,
174 eventq: Mutex::new(VirtQueue::new(8)),
175 statusq: Mutex::new(VirtQueue::new(8)),
176 event_device: event_device.clone(),
177 initialized: Mutex::new(false),
178 event_buffers: Mutex::new(Vec::new()),
179 interrupt_id: Mutex::new(None),
180 };
181
182 if let Err(e) = device.init() {
184 panic!("[virtio-input] Failed to initialize: {}", e);
185 }
186
187 DeviceManager::get_manager()
189 .register_device_with_name(device_name.to_string(), event_device);
190
191 early_println!("[virtio-input] Device initialized successfully");
192
193 device
194 }
195
196 fn init(&mut self) -> Result<(), &'static str> {
198 self.write32_register(Register::Status, 0);
200
201 let mut status = 0u32;
203 DeviceStatus::Acknowledge.set(&mut status);
204 self.write32_register(Register::Status, status);
205
206 DeviceStatus::Driver.set(&mut status);
208 self.write32_register(Register::Status, status);
209
210 self.write32_register(Register::DeviceFeaturesSel, 0);
212 let _device_features = self.read32_register(Register::DeviceFeatures);
213
214 self.write32_register(Register::DriverFeaturesSel, 0);
216 self.write32_register(Register::DriverFeatures, 0);
217
218 DeviceStatus::FeaturesOK.set(&mut status);
220 self.write32_register(Register::Status, status);
221
222 let status_readback = self.read32_register(Register::Status);
224 if !DeviceStatus::FeaturesOK.is_set(status_readback) {
225 return Err("Device rejected features");
226 }
227
228 self.setup_queues()?;
230
231 DeviceStatus::DriverOK.set(&mut status);
233 self.write32_register(Register::Status, status);
234
235 self.prefill_event_queue()?;
237
238 *self.initialized.lock() = true;
239
240 Ok(())
241 }
242
243 fn setup_queues(&mut self) -> Result<(), &'static str> {
245 self.write32_register(Register::QueueSel, 0);
247 let max_queue_size = self.read32_register(Register::QueueNumMax);
248
249 if max_queue_size == 0 {
250 return Err("Event queue not available");
251 }
252
253 let queue_size = core::cmp::min(max_queue_size, 8);
254 self.write32_register(Register::QueueNum, queue_size);
255
256 let mut eventq = self.eventq.lock();
258 eventq.init();
259
260 let desc_addr = eventq.get_raw_ptr() as u64;
262 let driver_addr = eventq.avail.flags as *const _ as u64;
263 let device_addr = eventq.used.flags as *const _ as u64;
264
265 self.write32_register(Register::QueueDescLow, desc_addr as u32);
266 self.write32_register(Register::QueueDescHigh, (desc_addr >> 32) as u32);
267 self.write32_register(Register::DriverDescLow, driver_addr as u32);
268 self.write32_register(Register::DriverDescHigh, (driver_addr >> 32) as u32);
269 self.write32_register(Register::DeviceDescLow, device_addr as u32);
270 self.write32_register(Register::DeviceDescHigh, (device_addr >> 32) as u32);
271
272 self.write32_register(Register::QueueReady, 1);
273
274 drop(eventq);
275
276 self.write32_register(Register::QueueSel, 1);
278 let status_max = self.read32_register(Register::QueueNumMax);
279 if status_max > 0 {
280 let status_size = core::cmp::min(status_max, 8);
281 self.write32_register(Register::QueueNum, status_size);
282
283 let mut statusq = self.statusq.lock();
284 statusq.init();
285
286 let desc_addr = statusq.get_raw_ptr() as u64;
287 let driver_addr = statusq.avail.flags as *const _ as u64;
288 let device_addr = statusq.used.flags as *const _ as u64;
289
290 self.write32_register(Register::QueueDescLow, desc_addr as u32);
291 self.write32_register(Register::QueueDescHigh, (desc_addr >> 32) as u32);
292 self.write32_register(Register::DriverDescLow, driver_addr as u32);
293 self.write32_register(Register::DriverDescHigh, (driver_addr >> 32) as u32);
294 self.write32_register(Register::DeviceDescLow, device_addr as u32);
295 self.write32_register(Register::DeviceDescHigh, (device_addr >> 32) as u32);
296
297 self.write32_register(Register::QueueReady, 1);
298 }
299
300 Ok(())
301 }
302
303 fn prefill_event_queue(&mut self) -> Result<(), &'static str> {
305 let queue_size = 8;
306 let mut buffers = self.event_buffers.lock();
307 let mut eventq = self.eventq.lock();
308
309 for _ in 0..queue_size {
310 let buffer: Box<[u8]> = vec![0u8; VirtioInputEvent::size()].into_boxed_slice();
312 let buffer_ptr = Box::into_raw(buffer);
313 let buffer_addr = buffer_ptr as *mut u8 as usize;
314
315 let desc_idx = eventq
317 .alloc_desc()
318 .ok_or("Failed to allocate event queue descriptor")?;
319
320 let buffer_phys = crate::vm::get_kernel_vm_manager()
322 .translate_vaddr(buffer_addr)
323 .ok_or("Failed to translate event buffer vaddr")?;
324
325 eventq.desc[desc_idx].addr = buffer_phys as u64;
327 eventq.desc[desc_idx].len = VirtioInputEvent::size() as u32;
328 eventq.desc[desc_idx].flags = DescriptorFlag::Write as u16; eventq.desc[desc_idx].next = 0; eventq
333 .push(desc_idx)
334 .map_err(|_| "Failed to push descriptor to event queue")?;
335
336 buffers.push(unsafe { Box::from_raw(buffer_ptr) });
338 }
339
340 self.write32_register(Register::QueueNotify, 0);
342
343 Ok(())
344 }
345
346 pub fn handle_interrupt(&self) {
350 let isr_status = self.read32_register(Register::InterruptStatus);
352 if isr_status == 0 {
353 return;
354 }
355
356 self.write32_register(Register::InterruptAck, isr_status);
357
358 self.process_events();
360 }
361
362 pub fn poll_events(&self) {
367 self.process_events();
368 }
369
370 fn process_events(&self) {
372 let mut eventq = self.eventq.lock();
373
374 while let Some(desc_idx) = eventq.pop() {
375 let buffer_addr = eventq.desc[desc_idx].addr;
376 let length = eventq.desc[desc_idx].len;
377
378 if length != VirtioInputEvent::size() as u32 {
379 early_println!("[virtio-input] Warning: unexpected event size {}", length);
380 eventq.free_desc(desc_idx);
381 continue;
382 }
383
384 let virtio_event =
387 unsafe { core::ptr::read_volatile(buffer_addr as *const VirtioInputEvent) };
388
389 self.event_device
391 .push_event(virtio_event.type_, virtio_event.code, virtio_event.value);
392
393 eventq.desc[desc_idx].len = VirtioInputEvent::size() as u32;
395 eventq.desc[desc_idx].flags = DescriptorFlag::Write as u16;
396
397 if let Err(e) = eventq.push(desc_idx) {
399 early_println!("[virtio-input] Failed to re-add buffer: {:?}", e);
400 eventq.free_desc(desc_idx);
401 }
402 }
403
404 self.write32_register(Register::QueueNotify, 0);
406 }
407
408 pub fn enable_interrupts(&self, interrupt_id: u32) -> Result<(), &'static str> {
410 *self.interrupt_id.lock() = Some(interrupt_id);
412
413 let isr = self.read32_register(Register::InterruptStatus);
415 if isr != 0 {
416 self.write32_register(Register::InterruptAck, isr);
417 self.process_events();
419 }
420
421 crate::interrupt::InterruptManager::with_manager(|mgr| {
423 mgr.enable_external_interrupt(interrupt_id, 0)
424 })
425 .map_err(|_| "Failed to enable interrupt in PLIC")?;
426
427 Ok(())
428 }
429
430 pub fn get_event_device(&self) -> Arc<EventDevice> {
432 self.event_device.clone()
433 }
434}
435
436impl crate::object::capability::memory_mapping::MemoryMappingOps for VirtioInputDevice {
438 fn get_mapping_info(
439 &self,
440 _offset: usize,
441 _length: usize,
442 ) -> Result<(usize, usize, bool), &'static str> {
443 Err("Memory mapping not supported")
444 }
445}
446
447impl crate::device::Device for VirtioInputDevice {
449 fn device_type(&self) -> crate::device::DeviceType {
450 crate::device::DeviceType::Char
451 }
452
453 fn name(&self) -> &'static str {
454 "virtio-input"
455 }
456
457 fn as_any(&self) -> &dyn core::any::Any {
458 self
459 }
460
461 fn as_any_mut(&mut self) -> &mut dyn core::any::Any {
462 self
463 }
464}
465
466impl crate::object::capability::selectable::Selectable for VirtioInputDevice {
468 fn wait_until_ready(
469 &self,
470 _interest: crate::object::capability::selectable::ReadyInterest,
471 _trapframe: &mut crate::arch::Trapframe,
472 _timeout_ticks: Option<u64>,
473 ) -> crate::object::capability::selectable::SelectWaitOutcome {
474 crate::object::capability::selectable::SelectWaitOutcome::Ready
475 }
476}
477
478impl crate::object::capability::control::ControlOps for VirtioInputDevice {}
480
481impl VirtioDevice for VirtioInputDevice {
482 fn get_base_addr(&self) -> usize {
483 self.base_addr
484 }
485
486 fn get_device_info(&self) -> (u32, u32) {
487 let device_id = self.read32_register(Register::DeviceId);
488 let vendor_id = self.read32_register(Register::VendorId);
489 (device_id, vendor_id)
490 }
491
492 fn get_virtqueue_count(&self) -> usize {
493 2 }
495
496 fn get_virtqueue_size(&self, queue_idx: usize) -> usize {
497 match queue_idx {
498 0 => self.eventq.lock().get_queue_size(),
499 1 => self.statusq.lock().get_queue_size(),
500 _ => 0,
501 }
502 }
503
504 fn get_queue_desc_addr(&self, queue_idx: usize) -> Option<u64> {
505 match queue_idx {
506 0 => Some(self.eventq.lock().get_raw_ptr() as u64),
507 1 => Some(self.statusq.lock().get_raw_ptr() as u64),
508 _ => None,
509 }
510 }
511
512 fn get_queue_driver_addr(&self, queue_idx: usize) -> Option<u64> {
513 match queue_idx {
514 0 => Some(self.eventq.lock().avail.flags as *const _ as u64),
515 1 => Some(self.statusq.lock().avail.flags as *const _ as u64),
516 _ => None,
517 }
518 }
519
520 fn get_queue_device_addr(&self, queue_idx: usize) -> Option<u64> {
521 match queue_idx {
522 0 => Some(self.eventq.lock().used.flags as *const _ as u64),
523 1 => Some(self.statusq.lock().used.flags as *const _ as u64),
524 _ => None,
525 }
526 }
527}
528
529#[cfg(test)]
530mod tests {
531 use crate::device::input::{event_types::*, key_codes::*};
532
533 use super::*;
534
535 #[test_case]
536 fn test_virtio_input_event_size() {
537 assert_eq!(VirtioInputEvent::size(), 8);
539 }
540
541 #[test_case]
542 fn test_event_conversion() {
543 let virtio_event = VirtioInputEvent {
544 type_: EV_KEY,
545 code: KEY_A,
546 value: 1,
547 };
548
549 assert_eq!(virtio_event.type_, EV_KEY);
550 assert_eq!(virtio_event.code, KEY_A);
551 assert_eq!(virtio_event.value, 1);
552 }
553}
554
555impl crate::device::events::InterruptCapableDevice for VirtioInputDevice {
557 fn handle_interrupt(&self) -> crate::interrupt::InterruptResult<()> {
558 let isr_status = self.read32_register(Register::InterruptStatus);
560 if isr_status == 0 {
561 return Ok(());
562 }
563
564 self.write32_register(Register::InterruptAck, isr_status);
566
567 self.process_events();
569
570 Ok(())
571 }
572
573 fn interrupt_id(&self) -> Option<crate::interrupt::InterruptId> {
574 None
575 }
576}