1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2024 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 std::mem; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::drop; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::RwLock; 9*bb4ee6a4SAndroid Build Coastguard Worker 10*bb4ee6a4SAndroid Build Coastguard Worker use base::debug; 11*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 12*bb4ee6a4SAndroid Build Coastguard Worker use base::warn; 13*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor; 14*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor; 15*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::ConfigDescriptorTree; 16*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::ControlRequestDataPhaseTransferDirection; 17*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::ControlRequestRecipient; 18*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::DescriptorType; 19*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::DeviceDescriptorTree; 20*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::DeviceSpeed; 21*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::StandardControlRequest; 22*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::Transfer; 23*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::TransferBuffer; 24*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::TransferStatus; 25*bb4ee6a4SAndroid Build Coastguard Worker use usb_util::UsbRequestSetup; 26*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes; 27*bb4ee6a4SAndroid Build Coastguard Worker 28*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::endpoint::ControlEndpointState; 29*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::endpoint::UsbEndpoint; 30*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::error::Error; 31*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::error::Result; 32*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::fido_backend::fido_passthrough::FidoPassthroughDevice; 33*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::fido_backend::transfer::FidoTransfer; 34*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::host_backend::host_device::HostDevice; 35*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::transfer::BackendTransfer; 36*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::transfer::BackendTransferHandle; 37*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::transfer::BackendTransferType; 38*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::transfer::ControlTransferState; 39*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::utils::multi_dispatch; 40*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::backend::utils::update_transfer_state; 41*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::scatter_gather_buffer::ScatterGatherBuffer; 42*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::xhci_backend_device::BackendType; 43*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::xhci_backend_device::UsbDeviceAddress; 44*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::xhci_backend_device::XhciBackendDevice; 45*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::xhci_transfer::XhciTransfer; 46*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::xhci_transfer::XhciTransferState; 47*bb4ee6a4SAndroid Build Coastguard Worker use crate::usb::xhci::xhci_transfer::XhciTransferType; 48*bb4ee6a4SAndroid Build Coastguard Worker use crate::utils::AsyncJobQueue; 49*bb4ee6a4SAndroid Build Coastguard Worker use crate::utils::EventLoop; 50*bb4ee6a4SAndroid Build Coastguard Worker use crate::utils::FailHandle; 51*bb4ee6a4SAndroid Build Coastguard Worker 52*bb4ee6a4SAndroid Build Coastguard Worker /// This enum defines different USB backend implementations that we support. Each implementation 53*bb4ee6a4SAndroid Build Coastguard Worker /// needs to implement the `BackendDevice` trait as we dispatch on the enum based on the type. 54*bb4ee6a4SAndroid Build Coastguard Worker /// Each concrete implementation can take care of setting up the device-specific configurations. 55*bb4ee6a4SAndroid Build Coastguard Worker pub enum BackendDeviceType { 56*bb4ee6a4SAndroid Build Coastguard Worker // Real device on the host, backed by usbdevfs 57*bb4ee6a4SAndroid Build Coastguard Worker HostDevice(HostDevice), 58*bb4ee6a4SAndroid Build Coastguard Worker // Virtual security key implementation 59*bb4ee6a4SAndroid Build Coastguard Worker FidoDevice(FidoPassthroughDevice), 60*bb4ee6a4SAndroid Build Coastguard Worker } 61*bb4ee6a4SAndroid Build Coastguard Worker 62*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for BackendDeviceType { as_raw_descriptor(&self) -> RawDescriptor63*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor { 64*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, as_raw_descriptor) 65*bb4ee6a4SAndroid Build Coastguard Worker } 66*bb4ee6a4SAndroid Build Coastguard Worker } 67*bb4ee6a4SAndroid Build Coastguard Worker 68*bb4ee6a4SAndroid Build Coastguard Worker impl BackendDevice for BackendDeviceType { submit_backend_transfer( &mut self, transfer: BackendTransferType, ) -> Result<BackendTransferHandle>69*bb4ee6a4SAndroid Build Coastguard Worker fn submit_backend_transfer( 70*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 71*bb4ee6a4SAndroid Build Coastguard Worker transfer: BackendTransferType, 72*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<BackendTransferHandle> { 73*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 74*bb4ee6a4SAndroid Build Coastguard Worker self, 75*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 76*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 77*bb4ee6a4SAndroid Build Coastguard Worker submit_backend_transfer, 78*bb4ee6a4SAndroid Build Coastguard Worker transfer 79*bb4ee6a4SAndroid Build Coastguard Worker ) 80*bb4ee6a4SAndroid Build Coastguard Worker } 81*bb4ee6a4SAndroid Build Coastguard Worker detach_event_handler(&self, event_loop: &Arc<EventLoop>) -> Result<()>82*bb4ee6a4SAndroid Build Coastguard Worker fn detach_event_handler(&self, event_loop: &Arc<EventLoop>) -> Result<()> { 83*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 84*bb4ee6a4SAndroid Build Coastguard Worker self, 85*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 86*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 87*bb4ee6a4SAndroid Build Coastguard Worker detach_event_handler, 88*bb4ee6a4SAndroid Build Coastguard Worker event_loop 89*bb4ee6a4SAndroid Build Coastguard Worker ) 90*bb4ee6a4SAndroid Build Coastguard Worker } 91*bb4ee6a4SAndroid Build Coastguard Worker request_transfer_buffer(&mut self, size: usize) -> TransferBuffer92*bb4ee6a4SAndroid Build Coastguard Worker fn request_transfer_buffer(&mut self, size: usize) -> TransferBuffer { 93*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 94*bb4ee6a4SAndroid Build Coastguard Worker self, 95*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 96*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 97*bb4ee6a4SAndroid Build Coastguard Worker request_transfer_buffer, 98*bb4ee6a4SAndroid Build Coastguard Worker size 99*bb4ee6a4SAndroid Build Coastguard Worker ) 100*bb4ee6a4SAndroid Build Coastguard Worker } 101*bb4ee6a4SAndroid Build Coastguard Worker build_bulk_transfer( &mut self, ep_addr: u8, transfer_buffer: TransferBuffer, stream_id: Option<u16>, ) -> Result<BackendTransferType>102*bb4ee6a4SAndroid Build Coastguard Worker fn build_bulk_transfer( 103*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 104*bb4ee6a4SAndroid Build Coastguard Worker ep_addr: u8, 105*bb4ee6a4SAndroid Build Coastguard Worker transfer_buffer: TransferBuffer, 106*bb4ee6a4SAndroid Build Coastguard Worker stream_id: Option<u16>, 107*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<BackendTransferType> { 108*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 109*bb4ee6a4SAndroid Build Coastguard Worker self, 110*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 111*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 112*bb4ee6a4SAndroid Build Coastguard Worker build_bulk_transfer, 113*bb4ee6a4SAndroid Build Coastguard Worker ep_addr, 114*bb4ee6a4SAndroid Build Coastguard Worker transfer_buffer, 115*bb4ee6a4SAndroid Build Coastguard Worker stream_id 116*bb4ee6a4SAndroid Build Coastguard Worker ) 117*bb4ee6a4SAndroid Build Coastguard Worker } 118*bb4ee6a4SAndroid Build Coastguard Worker build_interrupt_transfer( &mut self, ep_addr: u8, transfer_buffer: TransferBuffer, ) -> Result<BackendTransferType>119*bb4ee6a4SAndroid Build Coastguard Worker fn build_interrupt_transfer( 120*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 121*bb4ee6a4SAndroid Build Coastguard Worker ep_addr: u8, 122*bb4ee6a4SAndroid Build Coastguard Worker transfer_buffer: TransferBuffer, 123*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<BackendTransferType> { 124*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 125*bb4ee6a4SAndroid Build Coastguard Worker self, 126*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 127*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 128*bb4ee6a4SAndroid Build Coastguard Worker build_interrupt_transfer, 129*bb4ee6a4SAndroid Build Coastguard Worker ep_addr, 130*bb4ee6a4SAndroid Build Coastguard Worker transfer_buffer 131*bb4ee6a4SAndroid Build Coastguard Worker ) 132*bb4ee6a4SAndroid Build Coastguard Worker } 133*bb4ee6a4SAndroid Build Coastguard Worker get_control_transfer_state(&mut self) -> Arc<RwLock<ControlTransferState>>134*bb4ee6a4SAndroid Build Coastguard Worker fn get_control_transfer_state(&mut self) -> Arc<RwLock<ControlTransferState>> { 135*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 136*bb4ee6a4SAndroid Build Coastguard Worker self, 137*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 138*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 139*bb4ee6a4SAndroid Build Coastguard Worker get_control_transfer_state 140*bb4ee6a4SAndroid Build Coastguard Worker ) 141*bb4ee6a4SAndroid Build Coastguard Worker } 142*bb4ee6a4SAndroid Build Coastguard Worker get_device_state(&mut self) -> Arc<RwLock<DeviceState>>143*bb4ee6a4SAndroid Build Coastguard Worker fn get_device_state(&mut self) -> Arc<RwLock<DeviceState>> { 144*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, get_device_state) 145*bb4ee6a4SAndroid Build Coastguard Worker } 146*bb4ee6a4SAndroid Build Coastguard Worker get_active_config_descriptor(&mut self) -> Result<ConfigDescriptorTree>147*bb4ee6a4SAndroid Build Coastguard Worker fn get_active_config_descriptor(&mut self) -> Result<ConfigDescriptorTree> { 148*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 149*bb4ee6a4SAndroid Build Coastguard Worker self, 150*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 151*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 152*bb4ee6a4SAndroid Build Coastguard Worker get_active_config_descriptor 153*bb4ee6a4SAndroid Build Coastguard Worker ) 154*bb4ee6a4SAndroid Build Coastguard Worker } 155*bb4ee6a4SAndroid Build Coastguard Worker get_config_descriptor(&mut self, config: u8) -> Result<ConfigDescriptorTree>156*bb4ee6a4SAndroid Build Coastguard Worker fn get_config_descriptor(&mut self, config: u8) -> Result<ConfigDescriptorTree> { 157*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 158*bb4ee6a4SAndroid Build Coastguard Worker self, 159*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 160*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 161*bb4ee6a4SAndroid Build Coastguard Worker get_config_descriptor, 162*bb4ee6a4SAndroid Build Coastguard Worker config 163*bb4ee6a4SAndroid Build Coastguard Worker ) 164*bb4ee6a4SAndroid Build Coastguard Worker } 165*bb4ee6a4SAndroid Build Coastguard Worker get_config_descriptor_by_index(&mut self, config_index: u8) -> Result<ConfigDescriptorTree>166*bb4ee6a4SAndroid Build Coastguard Worker fn get_config_descriptor_by_index(&mut self, config_index: u8) -> Result<ConfigDescriptorTree> { 167*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 168*bb4ee6a4SAndroid Build Coastguard Worker self, 169*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 170*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 171*bb4ee6a4SAndroid Build Coastguard Worker get_config_descriptor_by_index, 172*bb4ee6a4SAndroid Build Coastguard Worker config_index 173*bb4ee6a4SAndroid Build Coastguard Worker ) 174*bb4ee6a4SAndroid Build Coastguard Worker } 175*bb4ee6a4SAndroid Build Coastguard Worker get_device_descriptor_tree(&mut self) -> Result<DeviceDescriptorTree>176*bb4ee6a4SAndroid Build Coastguard Worker fn get_device_descriptor_tree(&mut self) -> Result<DeviceDescriptorTree> { 177*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 178*bb4ee6a4SAndroid Build Coastguard Worker self, 179*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 180*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 181*bb4ee6a4SAndroid Build Coastguard Worker get_device_descriptor_tree 182*bb4ee6a4SAndroid Build Coastguard Worker ) 183*bb4ee6a4SAndroid Build Coastguard Worker } 184*bb4ee6a4SAndroid Build Coastguard Worker get_active_configuration(&mut self) -> Result<u8>185*bb4ee6a4SAndroid Build Coastguard Worker fn get_active_configuration(&mut self) -> Result<u8> { 186*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 187*bb4ee6a4SAndroid Build Coastguard Worker self, 188*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 189*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 190*bb4ee6a4SAndroid Build Coastguard Worker get_active_configuration 191*bb4ee6a4SAndroid Build Coastguard Worker ) 192*bb4ee6a4SAndroid Build Coastguard Worker } 193*bb4ee6a4SAndroid Build Coastguard Worker set_active_configuration(&mut self, config: u8) -> Result<()>194*bb4ee6a4SAndroid Build Coastguard Worker fn set_active_configuration(&mut self, config: u8) -> Result<()> { 195*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 196*bb4ee6a4SAndroid Build Coastguard Worker self, 197*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 198*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 199*bb4ee6a4SAndroid Build Coastguard Worker set_active_configuration, 200*bb4ee6a4SAndroid Build Coastguard Worker config 201*bb4ee6a4SAndroid Build Coastguard Worker ) 202*bb4ee6a4SAndroid Build Coastguard Worker } 203*bb4ee6a4SAndroid Build Coastguard Worker clear_feature(&mut self, value: u16, index: u16) -> Result<TransferStatus>204*bb4ee6a4SAndroid Build Coastguard Worker fn clear_feature(&mut self, value: u16, index: u16) -> Result<TransferStatus> { 205*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 206*bb4ee6a4SAndroid Build Coastguard Worker self, 207*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 208*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 209*bb4ee6a4SAndroid Build Coastguard Worker clear_feature, 210*bb4ee6a4SAndroid Build Coastguard Worker value, 211*bb4ee6a4SAndroid Build Coastguard Worker index 212*bb4ee6a4SAndroid Build Coastguard Worker ) 213*bb4ee6a4SAndroid Build Coastguard Worker } 214*bb4ee6a4SAndroid Build Coastguard Worker create_endpoints(&mut self, config_descriptor: &ConfigDescriptorTree) -> Result<()>215*bb4ee6a4SAndroid Build Coastguard Worker fn create_endpoints(&mut self, config_descriptor: &ConfigDescriptorTree) -> Result<()> { 216*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 217*bb4ee6a4SAndroid Build Coastguard Worker self, 218*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 219*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 220*bb4ee6a4SAndroid Build Coastguard Worker create_endpoints, 221*bb4ee6a4SAndroid Build Coastguard Worker config_descriptor 222*bb4ee6a4SAndroid Build Coastguard Worker ) 223*bb4ee6a4SAndroid Build Coastguard Worker } 224*bb4ee6a4SAndroid Build Coastguard Worker } 225*bb4ee6a4SAndroid Build Coastguard Worker 226*bb4ee6a4SAndroid Build Coastguard Worker impl XhciBackendDevice for BackendDeviceType { get_backend_type(&self) -> BackendType227*bb4ee6a4SAndroid Build Coastguard Worker fn get_backend_type(&self) -> BackendType { 228*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, get_backend_type) 229*bb4ee6a4SAndroid Build Coastguard Worker } 230*bb4ee6a4SAndroid Build Coastguard Worker get_vid(&self) -> u16231*bb4ee6a4SAndroid Build Coastguard Worker fn get_vid(&self) -> u16 { 232*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, get_vid) 233*bb4ee6a4SAndroid Build Coastguard Worker } 234*bb4ee6a4SAndroid Build Coastguard Worker get_pid(&self) -> u16235*bb4ee6a4SAndroid Build Coastguard Worker fn get_pid(&self) -> u16 { 236*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, get_pid) 237*bb4ee6a4SAndroid Build Coastguard Worker } 238*bb4ee6a4SAndroid Build Coastguard Worker set_address(&mut self, address: UsbDeviceAddress)239*bb4ee6a4SAndroid Build Coastguard Worker fn set_address(&mut self, address: UsbDeviceAddress) { 240*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, set_address, address) 241*bb4ee6a4SAndroid Build Coastguard Worker } 242*bb4ee6a4SAndroid Build Coastguard Worker reset(&mut self) -> Result<()>243*bb4ee6a4SAndroid Build Coastguard Worker fn reset(&mut self) -> Result<()> { 244*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, reset) 245*bb4ee6a4SAndroid Build Coastguard Worker } 246*bb4ee6a4SAndroid Build Coastguard Worker get_speed(&self) -> Option<DeviceSpeed>247*bb4ee6a4SAndroid Build Coastguard Worker fn get_speed(&self) -> Option<DeviceSpeed> { 248*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, get_speed) 249*bb4ee6a4SAndroid Build Coastguard Worker } 250*bb4ee6a4SAndroid Build Coastguard Worker alloc_streams(&self, ep: u8, num_streams: u16) -> Result<()>251*bb4ee6a4SAndroid Build Coastguard Worker fn alloc_streams(&self, ep: u8, num_streams: u16) -> Result<()> { 252*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!( 253*bb4ee6a4SAndroid Build Coastguard Worker self, 254*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType, 255*bb4ee6a4SAndroid Build Coastguard Worker HostDevice FidoDevice, 256*bb4ee6a4SAndroid Build Coastguard Worker alloc_streams, 257*bb4ee6a4SAndroid Build Coastguard Worker ep, 258*bb4ee6a4SAndroid Build Coastguard Worker num_streams 259*bb4ee6a4SAndroid Build Coastguard Worker ) 260*bb4ee6a4SAndroid Build Coastguard Worker } 261*bb4ee6a4SAndroid Build Coastguard Worker free_streams(&self, ep: u8) -> Result<()>262*bb4ee6a4SAndroid Build Coastguard Worker fn free_streams(&self, ep: u8) -> Result<()> { 263*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, free_streams, ep) 264*bb4ee6a4SAndroid Build Coastguard Worker } 265*bb4ee6a4SAndroid Build Coastguard Worker stop(&mut self)266*bb4ee6a4SAndroid Build Coastguard Worker fn stop(&mut self) { 267*bb4ee6a4SAndroid Build Coastguard Worker multi_dispatch!(self, BackendDeviceType, HostDevice FidoDevice, stop) 268*bb4ee6a4SAndroid Build Coastguard Worker } 269*bb4ee6a4SAndroid Build Coastguard Worker } 270*bb4ee6a4SAndroid Build Coastguard Worker 271*bb4ee6a4SAndroid Build Coastguard Worker pub struct DeviceState { 272*bb4ee6a4SAndroid Build Coastguard Worker pub fail_handle: Arc<dyn FailHandle>, 273*bb4ee6a4SAndroid Build Coastguard Worker // Endpoints only contains data endpoints (1 to 30). Control transfers are handled at device 274*bb4ee6a4SAndroid Build Coastguard Worker // level. 275*bb4ee6a4SAndroid Build Coastguard Worker pub endpoints: Vec<UsbEndpoint>, 276*bb4ee6a4SAndroid Build Coastguard Worker pub initialized: bool, 277*bb4ee6a4SAndroid Build Coastguard Worker pub job_queue: Arc<AsyncJobQueue>, 278*bb4ee6a4SAndroid Build Coastguard Worker } 279*bb4ee6a4SAndroid Build Coastguard Worker 280*bb4ee6a4SAndroid Build Coastguard Worker impl DeviceState { new(fail_handle: Arc<dyn FailHandle>, job_queue: Arc<AsyncJobQueue>) -> Self281*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(fail_handle: Arc<dyn FailHandle>, job_queue: Arc<AsyncJobQueue>) -> Self { 282*bb4ee6a4SAndroid Build Coastguard Worker DeviceState { 283*bb4ee6a4SAndroid Build Coastguard Worker fail_handle, 284*bb4ee6a4SAndroid Build Coastguard Worker endpoints: vec![], 285*bb4ee6a4SAndroid Build Coastguard Worker initialized: false, 286*bb4ee6a4SAndroid Build Coastguard Worker job_queue, 287*bb4ee6a4SAndroid Build Coastguard Worker } 288*bb4ee6a4SAndroid Build Coastguard Worker } 289*bb4ee6a4SAndroid Build Coastguard Worker } 290*bb4ee6a4SAndroid Build Coastguard Worker 291*bb4ee6a4SAndroid Build Coastguard Worker impl BackendDeviceType { 292*bb4ee6a4SAndroid Build Coastguard Worker // Check for requests that should be intercepted and handled in a generic way 293*bb4ee6a4SAndroid Build Coastguard Worker // rather than passed directly to the backend device for device-specific implementations. 294*bb4ee6a4SAndroid Build Coastguard Worker // Returns true if the request has been intercepted or false if the request 295*bb4ee6a4SAndroid Build Coastguard Worker // should be passed through. intercepted_control_transfer( &mut self, xhci_transfer: &XhciTransfer, buffer: &Option<ScatterGatherBuffer>, control_request_setup: &UsbRequestSetup, ) -> Result<bool>296*bb4ee6a4SAndroid Build Coastguard Worker fn intercepted_control_transfer( 297*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 298*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer: &XhciTransfer, 299*bb4ee6a4SAndroid Build Coastguard Worker buffer: &Option<ScatterGatherBuffer>, 300*bb4ee6a4SAndroid Build Coastguard Worker control_request_setup: &UsbRequestSetup, 301*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<bool> { 302*bb4ee6a4SAndroid Build Coastguard Worker let direction = control_request_setup.get_direction(); 303*bb4ee6a4SAndroid Build Coastguard Worker let recipient = control_request_setup.get_recipient(); 304*bb4ee6a4SAndroid Build Coastguard Worker let standard_request = if let Some(req) = control_request_setup.get_standard_request() { 305*bb4ee6a4SAndroid Build Coastguard Worker req 306*bb4ee6a4SAndroid Build Coastguard Worker } else { 307*bb4ee6a4SAndroid Build Coastguard Worker // Unknown control requests will be passed through to the device. 308*bb4ee6a4SAndroid Build Coastguard Worker return Ok(false); 309*bb4ee6a4SAndroid Build Coastguard Worker }; 310*bb4ee6a4SAndroid Build Coastguard Worker 311*bb4ee6a4SAndroid Build Coastguard Worker let (status, bytes_transferred) = match (standard_request, recipient, direction) { 312*bb4ee6a4SAndroid Build Coastguard Worker ( 313*bb4ee6a4SAndroid Build Coastguard Worker StandardControlRequest::SetAddress, 314*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestRecipient::Device, 315*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestDataPhaseTransferDirection::HostToDevice, 316*bb4ee6a4SAndroid Build Coastguard Worker ) => { 317*bb4ee6a4SAndroid Build Coastguard Worker usb_trace!("handling set address"); 318*bb4ee6a4SAndroid Build Coastguard Worker let addr = control_request_setup.value as u32; 319*bb4ee6a4SAndroid Build Coastguard Worker self.set_address(addr); 320*bb4ee6a4SAndroid Build Coastguard Worker (TransferStatus::Completed, 0) 321*bb4ee6a4SAndroid Build Coastguard Worker } 322*bb4ee6a4SAndroid Build Coastguard Worker ( 323*bb4ee6a4SAndroid Build Coastguard Worker StandardControlRequest::SetConfiguration, 324*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestRecipient::Device, 325*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestDataPhaseTransferDirection::HostToDevice, 326*bb4ee6a4SAndroid Build Coastguard Worker ) => { 327*bb4ee6a4SAndroid Build Coastguard Worker usb_trace!("handling set config"); 328*bb4ee6a4SAndroid Build Coastguard Worker let config = (control_request_setup.value & 0xff) as u8; 329*bb4ee6a4SAndroid Build Coastguard Worker match self.set_config(config) { 330*bb4ee6a4SAndroid Build Coastguard Worker Ok(status) => (status, 0), 331*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 332*bb4ee6a4SAndroid Build Coastguard Worker error!("set config error: {}", e); 333*bb4ee6a4SAndroid Build Coastguard Worker (TransferStatus::Stalled, 0) 334*bb4ee6a4SAndroid Build Coastguard Worker } 335*bb4ee6a4SAndroid Build Coastguard Worker } 336*bb4ee6a4SAndroid Build Coastguard Worker } 337*bb4ee6a4SAndroid Build Coastguard Worker ( 338*bb4ee6a4SAndroid Build Coastguard Worker StandardControlRequest::SetInterface, 339*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestRecipient::Interface, 340*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestDataPhaseTransferDirection::HostToDevice, 341*bb4ee6a4SAndroid Build Coastguard Worker ) => { 342*bb4ee6a4SAndroid Build Coastguard Worker usb_trace!("handling set interface"); 343*bb4ee6a4SAndroid Build Coastguard Worker match self { 344*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType::HostDevice(host_device) => match host_device.set_interface( 345*bb4ee6a4SAndroid Build Coastguard Worker control_request_setup.index as u8, 346*bb4ee6a4SAndroid Build Coastguard Worker control_request_setup.value as u8, 347*bb4ee6a4SAndroid Build Coastguard Worker ) { 348*bb4ee6a4SAndroid Build Coastguard Worker Ok(status) => (status, 0), 349*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 350*bb4ee6a4SAndroid Build Coastguard Worker error!("set interface error: {}", e); 351*bb4ee6a4SAndroid Build Coastguard Worker (TransferStatus::Stalled, 0) 352*bb4ee6a4SAndroid Build Coastguard Worker } 353*bb4ee6a4SAndroid Build Coastguard Worker }, 354*bb4ee6a4SAndroid Build Coastguard Worker _ => { 355*bb4ee6a4SAndroid Build Coastguard Worker // Nothing to do for non-host devices 356*bb4ee6a4SAndroid Build Coastguard Worker (TransferStatus::Completed, 0) 357*bb4ee6a4SAndroid Build Coastguard Worker } 358*bb4ee6a4SAndroid Build Coastguard Worker } 359*bb4ee6a4SAndroid Build Coastguard Worker } 360*bb4ee6a4SAndroid Build Coastguard Worker ( 361*bb4ee6a4SAndroid Build Coastguard Worker StandardControlRequest::ClearFeature, 362*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestRecipient::Endpoint, 363*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestDataPhaseTransferDirection::HostToDevice, 364*bb4ee6a4SAndroid Build Coastguard Worker ) => { 365*bb4ee6a4SAndroid Build Coastguard Worker usb_trace!("handling clear feature"); 366*bb4ee6a4SAndroid Build Coastguard Worker match self.clear_feature(control_request_setup.value, control_request_setup.index) { 367*bb4ee6a4SAndroid Build Coastguard Worker Ok(status) => (status, 0), 368*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 369*bb4ee6a4SAndroid Build Coastguard Worker error!("clear feature error: {}", e); 370*bb4ee6a4SAndroid Build Coastguard Worker (TransferStatus::Stalled, 0) 371*bb4ee6a4SAndroid Build Coastguard Worker } 372*bb4ee6a4SAndroid Build Coastguard Worker } 373*bb4ee6a4SAndroid Build Coastguard Worker } 374*bb4ee6a4SAndroid Build Coastguard Worker ( 375*bb4ee6a4SAndroid Build Coastguard Worker StandardControlRequest::GetDescriptor, 376*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestRecipient::Device, 377*bb4ee6a4SAndroid Build Coastguard Worker ControlRequestDataPhaseTransferDirection::DeviceToHost, 378*bb4ee6a4SAndroid Build Coastguard Worker ) => { 379*bb4ee6a4SAndroid Build Coastguard Worker let descriptor_type = (control_request_setup.value >> 8) as u8; 380*bb4ee6a4SAndroid Build Coastguard Worker if descriptor_type == DescriptorType::Configuration as u8 { 381*bb4ee6a4SAndroid Build Coastguard Worker let buffer = if let Some(buffer) = buffer { 382*bb4ee6a4SAndroid Build Coastguard Worker buffer 383*bb4ee6a4SAndroid Build Coastguard Worker } else { 384*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::MissingRequiredBuffer); 385*bb4ee6a4SAndroid Build Coastguard Worker }; 386*bb4ee6a4SAndroid Build Coastguard Worker 387*bb4ee6a4SAndroid Build Coastguard Worker match self { 388*bb4ee6a4SAndroid Build Coastguard Worker // If it's a host device we filter the descriptor tree 389*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType::HostDevice(host_device) => { 390*bb4ee6a4SAndroid Build Coastguard Worker match host_device.get_config_descriptor_filtered( 391*bb4ee6a4SAndroid Build Coastguard Worker buffer, 392*bb4ee6a4SAndroid Build Coastguard Worker control_request_setup.value as u8, 393*bb4ee6a4SAndroid Build Coastguard Worker ) { 394*bb4ee6a4SAndroid Build Coastguard Worker Ok((status, b)) => (status, b), 395*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 396*bb4ee6a4SAndroid Build Coastguard Worker error!("get descriptor error: {}", e); 397*bb4ee6a4SAndroid Build Coastguard Worker (TransferStatus::Stalled, 0) 398*bb4ee6a4SAndroid Build Coastguard Worker } 399*bb4ee6a4SAndroid Build Coastguard Worker } 400*bb4ee6a4SAndroid Build Coastguard Worker } 401*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType::FidoDevice(fido_passthrough) => { 402*bb4ee6a4SAndroid Build Coastguard Worker match fido_passthrough 403*bb4ee6a4SAndroid Build Coastguard Worker .get_config_descriptor_by_index(control_request_setup.value as u8) 404*bb4ee6a4SAndroid Build Coastguard Worker { 405*bb4ee6a4SAndroid Build Coastguard Worker Ok(descriptor_tree) => { 406*bb4ee6a4SAndroid Build Coastguard Worker let device_descriptor = 407*bb4ee6a4SAndroid Build Coastguard Worker fido_passthrough.get_device_descriptor_tree()?; 408*bb4ee6a4SAndroid Build Coastguard Worker let offset = descriptor_tree.offset(); 409*bb4ee6a4SAndroid Build Coastguard Worker let data = device_descriptor.raw() 410*bb4ee6a4SAndroid Build Coastguard Worker [offset..offset + descriptor_tree.wTotalLength as usize] 411*bb4ee6a4SAndroid Build Coastguard Worker .to_vec(); 412*bb4ee6a4SAndroid Build Coastguard Worker let bytes = buffer.write(&data).map_err(Error::WriteBuffer)?; 413*bb4ee6a4SAndroid Build Coastguard Worker (TransferStatus::Completed, bytes as u32) 414*bb4ee6a4SAndroid Build Coastguard Worker } 415*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 416*bb4ee6a4SAndroid Build Coastguard Worker error!("get fido descriptor error: {}", e); 417*bb4ee6a4SAndroid Build Coastguard Worker (TransferStatus::Stalled, 0) 418*bb4ee6a4SAndroid Build Coastguard Worker } 419*bb4ee6a4SAndroid Build Coastguard Worker } 420*bb4ee6a4SAndroid Build Coastguard Worker } 421*bb4ee6a4SAndroid Build Coastguard Worker } 422*bb4ee6a4SAndroid Build Coastguard Worker } else { 423*bb4ee6a4SAndroid Build Coastguard Worker return Ok(false); 424*bb4ee6a4SAndroid Build Coastguard Worker } 425*bb4ee6a4SAndroid Build Coastguard Worker } 426*bb4ee6a4SAndroid Build Coastguard Worker _ => { 427*bb4ee6a4SAndroid Build Coastguard Worker // Other requests will be passed through to the device. 428*bb4ee6a4SAndroid Build Coastguard Worker return Ok(false); 429*bb4ee6a4SAndroid Build Coastguard Worker } 430*bb4ee6a4SAndroid Build Coastguard Worker }; 431*bb4ee6a4SAndroid Build Coastguard Worker 432*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer 433*bb4ee6a4SAndroid Build Coastguard Worker .on_transfer_complete(&status, bytes_transferred) 434*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::TransferComplete)?; 435*bb4ee6a4SAndroid Build Coastguard Worker 436*bb4ee6a4SAndroid Build Coastguard Worker Ok(true) 437*bb4ee6a4SAndroid Build Coastguard Worker } 438*bb4ee6a4SAndroid Build Coastguard Worker execute_control_transfer( &mut self, xhci_transfer: Arc<XhciTransfer>, buffer: Option<ScatterGatherBuffer>, control_request_setup: &UsbRequestSetup, ) -> Result<()>439*bb4ee6a4SAndroid Build Coastguard Worker fn execute_control_transfer( 440*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 441*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer: Arc<XhciTransfer>, 442*bb4ee6a4SAndroid Build Coastguard Worker buffer: Option<ScatterGatherBuffer>, 443*bb4ee6a4SAndroid Build Coastguard Worker control_request_setup: &UsbRequestSetup, 444*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> { 445*bb4ee6a4SAndroid Build Coastguard Worker if self.intercepted_control_transfer(&xhci_transfer, &buffer, control_request_setup)? { 446*bb4ee6a4SAndroid Build Coastguard Worker return Ok(()); 447*bb4ee6a4SAndroid Build Coastguard Worker } 448*bb4ee6a4SAndroid Build Coastguard Worker 449*bb4ee6a4SAndroid Build Coastguard Worker // Allocate a buffer for the control transfer. 450*bb4ee6a4SAndroid Build Coastguard Worker // This buffer will hold a UsbRequestSetup struct followed by the data. 451*bb4ee6a4SAndroid Build Coastguard Worker let control_buffer_len = 452*bb4ee6a4SAndroid Build Coastguard Worker mem::size_of::<UsbRequestSetup>() + control_request_setup.length as usize; 453*bb4ee6a4SAndroid Build Coastguard Worker let mut control_buffer = vec![0u8; control_buffer_len]; 454*bb4ee6a4SAndroid Build Coastguard Worker 455*bb4ee6a4SAndroid Build Coastguard Worker // Copy the control request header. 456*bb4ee6a4SAndroid Build Coastguard Worker control_buffer[..mem::size_of::<UsbRequestSetup>()] 457*bb4ee6a4SAndroid Build Coastguard Worker .copy_from_slice(control_request_setup.as_bytes()); 458*bb4ee6a4SAndroid Build Coastguard Worker 459*bb4ee6a4SAndroid Build Coastguard Worker let direction = control_request_setup.get_direction(); 460*bb4ee6a4SAndroid Build Coastguard Worker let buffer = if direction == ControlRequestDataPhaseTransferDirection::HostToDevice { 461*bb4ee6a4SAndroid Build Coastguard Worker if let Some(buffer) = buffer { 462*bb4ee6a4SAndroid Build Coastguard Worker buffer 463*bb4ee6a4SAndroid Build Coastguard Worker .read(&mut control_buffer[mem::size_of::<UsbRequestSetup>()..]) 464*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::ReadBuffer)?; 465*bb4ee6a4SAndroid Build Coastguard Worker } 466*bb4ee6a4SAndroid Build Coastguard Worker // buffer is consumed here for HostToDevice transfers. 467*bb4ee6a4SAndroid Build Coastguard Worker None 468*bb4ee6a4SAndroid Build Coastguard Worker } else { 469*bb4ee6a4SAndroid Build Coastguard Worker // buffer will be used later in the callback for DeviceToHost transfers. 470*bb4ee6a4SAndroid Build Coastguard Worker buffer 471*bb4ee6a4SAndroid Build Coastguard Worker }; 472*bb4ee6a4SAndroid Build Coastguard Worker 473*bb4ee6a4SAndroid Build Coastguard Worker // TODO(morg): Refactor this code so it doesn't need to match on each implementation type 474*bb4ee6a4SAndroid Build Coastguard Worker let mut control_transfer = match self { 475*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType::HostDevice(_) => BackendTransferType::HostDevice( 476*bb4ee6a4SAndroid Build Coastguard Worker Transfer::new_control(TransferBuffer::Vector(control_buffer)) 477*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::CreateTransfer)?, 478*bb4ee6a4SAndroid Build Coastguard Worker ), 479*bb4ee6a4SAndroid Build Coastguard Worker BackendDeviceType::FidoDevice(_) => BackendTransferType::FidoDevice(FidoTransfer::new( 480*bb4ee6a4SAndroid Build Coastguard Worker 0, 481*bb4ee6a4SAndroid Build Coastguard Worker TransferBuffer::Vector(control_buffer), 482*bb4ee6a4SAndroid Build Coastguard Worker )), 483*bb4ee6a4SAndroid Build Coastguard Worker }; 484*bb4ee6a4SAndroid Build Coastguard Worker 485*bb4ee6a4SAndroid Build Coastguard Worker let tmp_transfer = xhci_transfer.clone(); 486*bb4ee6a4SAndroid Build Coastguard Worker let callback = move |t: BackendTransferType| { 487*bb4ee6a4SAndroid Build Coastguard Worker usb_trace!("setup token control transfer callback"); 488*bb4ee6a4SAndroid Build Coastguard Worker update_transfer_state(&xhci_transfer, t.status())?; 489*bb4ee6a4SAndroid Build Coastguard Worker let state = xhci_transfer.state().lock(); 490*bb4ee6a4SAndroid Build Coastguard Worker match *state { 491*bb4ee6a4SAndroid Build Coastguard Worker XhciTransferState::Cancelled => { 492*bb4ee6a4SAndroid Build Coastguard Worker drop(state); 493*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer 494*bb4ee6a4SAndroid Build Coastguard Worker .on_transfer_complete(&TransferStatus::Cancelled, 0) 495*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::TransferComplete)?; 496*bb4ee6a4SAndroid Build Coastguard Worker } 497*bb4ee6a4SAndroid Build Coastguard Worker XhciTransferState::Completed => { 498*bb4ee6a4SAndroid Build Coastguard Worker let status = t.status(); 499*bb4ee6a4SAndroid Build Coastguard Worker let actual_length = t.actual_length(); 500*bb4ee6a4SAndroid Build Coastguard Worker if direction == ControlRequestDataPhaseTransferDirection::DeviceToHost { 501*bb4ee6a4SAndroid Build Coastguard Worker match t.buffer() { 502*bb4ee6a4SAndroid Build Coastguard Worker TransferBuffer::Vector(v) => { 503*bb4ee6a4SAndroid Build Coastguard Worker if let Some(control_request_data) = 504*bb4ee6a4SAndroid Build Coastguard Worker v.get(mem::size_of::<UsbRequestSetup>()..) 505*bb4ee6a4SAndroid Build Coastguard Worker { 506*bb4ee6a4SAndroid Build Coastguard Worker if let Some(buffer) = &buffer { 507*bb4ee6a4SAndroid Build Coastguard Worker buffer 508*bb4ee6a4SAndroid Build Coastguard Worker .write(control_request_data) 509*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::WriteBuffer)?; 510*bb4ee6a4SAndroid Build Coastguard Worker } 511*bb4ee6a4SAndroid Build Coastguard Worker } 512*bb4ee6a4SAndroid Build Coastguard Worker } 513*bb4ee6a4SAndroid Build Coastguard Worker // control buffer must use a vector for buffer 514*bb4ee6a4SAndroid Build Coastguard Worker TransferBuffer::Dma(_) => unreachable!(), 515*bb4ee6a4SAndroid Build Coastguard Worker } 516*bb4ee6a4SAndroid Build Coastguard Worker } 517*bb4ee6a4SAndroid Build Coastguard Worker drop(state); 518*bb4ee6a4SAndroid Build Coastguard Worker debug!( 519*bb4ee6a4SAndroid Build Coastguard Worker "xhci transfer completed with actual length {}", 520*bb4ee6a4SAndroid Build Coastguard Worker actual_length 521*bb4ee6a4SAndroid Build Coastguard Worker ); 522*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer 523*bb4ee6a4SAndroid Build Coastguard Worker .on_transfer_complete(&status, actual_length as u32) 524*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::TransferComplete)?; 525*bb4ee6a4SAndroid Build Coastguard Worker } 526*bb4ee6a4SAndroid Build Coastguard Worker _ => { 527*bb4ee6a4SAndroid Build Coastguard Worker // update_transfer_state is already invoked before match. 528*bb4ee6a4SAndroid Build Coastguard Worker // This transfer could only be `Cancelled` or `Completed`. 529*bb4ee6a4SAndroid Build Coastguard Worker // Any other state means there is a bug in crosvm implementation. 530*bb4ee6a4SAndroid Build Coastguard Worker error!("should not take this branch"); 531*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::BadXhciTransferState); 532*bb4ee6a4SAndroid Build Coastguard Worker } 533*bb4ee6a4SAndroid Build Coastguard Worker } 534*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 535*bb4ee6a4SAndroid Build Coastguard Worker }; 536*bb4ee6a4SAndroid Build Coastguard Worker 537*bb4ee6a4SAndroid Build Coastguard Worker let fail_handle = self.get_device_state().write().unwrap().fail_handle.clone(); 538*bb4ee6a4SAndroid Build Coastguard Worker control_transfer.set_callback(move |t: BackendTransferType| match callback(t) { 539*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => {} 540*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 541*bb4ee6a4SAndroid Build Coastguard Worker error!("control transfer callback failed {:?}", e); 542*bb4ee6a4SAndroid Build Coastguard Worker fail_handle.fail(); 543*bb4ee6a4SAndroid Build Coastguard Worker } 544*bb4ee6a4SAndroid Build Coastguard Worker }); 545*bb4ee6a4SAndroid Build Coastguard Worker // Create a temporary binding for the rwlock 546*bb4ee6a4SAndroid Build Coastguard Worker let device_state_binding = self.get_device_state(); 547*bb4ee6a4SAndroid Build Coastguard Worker // Acquire the lock as a reader 548*bb4ee6a4SAndroid Build Coastguard Worker let device_state_lock = device_state_binding.read().unwrap(); 549*bb4ee6a4SAndroid Build Coastguard Worker self.submit_transfer( 550*bb4ee6a4SAndroid Build Coastguard Worker device_state_lock.fail_handle.clone(), 551*bb4ee6a4SAndroid Build Coastguard Worker &device_state_lock.job_queue, 552*bb4ee6a4SAndroid Build Coastguard Worker tmp_transfer, 553*bb4ee6a4SAndroid Build Coastguard Worker control_transfer, 554*bb4ee6a4SAndroid Build Coastguard Worker ) 555*bb4ee6a4SAndroid Build Coastguard Worker } 556*bb4ee6a4SAndroid Build Coastguard Worker handle_control_transfer(&mut self, transfer: XhciTransfer) -> Result<()>557*bb4ee6a4SAndroid Build Coastguard Worker fn handle_control_transfer(&mut self, transfer: XhciTransfer) -> Result<()> { 558*bb4ee6a4SAndroid Build Coastguard Worker let xhci_transfer = Arc::new(transfer); 559*bb4ee6a4SAndroid Build Coastguard Worker let transfer_type = xhci_transfer 560*bb4ee6a4SAndroid Build Coastguard Worker .get_transfer_type() 561*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::GetXhciTransferType)?; 562*bb4ee6a4SAndroid Build Coastguard Worker let control_transfer_state_binding = self.get_control_transfer_state(); 563*bb4ee6a4SAndroid Build Coastguard Worker let mut control_transfer_state = control_transfer_state_binding.write().unwrap(); 564*bb4ee6a4SAndroid Build Coastguard Worker match transfer_type { 565*bb4ee6a4SAndroid Build Coastguard Worker XhciTransferType::SetupStage => { 566*bb4ee6a4SAndroid Build Coastguard Worker let setup = xhci_transfer 567*bb4ee6a4SAndroid Build Coastguard Worker .create_usb_request_setup() 568*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::CreateUsbRequestSetup)?; 569*bb4ee6a4SAndroid Build Coastguard Worker if control_transfer_state.ctl_ep_state != ControlEndpointState::SetupStage { 570*bb4ee6a4SAndroid Build Coastguard Worker error!("Control endpoint is in an inconsistant state"); 571*bb4ee6a4SAndroid Build Coastguard Worker return Ok(()); 572*bb4ee6a4SAndroid Build Coastguard Worker } 573*bb4ee6a4SAndroid Build Coastguard Worker usb_trace!("setup stage: setup buffer: {:?}", setup); 574*bb4ee6a4SAndroid Build Coastguard Worker control_transfer_state.control_request_setup = setup; 575*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer 576*bb4ee6a4SAndroid Build Coastguard Worker .on_transfer_complete(&TransferStatus::Completed, 0) 577*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::TransferComplete)?; 578*bb4ee6a4SAndroid Build Coastguard Worker control_transfer_state.ctl_ep_state = ControlEndpointState::DataStage; 579*bb4ee6a4SAndroid Build Coastguard Worker } 580*bb4ee6a4SAndroid Build Coastguard Worker XhciTransferType::DataStage => { 581*bb4ee6a4SAndroid Build Coastguard Worker if control_transfer_state.ctl_ep_state != ControlEndpointState::DataStage { 582*bb4ee6a4SAndroid Build Coastguard Worker error!("Control endpoint is in an inconsistant state"); 583*bb4ee6a4SAndroid Build Coastguard Worker return Ok(()); 584*bb4ee6a4SAndroid Build Coastguard Worker } 585*bb4ee6a4SAndroid Build Coastguard Worker // Requests with a DataStage will be executed here. 586*bb4ee6a4SAndroid Build Coastguard Worker // Requests without a DataStage will be executed in StatusStage. 587*bb4ee6a4SAndroid Build Coastguard Worker let buffer = xhci_transfer.create_buffer().map_err(Error::CreateBuffer)?; 588*bb4ee6a4SAndroid Build Coastguard Worker self.execute_control_transfer( 589*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer, 590*bb4ee6a4SAndroid Build Coastguard Worker Some(buffer), 591*bb4ee6a4SAndroid Build Coastguard Worker &control_transfer_state.control_request_setup, 592*bb4ee6a4SAndroid Build Coastguard Worker )?; 593*bb4ee6a4SAndroid Build Coastguard Worker control_transfer_state.executed = true; 594*bb4ee6a4SAndroid Build Coastguard Worker control_transfer_state.ctl_ep_state = ControlEndpointState::StatusStage; 595*bb4ee6a4SAndroid Build Coastguard Worker } 596*bb4ee6a4SAndroid Build Coastguard Worker XhciTransferType::StatusStage => { 597*bb4ee6a4SAndroid Build Coastguard Worker if control_transfer_state.ctl_ep_state == ControlEndpointState::SetupStage { 598*bb4ee6a4SAndroid Build Coastguard Worker error!("Control endpoint is in an inconsistant state"); 599*bb4ee6a4SAndroid Build Coastguard Worker return Ok(()); 600*bb4ee6a4SAndroid Build Coastguard Worker } 601*bb4ee6a4SAndroid Build Coastguard Worker if control_transfer_state.executed { 602*bb4ee6a4SAndroid Build Coastguard Worker // Request was already executed during DataStage. 603*bb4ee6a4SAndroid Build Coastguard Worker // Just complete the StatusStage transfer. 604*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer 605*bb4ee6a4SAndroid Build Coastguard Worker .on_transfer_complete(&TransferStatus::Completed, 0) 606*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::TransferComplete)?; 607*bb4ee6a4SAndroid Build Coastguard Worker } else { 608*bb4ee6a4SAndroid Build Coastguard Worker // Execute the request now since there was no DataStage. 609*bb4ee6a4SAndroid Build Coastguard Worker self.execute_control_transfer( 610*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer, 611*bb4ee6a4SAndroid Build Coastguard Worker None, 612*bb4ee6a4SAndroid Build Coastguard Worker &control_transfer_state.control_request_setup, 613*bb4ee6a4SAndroid Build Coastguard Worker )?; 614*bb4ee6a4SAndroid Build Coastguard Worker } 615*bb4ee6a4SAndroid Build Coastguard Worker control_transfer_state.executed = false; 616*bb4ee6a4SAndroid Build Coastguard Worker control_transfer_state.ctl_ep_state = ControlEndpointState::SetupStage; 617*bb4ee6a4SAndroid Build Coastguard Worker } 618*bb4ee6a4SAndroid Build Coastguard Worker _ => { 619*bb4ee6a4SAndroid Build Coastguard Worker // Non control transfer should not be handled in this function. 620*bb4ee6a4SAndroid Build Coastguard Worker error!( 621*bb4ee6a4SAndroid Build Coastguard Worker "Non control {} transfer sent to control endpoint.", 622*bb4ee6a4SAndroid Build Coastguard Worker transfer_type, 623*bb4ee6a4SAndroid Build Coastguard Worker ); 624*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer 625*bb4ee6a4SAndroid Build Coastguard Worker .on_transfer_complete(&TransferStatus::Completed, 0) 626*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::TransferComplete)?; 627*bb4ee6a4SAndroid Build Coastguard Worker } 628*bb4ee6a4SAndroid Build Coastguard Worker } 629*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 630*bb4ee6a4SAndroid Build Coastguard Worker } 631*bb4ee6a4SAndroid Build Coastguard Worker set_config(&mut self, config: u8) -> Result<TransferStatus>632*bb4ee6a4SAndroid Build Coastguard Worker fn set_config(&mut self, config: u8) -> Result<TransferStatus> { 633*bb4ee6a4SAndroid Build Coastguard Worker // It's a standard, set_config, device request. 634*bb4ee6a4SAndroid Build Coastguard Worker usb_trace!("set_config: {}", config); 635*bb4ee6a4SAndroid Build Coastguard Worker 636*bb4ee6a4SAndroid Build Coastguard Worker if let BackendDeviceType::HostDevice(host_device) = self { 637*bb4ee6a4SAndroid Build Coastguard Worker host_device.release_interfaces(); 638*bb4ee6a4SAndroid Build Coastguard Worker } 639*bb4ee6a4SAndroid Build Coastguard Worker 640*bb4ee6a4SAndroid Build Coastguard Worker let cur_config = match self.get_active_configuration() { 641*bb4ee6a4SAndroid Build Coastguard Worker Ok(c) => Some(c), 642*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 643*bb4ee6a4SAndroid Build Coastguard Worker // The device may be in the default state, in which case 644*bb4ee6a4SAndroid Build Coastguard Worker // GET_CONFIGURATION may fail. Assume the device needs to be 645*bb4ee6a4SAndroid Build Coastguard Worker // reconfigured. 646*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to get active configuration: {}", e); 647*bb4ee6a4SAndroid Build Coastguard Worker None 648*bb4ee6a4SAndroid Build Coastguard Worker } 649*bb4ee6a4SAndroid Build Coastguard Worker }; 650*bb4ee6a4SAndroid Build Coastguard Worker 651*bb4ee6a4SAndroid Build Coastguard Worker let mut need_set_config = true; 652*bb4ee6a4SAndroid Build Coastguard Worker let device_state_binding = self.get_device_state(); 653*bb4ee6a4SAndroid Build Coastguard Worker let mut device_state = device_state_binding.write().unwrap(); 654*bb4ee6a4SAndroid Build Coastguard Worker if !device_state.initialized { 655*bb4ee6a4SAndroid Build Coastguard Worker need_set_config = Some(config) != cur_config; 656*bb4ee6a4SAndroid Build Coastguard Worker device_state.initialized = true; 657*bb4ee6a4SAndroid Build Coastguard Worker } 658*bb4ee6a4SAndroid Build Coastguard Worker // Drop the lock on the device state writer 659*bb4ee6a4SAndroid Build Coastguard Worker drop(device_state); 660*bb4ee6a4SAndroid Build Coastguard Worker 661*bb4ee6a4SAndroid Build Coastguard Worker if need_set_config { 662*bb4ee6a4SAndroid Build Coastguard Worker self.set_active_configuration(config)?; 663*bb4ee6a4SAndroid Build Coastguard Worker } 664*bb4ee6a4SAndroid Build Coastguard Worker 665*bb4ee6a4SAndroid Build Coastguard Worker let config_descriptor = self.get_config_descriptor(config)?; 666*bb4ee6a4SAndroid Build Coastguard Worker 667*bb4ee6a4SAndroid Build Coastguard Worker if let BackendDeviceType::HostDevice(host_device) = self { 668*bb4ee6a4SAndroid Build Coastguard Worker host_device.claim_interfaces(&config_descriptor); 669*bb4ee6a4SAndroid Build Coastguard Worker } 670*bb4ee6a4SAndroid Build Coastguard Worker 671*bb4ee6a4SAndroid Build Coastguard Worker self.create_endpoints(&config_descriptor)?; 672*bb4ee6a4SAndroid Build Coastguard Worker Ok(TransferStatus::Completed) 673*bb4ee6a4SAndroid Build Coastguard Worker } 674*bb4ee6a4SAndroid Build Coastguard Worker submit_transfer( &mut self, fail_handle: Arc<dyn FailHandle>, job_queue: &Arc<AsyncJobQueue>, xhci_transfer: Arc<XhciTransfer>, usb_transfer: BackendTransferType, ) -> Result<()>675*bb4ee6a4SAndroid Build Coastguard Worker pub fn submit_transfer( 676*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 677*bb4ee6a4SAndroid Build Coastguard Worker fail_handle: Arc<dyn FailHandle>, 678*bb4ee6a4SAndroid Build Coastguard Worker job_queue: &Arc<AsyncJobQueue>, 679*bb4ee6a4SAndroid Build Coastguard Worker xhci_transfer: Arc<XhciTransfer>, 680*bb4ee6a4SAndroid Build Coastguard Worker usb_transfer: BackendTransferType, 681*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> { 682*bb4ee6a4SAndroid Build Coastguard Worker let transfer_status = { 683*bb4ee6a4SAndroid Build Coastguard Worker // We need to hold the lock to avoid race condition. 684*bb4ee6a4SAndroid Build Coastguard Worker // While we are trying to submit the transfer, another thread might want to cancel the 685*bb4ee6a4SAndroid Build Coastguard Worker // same transfer. Holding the lock here makes sure one of them is cancelled. 686*bb4ee6a4SAndroid Build Coastguard Worker let mut state = xhci_transfer.state().lock(); 687*bb4ee6a4SAndroid Build Coastguard Worker match mem::replace(&mut *state, XhciTransferState::Cancelled) { 688*bb4ee6a4SAndroid Build Coastguard Worker XhciTransferState::Created => { 689*bb4ee6a4SAndroid Build Coastguard Worker match self.submit_backend_transfer(usb_transfer) { 690*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 691*bb4ee6a4SAndroid Build Coastguard Worker error!("fail to submit transfer {:?}", e); 692*bb4ee6a4SAndroid Build Coastguard Worker *state = XhciTransferState::Completed; 693*bb4ee6a4SAndroid Build Coastguard Worker TransferStatus::NoDevice 694*bb4ee6a4SAndroid Build Coastguard Worker } 695*bb4ee6a4SAndroid Build Coastguard Worker Ok(canceller) => { 696*bb4ee6a4SAndroid Build Coastguard Worker let cancel_callback = Box::new(move || match canceller.cancel() { 697*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) => { 698*bb4ee6a4SAndroid Build Coastguard Worker debug!("cancel issued to kernel"); 699*bb4ee6a4SAndroid Build Coastguard Worker } 700*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => { 701*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to cancel XhciTransfer: {}", e); 702*bb4ee6a4SAndroid Build Coastguard Worker } 703*bb4ee6a4SAndroid Build Coastguard Worker }); 704*bb4ee6a4SAndroid Build Coastguard Worker *state = XhciTransferState::Submitted { cancel_callback }; 705*bb4ee6a4SAndroid Build Coastguard Worker // If it's submitted, we don't need to send on_transfer_complete now. 706*bb4ee6a4SAndroid Build Coastguard Worker return Ok(()); 707*bb4ee6a4SAndroid Build Coastguard Worker } 708*bb4ee6a4SAndroid Build Coastguard Worker } 709*bb4ee6a4SAndroid Build Coastguard Worker } 710*bb4ee6a4SAndroid Build Coastguard Worker XhciTransferState::Cancelled => { 711*bb4ee6a4SAndroid Build Coastguard Worker warn!("Transfer is already cancelled"); 712*bb4ee6a4SAndroid Build Coastguard Worker TransferStatus::Cancelled 713*bb4ee6a4SAndroid Build Coastguard Worker } 714*bb4ee6a4SAndroid Build Coastguard Worker _ => { 715*bb4ee6a4SAndroid Build Coastguard Worker // The transfer could not be in the following states: 716*bb4ee6a4SAndroid Build Coastguard Worker // Submitted: A transfer should only be submitted once. 717*bb4ee6a4SAndroid Build Coastguard Worker // Cancelling: Transfer is cancelling only when it's submitted and someone is 718*bb4ee6a4SAndroid Build Coastguard Worker // trying to cancel it. 719*bb4ee6a4SAndroid Build Coastguard Worker // Completed: A completed transfer should not be submitted again. 720*bb4ee6a4SAndroid Build Coastguard Worker error!("xhci trasfer state is invalid"); 721*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::BadXhciTransferState); 722*bb4ee6a4SAndroid Build Coastguard Worker } 723*bb4ee6a4SAndroid Build Coastguard Worker } 724*bb4ee6a4SAndroid Build Coastguard Worker }; 725*bb4ee6a4SAndroid Build Coastguard Worker // We are holding locks to of backends, we want to call on_transfer_complete 726*bb4ee6a4SAndroid Build Coastguard Worker // without any lock. 727*bb4ee6a4SAndroid Build Coastguard Worker job_queue 728*bb4ee6a4SAndroid Build Coastguard Worker .queue_job(move || { 729*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = xhci_transfer.on_transfer_complete(&transfer_status, 0) { 730*bb4ee6a4SAndroid Build Coastguard Worker error!("transfer complete failed: {:?}", e); 731*bb4ee6a4SAndroid Build Coastguard Worker fail_handle.fail(); 732*bb4ee6a4SAndroid Build Coastguard Worker } 733*bb4ee6a4SAndroid Build Coastguard Worker }) 734*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::QueueAsyncJob) 735*bb4ee6a4SAndroid Build Coastguard Worker } 736*bb4ee6a4SAndroid Build Coastguard Worker submit_xhci_transfer(&mut self, transfer: XhciTransfer) -> Result<()>737*bb4ee6a4SAndroid Build Coastguard Worker pub fn submit_xhci_transfer(&mut self, transfer: XhciTransfer) -> Result<()> { 738*bb4ee6a4SAndroid Build Coastguard Worker // We catch the submit_xhci_transfer call at the top BackendDeviceType level because 739*bb4ee6a4SAndroid Build Coastguard Worker // the implementation is generic for all backend types. If it's a control 740*bb4ee6a4SAndroid Build Coastguard Worker // transfer we handle it accordingly, before dispatching into each specific 741*bb4ee6a4SAndroid Build Coastguard Worker // endpoint logic. 742*bb4ee6a4SAndroid Build Coastguard Worker if transfer.get_endpoint_number() == 0 { 743*bb4ee6a4SAndroid Build Coastguard Worker return self.handle_control_transfer(transfer); 744*bb4ee6a4SAndroid Build Coastguard Worker } 745*bb4ee6a4SAndroid Build Coastguard Worker 746*bb4ee6a4SAndroid Build Coastguard Worker for ep in &self.get_device_state().write().unwrap().endpoints { 747*bb4ee6a4SAndroid Build Coastguard Worker if ep.match_ep(transfer.get_endpoint_number(), transfer.get_transfer_dir()) { 748*bb4ee6a4SAndroid Build Coastguard Worker return ep.handle_transfer(self, transfer); 749*bb4ee6a4SAndroid Build Coastguard Worker } 750*bb4ee6a4SAndroid Build Coastguard Worker } 751*bb4ee6a4SAndroid Build Coastguard Worker 752*bb4ee6a4SAndroid Build Coastguard Worker warn!("Could not find endpoint for transfer"); 753*bb4ee6a4SAndroid Build Coastguard Worker transfer 754*bb4ee6a4SAndroid Build Coastguard Worker .on_transfer_complete(&TransferStatus::Error, 0) 755*bb4ee6a4SAndroid Build Coastguard Worker .map_err(Error::TransferComplete) 756*bb4ee6a4SAndroid Build Coastguard Worker } 757*bb4ee6a4SAndroid Build Coastguard Worker } 758*bb4ee6a4SAndroid Build Coastguard Worker 759*bb4ee6a4SAndroid Build Coastguard Worker /// Backend device trait implementation is the interface of a generic backend device 760*bb4ee6a4SAndroid Build Coastguard Worker /// to interact with concrete implementations 761*bb4ee6a4SAndroid Build Coastguard Worker pub trait BackendDevice: Sync + Send { 762*bb4ee6a4SAndroid Build Coastguard Worker /// Submits a transfer to the specific backend implementation. submit_backend_transfer( &mut self, transfer: BackendTransferType, ) -> Result<BackendTransferHandle>763*bb4ee6a4SAndroid Build Coastguard Worker fn submit_backend_transfer( 764*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 765*bb4ee6a4SAndroid Build Coastguard Worker transfer: BackendTransferType, 766*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<BackendTransferHandle>; 767*bb4ee6a4SAndroid Build Coastguard Worker /// This is called by a generic backend provider when a USB detach message is received from the 768*bb4ee6a4SAndroid Build Coastguard Worker /// vm control socket. It detaches the backend device from the backend provider event loop. detach_event_handler(&self, event_loop: &Arc<EventLoop>) -> Result<()>769*bb4ee6a4SAndroid Build Coastguard Worker fn detach_event_handler(&self, event_loop: &Arc<EventLoop>) -> Result<()>; 770*bb4ee6a4SAndroid Build Coastguard Worker /// Gets a buffer used for data transfer between the host and this device. The buffer returned 771*bb4ee6a4SAndroid Build Coastguard Worker /// by this function must be consumed by `submit_backend_transfer()`. request_transfer_buffer(&mut self, size: usize) -> TransferBuffer772*bb4ee6a4SAndroid Build Coastguard Worker fn request_transfer_buffer(&mut self, size: usize) -> TransferBuffer; 773*bb4ee6a4SAndroid Build Coastguard Worker 774*bb4ee6a4SAndroid Build Coastguard Worker /// Requests the backend to build a backend-specific bulk transfer request build_bulk_transfer( &mut self, ep_addr: u8, transfer_buffer: TransferBuffer, stream_id: Option<u16>, ) -> Result<BackendTransferType>775*bb4ee6a4SAndroid Build Coastguard Worker fn build_bulk_transfer( 776*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 777*bb4ee6a4SAndroid Build Coastguard Worker ep_addr: u8, 778*bb4ee6a4SAndroid Build Coastguard Worker transfer_buffer: TransferBuffer, 779*bb4ee6a4SAndroid Build Coastguard Worker stream_id: Option<u16>, 780*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<BackendTransferType>; 781*bb4ee6a4SAndroid Build Coastguard Worker /// Requests the backend to build a backend-specific interrupt transfer request build_interrupt_transfer( &mut self, ep_addr: u8, transfer_buffer: TransferBuffer, ) -> Result<BackendTransferType>782*bb4ee6a4SAndroid Build Coastguard Worker fn build_interrupt_transfer( 783*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 784*bb4ee6a4SAndroid Build Coastguard Worker ep_addr: u8, 785*bb4ee6a4SAndroid Build Coastguard Worker transfer_buffer: TransferBuffer, 786*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<BackendTransferType>; 787*bb4ee6a4SAndroid Build Coastguard Worker 788*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the `ControlTransferState` for the given backend device. get_control_transfer_state(&mut self) -> Arc<RwLock<ControlTransferState>>789*bb4ee6a4SAndroid Build Coastguard Worker fn get_control_transfer_state(&mut self) -> Arc<RwLock<ControlTransferState>>; 790*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the `DeviceState` for the given backend device. This state contains all the 791*bb4ee6a4SAndroid Build Coastguard Worker /// backend-agnostic state for all generic USB backends. get_device_state(&mut self) -> Arc<RwLock<DeviceState>>792*bb4ee6a4SAndroid Build Coastguard Worker fn get_device_state(&mut self) -> Arc<RwLock<DeviceState>>; 793*bb4ee6a4SAndroid Build Coastguard Worker 794*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the device active config descriptor tree. get_active_config_descriptor(&mut self) -> Result<ConfigDescriptorTree>795*bb4ee6a4SAndroid Build Coastguard Worker fn get_active_config_descriptor(&mut self) -> Result<ConfigDescriptorTree>; 796*bb4ee6a4SAndroid Build Coastguard Worker /// Gets a specific device config descriptor tree. get_config_descriptor(&mut self, config: u8) -> Result<ConfigDescriptorTree>797*bb4ee6a4SAndroid Build Coastguard Worker fn get_config_descriptor(&mut self, config: u8) -> Result<ConfigDescriptorTree>; 798*bb4ee6a4SAndroid Build Coastguard Worker /// Gets a specific device config descriptor tree by index. get_config_descriptor_by_index(&mut self, config_index: u8) -> Result<ConfigDescriptorTree>799*bb4ee6a4SAndroid Build Coastguard Worker fn get_config_descriptor_by_index(&mut self, config_index: u8) -> Result<ConfigDescriptorTree>; 800*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the device descriptor tree. get_device_descriptor_tree(&mut self) -> Result<DeviceDescriptorTree>801*bb4ee6a4SAndroid Build Coastguard Worker fn get_device_descriptor_tree(&mut self) -> Result<DeviceDescriptorTree>; 802*bb4ee6a4SAndroid Build Coastguard Worker /// Gets the device current active configuration. get_active_configuration(&mut self) -> Result<u8>803*bb4ee6a4SAndroid Build Coastguard Worker fn get_active_configuration(&mut self) -> Result<u8>; 804*bb4ee6a4SAndroid Build Coastguard Worker /// Sets the device active configuration. set_active_configuration(&mut self, config: u8) -> Result<()>805*bb4ee6a4SAndroid Build Coastguard Worker fn set_active_configuration(&mut self, config: u8) -> Result<()>; 806*bb4ee6a4SAndroid Build Coastguard Worker /// Handles a clear feature endpoint request for the given device. clear_feature(&mut self, value: u16, index: u16) -> Result<TransferStatus>807*bb4ee6a4SAndroid Build Coastguard Worker fn clear_feature(&mut self, value: u16, index: u16) -> Result<TransferStatus>; 808*bb4ee6a4SAndroid Build Coastguard Worker /// Creates endpoints for the device with the given config descriptor tree. create_endpoints(&mut self, config_descriptor: &ConfigDescriptorTree) -> Result<()>809*bb4ee6a4SAndroid Build Coastguard Worker fn create_endpoints(&mut self, config_descriptor: &ConfigDescriptorTree) -> Result<()>; 810*bb4ee6a4SAndroid Build Coastguard Worker } 811