xref: /aosp_15_r20/external/crosvm/devices/src/usb/backend/transfer.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 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 usb_util::Transfer;
6*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::TransferBuffer;
7*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::TransferStatus;
8*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::UsbRequestSetup;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::endpoint::ControlEndpointState;
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::error::Result;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::fido_backend::transfer::FidoTransfer;
13*bb4ee6a4SAndroid Build Coastguard Worker 
14*bb4ee6a4SAndroid Build Coastguard Worker /// BackendTransferHandle is a wrapper structure around a generic transfer handle whose
15*bb4ee6a4SAndroid Build Coastguard Worker /// implementation depends on the backend type that is being used.
16*bb4ee6a4SAndroid Build Coastguard Worker pub struct BackendTransferHandle {
17*bb4ee6a4SAndroid Build Coastguard Worker     handle: Box<dyn GenericTransferHandle>,
18*bb4ee6a4SAndroid Build Coastguard Worker }
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker impl BackendTransferHandle {
new(handle: impl GenericTransferHandle + 'static) -> Self21*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(handle: impl GenericTransferHandle + 'static) -> Self {
22*bb4ee6a4SAndroid Build Coastguard Worker         BackendTransferHandle {
23*bb4ee6a4SAndroid Build Coastguard Worker             handle: Box::new(handle),
24*bb4ee6a4SAndroid Build Coastguard Worker         }
25*bb4ee6a4SAndroid Build Coastguard Worker     }
26*bb4ee6a4SAndroid Build Coastguard Worker 
cancel(&self) -> Result<()>27*bb4ee6a4SAndroid Build Coastguard Worker     pub fn cancel(&self) -> Result<()> {
28*bb4ee6a4SAndroid Build Coastguard Worker         self.handle.cancel()
29*bb4ee6a4SAndroid Build Coastguard Worker     }
30*bb4ee6a4SAndroid Build Coastguard Worker }
31*bb4ee6a4SAndroid Build Coastguard Worker 
32*bb4ee6a4SAndroid Build Coastguard Worker pub enum BackendTransferType {
33*bb4ee6a4SAndroid Build Coastguard Worker     HostDevice(Transfer),
34*bb4ee6a4SAndroid Build Coastguard Worker     FidoDevice(FidoTransfer),
35*bb4ee6a4SAndroid Build Coastguard Worker }
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker /// The backend transfer trait implemention is the interface of a generic transfer structure that
38*bb4ee6a4SAndroid Build Coastguard Worker /// each backend type should implement to be compatible with the generic backend device provider
39*bb4ee6a4SAndroid Build Coastguard Worker /// logic.
40*bb4ee6a4SAndroid Build Coastguard Worker pub trait BackendTransfer {
41*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the status of the transfer in a `TransferStatus` enum
status(&self) -> TransferStatus42*bb4ee6a4SAndroid Build Coastguard Worker     fn status(&self) -> TransferStatus;
43*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the actual amount of data transferred, which may be less than the original length.
actual_length(&self) -> usize44*bb4ee6a4SAndroid Build Coastguard Worker     fn actual_length(&self) -> usize;
45*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns a reference to the `TransferBuffer` object.
buffer(&self) -> &TransferBuffer46*bb4ee6a4SAndroid Build Coastguard Worker     fn buffer(&self) -> &TransferBuffer;
47*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets an optional callback on the transfer to be called when the transfer completes.
set_callback<C: 'static + Fn(BackendTransferType) + Send + Sync>(&mut self, cb: C)48*bb4ee6a4SAndroid Build Coastguard Worker     fn set_callback<C: 'static + Fn(BackendTransferType) + Send + Sync>(&mut self, cb: C);
49*bb4ee6a4SAndroid Build Coastguard Worker }
50*bb4ee6a4SAndroid Build Coastguard Worker 
51*bb4ee6a4SAndroid Build Coastguard Worker // TODO(morg): refactor with multi_dispatch
52*bb4ee6a4SAndroid Build Coastguard Worker impl BackendTransfer for BackendTransferType {
status(&self) -> TransferStatus53*bb4ee6a4SAndroid Build Coastguard Worker     fn status(&self) -> TransferStatus {
54*bb4ee6a4SAndroid Build Coastguard Worker         match self {
55*bb4ee6a4SAndroid Build Coastguard Worker             BackendTransferType::HostDevice(transfer) => BackendTransfer::status(transfer),
56*bb4ee6a4SAndroid Build Coastguard Worker             BackendTransferType::FidoDevice(transfer) => BackendTransfer::status(transfer),
57*bb4ee6a4SAndroid Build Coastguard Worker         }
58*bb4ee6a4SAndroid Build Coastguard Worker     }
59*bb4ee6a4SAndroid Build Coastguard Worker 
actual_length(&self) -> usize60*bb4ee6a4SAndroid Build Coastguard Worker     fn actual_length(&self) -> usize {
61*bb4ee6a4SAndroid Build Coastguard Worker         match self {
62*bb4ee6a4SAndroid Build Coastguard Worker             BackendTransferType::HostDevice(transfer) => BackendTransfer::actual_length(transfer),
63*bb4ee6a4SAndroid Build Coastguard Worker             BackendTransferType::FidoDevice(transfer) => BackendTransfer::actual_length(transfer),
64*bb4ee6a4SAndroid Build Coastguard Worker         }
65*bb4ee6a4SAndroid Build Coastguard Worker     }
66*bb4ee6a4SAndroid Build Coastguard Worker 
buffer(&self) -> &TransferBuffer67*bb4ee6a4SAndroid Build Coastguard Worker     fn buffer(&self) -> &TransferBuffer {
68*bb4ee6a4SAndroid Build Coastguard Worker         match self {
69*bb4ee6a4SAndroid Build Coastguard Worker             BackendTransferType::HostDevice(transfer) => BackendTransfer::buffer(transfer),
70*bb4ee6a4SAndroid Build Coastguard Worker             BackendTransferType::FidoDevice(transfer) => BackendTransfer::buffer(transfer),
71*bb4ee6a4SAndroid Build Coastguard Worker         }
72*bb4ee6a4SAndroid Build Coastguard Worker     }
73*bb4ee6a4SAndroid Build Coastguard Worker 
set_callback<C: 'static + Fn(BackendTransferType) + Send + Sync>(&mut self, cb: C)74*bb4ee6a4SAndroid Build Coastguard Worker     fn set_callback<C: 'static + Fn(BackendTransferType) + Send + Sync>(&mut self, cb: C) {
75*bb4ee6a4SAndroid Build Coastguard Worker         match self {
76*bb4ee6a4SAndroid Build Coastguard Worker             BackendTransferType::HostDevice(transfer) => {
77*bb4ee6a4SAndroid Build Coastguard Worker                 BackendTransfer::set_callback(transfer, cb)
78*bb4ee6a4SAndroid Build Coastguard Worker             }
79*bb4ee6a4SAndroid Build Coastguard Worker             BackendTransferType::FidoDevice(transfer) => {
80*bb4ee6a4SAndroid Build Coastguard Worker                 BackendTransfer::set_callback(transfer, cb)
81*bb4ee6a4SAndroid Build Coastguard Worker             }
82*bb4ee6a4SAndroid Build Coastguard Worker         }
83*bb4ee6a4SAndroid Build Coastguard Worker     }
84*bb4ee6a4SAndroid Build Coastguard Worker }
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker /// Generic transfer handle is a generic handle that allows for cancellation of in-flight
87*bb4ee6a4SAndroid Build Coastguard Worker /// transfers. It should be implemented by all backends that need to be plugged into a generic
88*bb4ee6a4SAndroid Build Coastguard Worker /// BackendTransferHandle structure.
89*bb4ee6a4SAndroid Build Coastguard Worker pub trait GenericTransferHandle: Send {
90*bb4ee6a4SAndroid Build Coastguard Worker     /// All objects that implement this method need to make sure `cancel()` is safe to call
91*bb4ee6a4SAndroid Build Coastguard Worker     /// multiple times as its invocation should be idempotent. A transfer that has already been
92*bb4ee6a4SAndroid Build Coastguard Worker     /// canceled ought not to error if it gets canceled again.
cancel(&self) -> Result<()>93*bb4ee6a4SAndroid Build Coastguard Worker     fn cancel(&self) -> Result<()>;
94*bb4ee6a4SAndroid Build Coastguard Worker }
95*bb4ee6a4SAndroid Build Coastguard Worker 
96*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
97*bb4ee6a4SAndroid Build Coastguard Worker pub struct ControlTransferState {
98*bb4ee6a4SAndroid Build Coastguard Worker     pub ctl_ep_state: ControlEndpointState,
99*bb4ee6a4SAndroid Build Coastguard Worker     pub control_request_setup: UsbRequestSetup,
100*bb4ee6a4SAndroid Build Coastguard Worker     pub executed: bool,
101*bb4ee6a4SAndroid Build Coastguard Worker }
102