xref: /aosp_15_r20/external/crosvm/devices/src/usb/backend/device.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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