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 use std::sync::Weak; 7 8 use anyhow::Context; 9 use base::Event; 10 use sync::Mutex; 11 use vm_memory::GuestMemory; 12 13 use super::device_slot::DeviceSlot; 14 use super::interrupter::Interrupter; 15 use super::usb_hub::UsbPort; 16 use super::xhci_abi::TransferDescriptor; 17 use super::xhci_transfer::XhciTransferManager; 18 use crate::usb::xhci::ring_buffer_controller::Error as RingBufferControllerError; 19 use crate::usb::xhci::ring_buffer_controller::RingBufferController; 20 use crate::usb::xhci::ring_buffer_controller::TransferDescriptorHandler; 21 use crate::utils::EventLoop; 22 23 /// Transfer ring controller manages transfer ring. 24 pub type TransferRingController = RingBufferController<TransferRingTrbHandler>; 25 26 #[derive(Clone)] 27 pub enum TransferRingControllers { 28 Endpoint(Arc<TransferRingController>), 29 Stream(Vec<Arc<TransferRingController>>), 30 } 31 32 pub type TransferRingControllerError = RingBufferControllerError; 33 34 /// TransferRingTrbHandler handles trbs on transfer ring. 35 pub struct TransferRingTrbHandler { 36 mem: GuestMemory, 37 port: Arc<UsbPort>, 38 interrupter: Arc<Mutex<Interrupter>>, 39 slot_id: u8, 40 endpoint_id: u8, 41 transfer_manager: XhciTransferManager, 42 stream_id: Option<u16>, 43 } 44 45 impl TransferDescriptorHandler for TransferRingTrbHandler { handle_transfer_descriptor( &self, descriptor: TransferDescriptor, completion_event: Event, ) -> anyhow::Result<()>46 fn handle_transfer_descriptor( 47 &self, 48 descriptor: TransferDescriptor, 49 completion_event: Event, 50 ) -> anyhow::Result<()> { 51 let xhci_transfer = self.transfer_manager.create_transfer( 52 self.mem.clone(), 53 self.port.clone(), 54 self.interrupter.clone(), 55 self.slot_id, 56 self.endpoint_id, 57 descriptor, 58 completion_event, 59 self.stream_id, 60 ); 61 xhci_transfer 62 .send_to_backend_if_valid() 63 .context("failed to send transfer to backend") 64 } 65 stop(&self) -> bool66 fn stop(&self) -> bool { 67 let backend = self.port.backend_device(); 68 if backend.is_some() { 69 self.transfer_manager.cancel_all(); 70 true 71 } else { 72 false 73 } 74 } 75 } 76 77 impl TransferRingController { new( mem: GuestMemory, port: Arc<UsbPort>, event_loop: Arc<EventLoop>, interrupter: Arc<Mutex<Interrupter>>, slot_id: u8, endpoint_id: u8, device_slot: Weak<DeviceSlot>, stream_id: Option<u16>, ) -> Result<Arc<TransferRingController>, TransferRingControllerError>78 pub fn new( 79 mem: GuestMemory, 80 port: Arc<UsbPort>, 81 event_loop: Arc<EventLoop>, 82 interrupter: Arc<Mutex<Interrupter>>, 83 slot_id: u8, 84 endpoint_id: u8, 85 device_slot: Weak<DeviceSlot>, 86 stream_id: Option<u16>, 87 ) -> Result<Arc<TransferRingController>, TransferRingControllerError> { 88 RingBufferController::new_with_handler( 89 format!("transfer ring slot_{} ep_{}", slot_id, endpoint_id), 90 mem.clone(), 91 event_loop, 92 TransferRingTrbHandler { 93 mem, 94 port, 95 interrupter, 96 slot_id, 97 endpoint_id, 98 transfer_manager: XhciTransferManager::new(device_slot), 99 stream_id, 100 }, 101 ) 102 } 103 } 104