• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
7 use anyhow::Context;
8 use base::Event;
9 use sync::Mutex;
10 use vm_memory::GuestMemory;
11 
12 use super::interrupter::Interrupter;
13 use super::usb_hub::UsbPort;
14 use super::xhci_abi::TransferDescriptor;
15 use super::xhci_transfer::XhciTransferManager;
16 use crate::usb::xhci::ring_buffer_controller::Error as RingBufferControllerError;
17 use crate::usb::xhci::ring_buffer_controller::RingBufferController;
18 use crate::usb::xhci::ring_buffer_controller::TransferDescriptorHandler;
19 use crate::utils::EventLoop;
20 
21 /// Transfer ring controller manages transfer ring.
22 pub type TransferRingController = RingBufferController<TransferRingTrbHandler>;
23 
24 pub type TransferRingControllerError = RingBufferControllerError;
25 
26 /// TransferRingTrbHandler handles trbs on transfer ring.
27 pub struct TransferRingTrbHandler {
28     mem: GuestMemory,
29     port: Arc<UsbPort>,
30     interrupter: Arc<Mutex<Interrupter>>,
31     slot_id: u8,
32     endpoint_id: u8,
33     transfer_manager: XhciTransferManager,
34 }
35 
36 impl TransferDescriptorHandler for TransferRingTrbHandler {
handle_transfer_descriptor( &self, descriptor: TransferDescriptor, completion_event: Event, ) -> anyhow::Result<()>37     fn handle_transfer_descriptor(
38         &self,
39         descriptor: TransferDescriptor,
40         completion_event: Event,
41     ) -> anyhow::Result<()> {
42         let xhci_transfer = self.transfer_manager.create_transfer(
43             self.mem.clone(),
44             self.port.clone(),
45             self.interrupter.clone(),
46             self.slot_id,
47             self.endpoint_id,
48             descriptor,
49             completion_event,
50         );
51         xhci_transfer
52             .send_to_backend_if_valid()
53             .context("failed to send transfer to backend")
54     }
55 
stop(&self) -> bool56     fn stop(&self) -> bool {
57         let backend = self.port.get_backend_device();
58         if backend.is_some() {
59             self.transfer_manager.cancel_all();
60             true
61         } else {
62             false
63         }
64     }
65 }
66 
67 impl TransferRingController {
new( mem: GuestMemory, port: Arc<UsbPort>, event_loop: Arc<EventLoop>, interrupter: Arc<Mutex<Interrupter>>, slot_id: u8, endpoint_id: u8, ) -> Result<Arc<TransferRingController>, TransferRingControllerError>68     pub fn new(
69         mem: GuestMemory,
70         port: Arc<UsbPort>,
71         event_loop: Arc<EventLoop>,
72         interrupter: Arc<Mutex<Interrupter>>,
73         slot_id: u8,
74         endpoint_id: u8,
75     ) -> Result<Arc<TransferRingController>, TransferRingControllerError> {
76         RingBufferController::new_with_handler(
77             format!("transfer ring slot_{} ep_{}", slot_id, endpoint_id),
78             mem.clone(),
79             event_loop,
80             TransferRingTrbHandler {
81                 mem,
82                 port,
83                 interrupter,
84                 slot_id,
85                 endpoint_id,
86                 transfer_manager: XhciTransferManager::new(),
87             },
88         )
89     }
90 }
91