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