Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/usb/xhci/transfer_ring_controller.rs
5394 views
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 {
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
77
impl 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
}
104
105