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