xref: /aosp_15_r20/external/crosvm/devices/src/usb/xhci/transfer_ring_controller.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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