Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/usb/backend/transfer.rs
5394 views
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 {
21
pub fn new(handle: impl GenericTransferHandle + 'static) -> Self {
22
BackendTransferHandle {
23
handle: Box::new(handle),
24
}
25
}
26
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
42
fn status(&self) -> TransferStatus;
43
/// Returns the actual amount of data transferred, which may be less than the original length.
44
fn actual_length(&self) -> usize;
45
/// Returns a reference to the `TransferBuffer` object.
46
fn buffer(&self) -> &TransferBuffer;
47
/// Sets an optional callback on the transfer to be called when the transfer completes.
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 {
53
fn status(&self) -> TransferStatus {
54
match self {
55
BackendTransferType::HostDevice(transfer) => BackendTransfer::status(transfer),
56
BackendTransferType::FidoDevice(transfer) => BackendTransfer::status(transfer),
57
}
58
}
59
60
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
67
fn buffer(&self) -> &TransferBuffer {
68
match self {
69
BackendTransferType::HostDevice(transfer) => BackendTransfer::buffer(transfer),
70
BackendTransferType::FidoDevice(transfer) => BackendTransfer::buffer(transfer),
71
}
72
}
73
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.
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
103