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 Workerpub 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