xref: /aosp_15_r20/external/crosvm/devices/src/virtio/console/input.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2024 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! Virtio console device input handling.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::VecDeque;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::Queue;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker /// Checks for input from `buffer` and transfers it to the receive queue, if any.
13*bb4ee6a4SAndroid Build Coastguard Worker ///
14*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
15*bb4ee6a4SAndroid Build Coastguard Worker ///
16*bb4ee6a4SAndroid Build Coastguard Worker /// * `interrupt` - Interrupt used to signal that the queue has been used
17*bb4ee6a4SAndroid Build Coastguard Worker /// * `buffer` - Ring buffer providing data to put into the guest
18*bb4ee6a4SAndroid Build Coastguard Worker /// * `receive_queue` - The receive virtio Queue
process_receive_queue(buffer: &mut VecDeque<u8>, receive_queue: &mut Queue)19*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_receive_queue(buffer: &mut VecDeque<u8>, receive_queue: &mut Queue) {
20*bb4ee6a4SAndroid Build Coastguard Worker     while let Some(mut desc) = receive_queue.peek() {
21*bb4ee6a4SAndroid Build Coastguard Worker         if buffer.is_empty() {
22*bb4ee6a4SAndroid Build Coastguard Worker             break;
23*bb4ee6a4SAndroid Build Coastguard Worker         }
24*bb4ee6a4SAndroid Build Coastguard Worker 
25*bb4ee6a4SAndroid Build Coastguard Worker         let writer = &mut desc.writer;
26*bb4ee6a4SAndroid Build Coastguard Worker         while writer.available_bytes() > 0 && !buffer.is_empty() {
27*bb4ee6a4SAndroid Build Coastguard Worker             let (buffer_front, buffer_back) = buffer.as_slices();
28*bb4ee6a4SAndroid Build Coastguard Worker             let buffer_chunk = if !buffer_front.is_empty() {
29*bb4ee6a4SAndroid Build Coastguard Worker                 buffer_front
30*bb4ee6a4SAndroid Build Coastguard Worker             } else {
31*bb4ee6a4SAndroid Build Coastguard Worker                 buffer_back
32*bb4ee6a4SAndroid Build Coastguard Worker             };
33*bb4ee6a4SAndroid Build Coastguard Worker             let written = writer.write(buffer_chunk).unwrap();
34*bb4ee6a4SAndroid Build Coastguard Worker             drop(buffer.drain(..written));
35*bb4ee6a4SAndroid Build Coastguard Worker         }
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker         let bytes_written = writer.bytes_written() as u32;
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker         if bytes_written > 0 {
40*bb4ee6a4SAndroid Build Coastguard Worker             let desc = desc.pop();
41*bb4ee6a4SAndroid Build Coastguard Worker             receive_queue.add_used(desc, bytes_written);
42*bb4ee6a4SAndroid Build Coastguard Worker             receive_queue.trigger_interrupt();
43*bb4ee6a4SAndroid Build Coastguard Worker         }
44*bb4ee6a4SAndroid Build Coastguard Worker     }
45*bb4ee6a4SAndroid Build Coastguard Worker }
46