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::utils::EventLoop;
22
23pub type TransferRingController = RingBufferController<TransferRingTrbHandler>;
25
26#[derive(Clone)]
27pub enum TransferRingControllers {
28 Endpoint(Arc<TransferRingController>),
29 Stream(Vec<Arc<TransferRingController>>),
30}
31
32pub type TransferRingControllerError = RingBufferControllerError;
33
34pub 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
45impl TransferDescriptorHandler for TransferRingTrbHandler {
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
66 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
77impl TransferRingController {
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_{slot_id} ep_{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}