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