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