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