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