kernel/drivers/
virtio_input.rs

1//! VirtIO Input Device Driver
2//!
3//! This module implements a VirtIO input device driver that supports
4//! keyboards, mice, tablets, and other input devices.
5//!
6//! The driver integrates with Scarlet's native EventDevice to provide
7//! a clean interface for input event handling.
8
9extern 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/// VirtIO Input event structure (matches Linux virtio_input_event)
26#[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/// VirtIO Input device configuration
41#[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
51/// Config select values
52mod 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
62/// VirtIO Input Device
63pub struct VirtioInputDevice {
64    base_addr: usize,
65    eventq: Mutex<VirtQueue<'static>>, // Event queue (device -> driver)
66    statusq: Mutex<VirtQueue<'static>>, // Status queue (driver -> device)
67    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    /// Read a u8 from configuration space
75    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    /// Write a u8 to configuration space
83    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    /// Read device name from configuration
91    fn read_device_name(&self) -> Option<alloc::string::String> {
92        use config_select::*;
93
94        // Select name configuration
95        self.write8_config(0, VIRTIO_INPUT_CFG_ID_NAME);
96        self.write8_config(1, 0); // subsel
97
98        // Read size
99        let size = self.read8_config(2);
100        if size == 0 || size > 128 {
101            return None;
102        }
103
104        // Read name from data field (offset 8)
105        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    /// Determine device type from name
118    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    /// Create a new VirtIO Input device
132    ///
133    /// # Arguments
134    ///
135    /// * `base_addr` - The base address of the device
136    ///
137    /// # Returns
138    ///
139    /// A new instance of `VirtioInputDevice`
140    pub fn new(base_addr: usize) -> Self {
141        // Create a temporary device to read configuration
142        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        // Read device name from VirtIO config
153        let virtio_name = temp_device
154            .read_device_name()
155            .unwrap_or_else(|| "Unknown Device".to_string());
156
157        // Determine device type
158        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        // Create the EventDevice with the device type (it will assign the name)
167        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        // Initialize the VirtIO device
183        if let Err(e) = device.init() {
184            panic!("[virtio-input] Failed to initialize: {}", e);
185        }
186
187        // Register the EventDevice with DeviceManager
188        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    /// Initialize the VirtIO input device
197    fn init(&mut self) -> Result<(), &'static str> {
198        // 1. Reset the device
199        self.write32_register(Register::Status, 0);
200
201        // 2. Set ACKNOWLEDGE status bit
202        let mut status = 0u32;
203        DeviceStatus::Acknowledge.set(&mut status);
204        self.write32_register(Register::Status, status);
205
206        // 3. Set DRIVER status bit
207        DeviceStatus::Driver.set(&mut status);
208        self.write32_register(Register::Status, status);
209
210        // 4. Read device features
211        self.write32_register(Register::DeviceFeaturesSel, 0);
212        let _device_features = self.read32_register(Register::DeviceFeatures);
213
214        // 5. Negotiate features (for now, accept no optional features)
215        self.write32_register(Register::DriverFeaturesSel, 0);
216        self.write32_register(Register::DriverFeatures, 0);
217
218        // 6. Set FEATURES_OK
219        DeviceStatus::FeaturesOK.set(&mut status);
220        self.write32_register(Register::Status, status);
221
222        // 7. Re-read status to ensure FEATURES_OK is still set
223        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        // 8. Setup virtqueues
229        self.setup_queues()?;
230
231        // 9. Set DRIVER_OK
232        DeviceStatus::DriverOK.set(&mut status);
233        self.write32_register(Register::Status, status);
234
235        // 10. Prefill event queue with buffers
236        self.prefill_event_queue()?;
237
238        *self.initialized.lock() = true;
239
240        Ok(())
241    }
242
243    /// Setup virtqueues
244    fn setup_queues(&mut self) -> Result<(), &'static str> {
245        // Setup eventq (queue 0)
246        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        // Initialize the queue
257        let mut eventq = self.eventq.lock();
258        eventq.init();
259
260        // Set queue addresses
261        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        // Setup statusq (queue 1) - optional, not used for basic input
277        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    /// Prefill event queue with receive buffers
304    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            // Allocate buffer for VirtioInputEvent
311            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            // Allocate descriptor
316            let desc_idx = eventq
317                .alloc_desc()
318                .ok_or("Failed to allocate event queue descriptor")?;
319
320            // Translate virtual address to physical
321            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            // Setup descriptor - device writes events here
326            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; // Device writes
329            eventq.desc[desc_idx].next = 0; // No chaining
330
331            // Add to available ring
332            eventq
333                .push(desc_idx)
334                .map_err(|_| "Failed to push descriptor to event queue")?;
335
336            // Store buffer pointer for cleanup
337            buffers.push(unsafe { Box::from_raw(buffer_ptr) });
338        }
339
340        // Notify device that buffers are available
341        self.write32_register(Register::QueueNotify, 0);
342
343        Ok(())
344    }
345
346    /// Handle input events from the device
347    ///
348    /// This should be called from the interrupt handler or periodically polled
349    pub fn handle_interrupt(&self) {
350        // Read and acknowledge interrupt status
351        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        // Process events from the queue
359        self.process_events();
360    }
361
362    /// Poll for events (for testing without interrupt support)
363    ///
364    /// This can be called periodically to check for events when
365    /// interrupt handling is not yet implemented
366    pub fn poll_events(&self) {
367        self.process_events();
368    }
369
370    /// Process events from the event queue
371    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            // Read the VirtIO event directly from physical address
385            // Note: In identity-mapped kernel space, physical == virtual
386            let virtio_event =
387                unsafe { core::ptr::read_volatile(buffer_addr as *const VirtioInputEvent) };
388
389            // Convert to Scarlet event and push to EventDevice
390            self.event_device
391                .push_event(virtio_event.type_, virtio_event.code, virtio_event.value);
392
393            // Re-setup the descriptor for reuse
394            eventq.desc[desc_idx].len = VirtioInputEvent::size() as u32;
395            eventq.desc[desc_idx].flags = DescriptorFlag::Write as u16;
396
397            // Re-add to available ring
398            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        // Notify device that we've added more buffers
405        self.write32_register(Register::QueueNotify, 0);
406    }
407
408    /// Enable interrupts for this device
409    pub fn enable_interrupts(&self, interrupt_id: u32) -> Result<(), &'static str> {
410        // Store the interrupt ID
411        *self.interrupt_id.lock() = Some(interrupt_id);
412
413        // Check current ISR status and clear any pending interrupts
414        let isr = self.read32_register(Register::InterruptStatus);
415        if isr != 0 {
416            self.write32_register(Register::InterruptAck, isr);
417            // Process any pending events
418            self.process_events();
419        }
420
421        // Enable interrupt in PLIC for CPU 0
422        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    /// Get the EventDevice for this input device
431    pub fn get_event_device(&self) -> Arc<EventDevice> {
432        self.event_device.clone()
433    }
434}
435
436// Implement MemoryMappingOps for VirtioInputDevice
437impl 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
447// Implement Device for VirtioInputDevice
448impl 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
466// Implement Selectable for VirtioInputDevice
467impl 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
478// Implement ControlOps for VirtioInputDevice
479impl 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 // Event queue and status queue
494    }
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        // VirtioInputEvent should be 8 bytes (2+2+4)
538        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
555// Implement InterruptCapableDevice for VirtioInputDevice
556impl crate::device::events::InterruptCapableDevice for VirtioInputDevice {
557    fn handle_interrupt(&self) -> crate::interrupt::InterruptResult<()> {
558        // Read ISR status to acknowledge interrupt
559        let isr_status = self.read32_register(Register::InterruptStatus);
560        if isr_status == 0 {
561            return Ok(());
562        }
563
564        // Acknowledge the interrupt
565        self.write32_register(Register::InterruptAck, isr_status);
566
567        // Process pending events
568        self.process_events();
569
570        Ok(())
571    }
572
573    fn interrupt_id(&self) -> Option<crate::interrupt::InterruptId> {
574        None
575    }
576}