1 // Copyright 2019 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::sync::Arc; 6 7 use anyhow::Context; 8 use base::Event; 9 use sync::Mutex; 10 use vm_memory::GuestMemory; 11 12 use super::interrupter::Interrupter; 13 use super::usb_hub::UsbPort; 14 use super::xhci_abi::TransferDescriptor; 15 use super::xhci_transfer::XhciTransferManager; 16 use crate::usb::xhci::ring_buffer_controller::Error as RingBufferControllerError; 17 use crate::usb::xhci::ring_buffer_controller::RingBufferController; 18 use crate::usb::xhci::ring_buffer_controller::TransferDescriptorHandler; 19 use crate::utils::EventLoop; 20 21 /// Transfer ring controller manages transfer ring. 22 pub type TransferRingController = RingBufferController<TransferRingTrbHandler>; 23 24 pub type TransferRingControllerError = RingBufferControllerError; 25 26 /// TransferRingTrbHandler handles trbs on transfer ring. 27 pub struct TransferRingTrbHandler { 28 mem: GuestMemory, 29 port: Arc<UsbPort>, 30 interrupter: Arc<Mutex<Interrupter>>, 31 slot_id: u8, 32 endpoint_id: u8, 33 transfer_manager: XhciTransferManager, 34 } 35 36 impl TransferDescriptorHandler for TransferRingTrbHandler { handle_transfer_descriptor( &self, descriptor: TransferDescriptor, completion_event: Event, ) -> anyhow::Result<()>37 fn handle_transfer_descriptor( 38 &self, 39 descriptor: TransferDescriptor, 40 completion_event: Event, 41 ) -> anyhow::Result<()> { 42 let xhci_transfer = self.transfer_manager.create_transfer( 43 self.mem.clone(), 44 self.port.clone(), 45 self.interrupter.clone(), 46 self.slot_id, 47 self.endpoint_id, 48 descriptor, 49 completion_event, 50 ); 51 xhci_transfer 52 .send_to_backend_if_valid() 53 .context("failed to send transfer to backend") 54 } 55 stop(&self) -> bool56 fn stop(&self) -> bool { 57 let backend = self.port.get_backend_device(); 58 if backend.is_some() { 59 self.transfer_manager.cancel_all(); 60 true 61 } else { 62 false 63 } 64 } 65 } 66 67 impl TransferRingController { new( mem: GuestMemory, port: Arc<UsbPort>, event_loop: Arc<EventLoop>, interrupter: Arc<Mutex<Interrupter>>, slot_id: u8, endpoint_id: u8, ) -> Result<Arc<TransferRingController>, TransferRingControllerError>68 pub fn new( 69 mem: GuestMemory, 70 port: Arc<UsbPort>, 71 event_loop: Arc<EventLoop>, 72 interrupter: Arc<Mutex<Interrupter>>, 73 slot_id: u8, 74 endpoint_id: u8, 75 ) -> Result<Arc<TransferRingController>, TransferRingControllerError> { 76 RingBufferController::new_with_handler( 77 format!("transfer ring slot_{} ep_{}", slot_id, endpoint_id), 78 mem.clone(), 79 event_loop, 80 TransferRingTrbHandler { 81 mem, 82 port, 83 interrupter, 84 slot_id, 85 endpoint_id, 86 transfer_manager: XhciTransferManager::new(), 87 }, 88 ) 89 } 90 } 91