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