Path: blob/main/devices/src/usb/xhci/transfer_ring_controller.rs
5394 views
// Copyright 2019 The ChromiumOS Authors1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34use std::sync::Arc;5use std::sync::Weak;67use anyhow::Context;8use base::Event;9use sync::Mutex;10use vm_memory::GuestMemory;1112use super::device_slot::DeviceSlot;13use super::interrupter::Interrupter;14use super::usb_hub::UsbPort;15use super::xhci_abi::TransferDescriptor;16use super::xhci_transfer::XhciTransferManager;17use crate::usb::xhci::ring_buffer_controller::Error as RingBufferControllerError;18use crate::usb::xhci::ring_buffer_controller::RingBufferController;19use crate::usb::xhci::ring_buffer_controller::TransferDescriptorHandler;20use crate::utils::EventLoop;2122/// Transfer ring controller manages transfer ring.23pub type TransferRingController = RingBufferController<TransferRingTrbHandler>;2425#[derive(Clone)]26pub enum TransferRingControllers {27Endpoint(Arc<TransferRingController>),28Stream(Vec<Arc<TransferRingController>>),29}3031pub type TransferRingControllerError = RingBufferControllerError;3233/// TransferRingTrbHandler handles trbs on transfer ring.34pub struct TransferRingTrbHandler {35mem: GuestMemory,36port: Arc<UsbPort>,37interrupter: Arc<Mutex<Interrupter>>,38slot_id: u8,39endpoint_id: u8,40transfer_manager: XhciTransferManager,41stream_id: Option<u16>,42}4344impl TransferDescriptorHandler for TransferRingTrbHandler {45fn handle_transfer_descriptor(46&self,47descriptor: TransferDescriptor,48completion_event: Event,49) -> anyhow::Result<()> {50let xhci_transfer = self.transfer_manager.create_transfer(51self.mem.clone(),52self.port.clone(),53self.interrupter.clone(),54self.slot_id,55self.endpoint_id,56descriptor,57completion_event,58self.stream_id,59);60xhci_transfer61.send_to_backend_if_valid()62.context("failed to send transfer to backend")63}6465fn stop(&self) -> bool {66let backend = self.port.backend_device();67if backend.is_some() {68self.transfer_manager.cancel_all();69true70} else {71false72}73}74}7576impl TransferRingController {77pub fn new(78mem: GuestMemory,79port: Arc<UsbPort>,80event_loop: Arc<EventLoop>,81interrupter: Arc<Mutex<Interrupter>>,82slot_id: u8,83endpoint_id: u8,84device_slot: Weak<DeviceSlot>,85stream_id: Option<u16>,86) -> Result<Arc<TransferRingController>, TransferRingControllerError> {87RingBufferController::new_with_handler(88format!("transfer ring slot_{slot_id} ep_{endpoint_id}"),89mem.clone(),90event_loop,91TransferRingTrbHandler {92mem,93port,94interrupter,95slot_id,96endpoint_id,97transfer_manager: XhciTransferManager::new(device_slot),98stream_id,99},100)101}102}103104105