xref: /aosp_15_r20/external/crosvm/devices/src/usb/backend/utils.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
8*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
9*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
10*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::TransferStatus;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::device::BackendDeviceType;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::error::Error;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::error::Result;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::xhci_transfer::XhciTransfer;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::xhci_transfer::XhciTransferState;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::utils::EventHandler;
18*bb4ee6a4SAndroid Build Coastguard Worker 
19*bb4ee6a4SAndroid Build Coastguard Worker #[macro_export]
20*bb4ee6a4SAndroid Build Coastguard Worker /// Allows dispatching a function call to all its enum value implementations.
21*bb4ee6a4SAndroid Build Coastguard Worker /// See `BackendDeviceType` in usb/backend/device.rs for an example usage of it.
22*bb4ee6a4SAndroid Build Coastguard Worker ///
23*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
24*bb4ee6a4SAndroid Build Coastguard Worker ///
25*bb4ee6a4SAndroid Build Coastguard Worker /// * `self` - Replacement for the local `self` reference in the function call.
26*bb4ee6a4SAndroid Build Coastguard Worker /// * `enum` - Enum name that the macro is matching on.
27*bb4ee6a4SAndroid Build Coastguard Worker /// * `types` - Space-separated list of value types of the given enum.
28*bb4ee6a4SAndroid Build Coastguard Worker /// * `func` - Function name that will be called by each match arm.
29*bb4ee6a4SAndroid Build Coastguard Worker /// * `param` - Optional parameters needed for the given function call.
30*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! multi_dispatch {
31*bb4ee6a4SAndroid Build Coastguard Worker     ($self:ident, $enum:ident, $($types:ident )+, $func:ident) => {
32*bb4ee6a4SAndroid Build Coastguard Worker         match $self {
33*bb4ee6a4SAndroid Build Coastguard Worker             $(
34*bb4ee6a4SAndroid Build Coastguard Worker                 $enum::$types(device) => device.$func(),
35*bb4ee6a4SAndroid Build Coastguard Worker             )+
36*bb4ee6a4SAndroid Build Coastguard Worker         }
37*bb4ee6a4SAndroid Build Coastguard Worker     };
38*bb4ee6a4SAndroid Build Coastguard Worker     ($self:ident, $enum:ident, $($types:ident )+, $func:ident, $param:expr) => {
39*bb4ee6a4SAndroid Build Coastguard Worker         match $self {
40*bb4ee6a4SAndroid Build Coastguard Worker             $(
41*bb4ee6a4SAndroid Build Coastguard Worker                 $enum::$types(device) => device.$func($param),
42*bb4ee6a4SAndroid Build Coastguard Worker             )+
43*bb4ee6a4SAndroid Build Coastguard Worker         }
44*bb4ee6a4SAndroid Build Coastguard Worker     };
45*bb4ee6a4SAndroid Build Coastguard Worker     ($self:ident, $enum:ident, $($types:ident )+, $func:ident, $param1:expr, $param2: expr) => {
46*bb4ee6a4SAndroid Build Coastguard Worker         match $self {
47*bb4ee6a4SAndroid Build Coastguard Worker             $(
48*bb4ee6a4SAndroid Build Coastguard Worker                 $enum::$types(device) => device.$func($param1, $param2),
49*bb4ee6a4SAndroid Build Coastguard Worker             )+
50*bb4ee6a4SAndroid Build Coastguard Worker         }
51*bb4ee6a4SAndroid Build Coastguard Worker     };
52*bb4ee6a4SAndroid Build Coastguard Worker     ($self:ident, $enum:ident, $($types:ident )+, $func:ident, $param1:expr, $param2: expr, $param3: expr) => {
53*bb4ee6a4SAndroid Build Coastguard Worker         match $self {
54*bb4ee6a4SAndroid Build Coastguard Worker             $(
55*bb4ee6a4SAndroid Build Coastguard Worker                 $enum::$types(device) => device.$func($param1, $param2, $param3),
56*bb4ee6a4SAndroid Build Coastguard Worker             )+
57*bb4ee6a4SAndroid Build Coastguard Worker         }
58*bb4ee6a4SAndroid Build Coastguard Worker     };
59*bb4ee6a4SAndroid Build Coastguard Worker }
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) use multi_dispatch;
62*bb4ee6a4SAndroid Build Coastguard Worker 
63*bb4ee6a4SAndroid Build Coastguard Worker pub struct UsbUtilEventHandler {
64*bb4ee6a4SAndroid Build Coastguard Worker     pub device: Arc<Mutex<BackendDeviceType>>,
65*bb4ee6a4SAndroid Build Coastguard Worker }
66*bb4ee6a4SAndroid Build Coastguard Worker 
67*bb4ee6a4SAndroid Build Coastguard Worker impl EventHandler for UsbUtilEventHandler {
on_event(&self) -> anyhow::Result<()>68*bb4ee6a4SAndroid Build Coastguard Worker     fn on_event(&self) -> anyhow::Result<()> {
69*bb4ee6a4SAndroid Build Coastguard Worker         match &mut *self.device.lock() {
70*bb4ee6a4SAndroid Build Coastguard Worker             BackendDeviceType::HostDevice(host_device) => host_device
71*bb4ee6a4SAndroid Build Coastguard Worker                 .device
72*bb4ee6a4SAndroid Build Coastguard Worker                 .lock()
73*bb4ee6a4SAndroid Build Coastguard Worker                 .poll_transfers()
74*bb4ee6a4SAndroid Build Coastguard Worker                 .context("UsbUtilEventHandler poll_transfers failed"),
75*bb4ee6a4SAndroid Build Coastguard Worker             BackendDeviceType::FidoDevice(fido_device) => fido_device
76*bb4ee6a4SAndroid Build Coastguard Worker                 .read_hidraw_file()
77*bb4ee6a4SAndroid Build Coastguard Worker                 .context("FidoDeviceEventHandler failed to read hidraw device"),
78*bb4ee6a4SAndroid Build Coastguard Worker         }
79*bb4ee6a4SAndroid Build Coastguard Worker     }
80*bb4ee6a4SAndroid Build Coastguard Worker }
81*bb4ee6a4SAndroid Build Coastguard Worker 
82*bb4ee6a4SAndroid Build Coastguard Worker /// Helper function to update xhci_transfer state.
update_transfer_state( xhci_transfer: &Arc<XhciTransfer>, status: TransferStatus, ) -> Result<()>83*bb4ee6a4SAndroid Build Coastguard Worker pub fn update_transfer_state(
84*bb4ee6a4SAndroid Build Coastguard Worker     xhci_transfer: &Arc<XhciTransfer>,
85*bb4ee6a4SAndroid Build Coastguard Worker     status: TransferStatus,
86*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
87*bb4ee6a4SAndroid Build Coastguard Worker     let mut state = xhci_transfer.state().lock();
88*bb4ee6a4SAndroid Build Coastguard Worker 
89*bb4ee6a4SAndroid Build Coastguard Worker     if status == TransferStatus::Cancelled {
90*bb4ee6a4SAndroid Build Coastguard Worker         *state = XhciTransferState::Cancelled;
91*bb4ee6a4SAndroid Build Coastguard Worker         return Ok(());
92*bb4ee6a4SAndroid Build Coastguard Worker     }
93*bb4ee6a4SAndroid Build Coastguard Worker 
94*bb4ee6a4SAndroid Build Coastguard Worker     match *state {
95*bb4ee6a4SAndroid Build Coastguard Worker         XhciTransferState::Cancelling => {
96*bb4ee6a4SAndroid Build Coastguard Worker             *state = XhciTransferState::Cancelled;
97*bb4ee6a4SAndroid Build Coastguard Worker         }
98*bb4ee6a4SAndroid Build Coastguard Worker         XhciTransferState::Submitted { .. } => {
99*bb4ee6a4SAndroid Build Coastguard Worker             *state = XhciTransferState::Completed;
100*bb4ee6a4SAndroid Build Coastguard Worker         }
101*bb4ee6a4SAndroid Build Coastguard Worker         _ => {
102*bb4ee6a4SAndroid Build Coastguard Worker             error!("xhci trasfer state is invalid");
103*bb4ee6a4SAndroid Build Coastguard Worker             *state = XhciTransferState::Completed;
104*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::BadXhciTransferState);
105*bb4ee6a4SAndroid Build Coastguard Worker         }
106*bb4ee6a4SAndroid Build Coastguard Worker     }
107*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
108*bb4ee6a4SAndroid Build Coastguard Worker }
109