devices/usb/backend/
device.rs

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