1use std::cmp::min;
6use std::fmt;
7use std::fmt::Display;
8use std::mem;
9use std::sync::Arc;
10use std::sync::Weak;
11
12use base::debug;
13use base::error;
14use base::info;
15use base::warn;
16use base::Error as SysError;
17use base::Event;
18use bit_field::Error as BitFieldError;
19use remain::sorted;
20use sync::Mutex;
21use thiserror::Error;
22use usb_util::TransferStatus;
23use usb_util::UsbRequestSetup;
24use vm_memory::GuestMemory;
25use vm_memory::GuestMemoryError;
26
27use super::device_slot::DeviceSlot;
28use super::interrupter::Error as InterrupterError;
29use super::interrupter::Interrupter;
30use super::ring_buffer_stop_cb::RingBufferStopCallback;
31use super::scatter_gather_buffer::Error as BufferError;
32use super::scatter_gather_buffer::ScatterGatherBuffer;
33use super::usb_hub::Error as HubError;
34use super::usb_hub::UsbPort;
35use super::xhci_abi::AddressedTrb;
36use super::xhci_abi::Error as TrbError;
37use super::xhci_abi::EventDataTrb;
38use super::xhci_abi::SetupStageTrb;
39use super::xhci_abi::TransferDescriptor;
40use super::xhci_abi::TrbCast;
41use super::xhci_abi::TrbCompletionCode;
42use super::xhci_abi::TrbType;
43use super::xhci_regs::MAX_INTERRUPTER;
44
45#[sorted]
46#[derive(Error, Debug)]
47pub enum Error {
48 #[error("unexpected trb type: {0:?}")]
49 BadTrbType(TrbType),
50 #[error("cannot cast trb: {0}")]
51 CastTrb(TrbError),
52 #[error("cannot create transfer buffer: {0}")]
53 CreateBuffer(BufferError),
54 #[error("cannot detach from port: {0}")]
55 DetachPort(HubError),
56 #[error("failed to get max payload length for ep: {0}")]
57 GetMaxPayload(u8),
58 #[error("failed to halt the endpoint: {0}")]
59 HaltEndpoint(u8),
60 #[error("failed to read guest memory: {0}")]
61 ReadGuestMemory(GuestMemoryError),
62 #[error("cannot send interrupt: {0}")]
63 SendInterrupt(InterrupterError),
64 #[error("failed to submit transfer to backend")]
65 SubmitTransfer,
66 #[error("cannot get transfer length: {0}")]
67 TransferLength(TrbError),
68 #[error("cannot get trb type: {0}")]
69 TrbType(BitFieldError),
70 #[error("cannot write completion event: {0}")]
71 WriteCompletionEvent(SysError),
72 #[error("failed to write guest memory: {0}")]
73 WriteGuestMemory(GuestMemoryError),
74}
75
76type Result<T> = std::result::Result<T, Error>;
77
78#[derive(PartialEq, Eq, Clone, Copy, Debug)]
80pub enum TransferDirection {
81 In,
82 Out,
83 Control,
84}
85
86pub enum XhciTransferState {
88 Created,
89 Submitted {
92 cancel_callback: Box<dyn FnOnce() + Send>,
93 },
94 Cancelling,
95 Cancelled,
96 Completed,
97}
98
99impl XhciTransferState {
100 pub fn try_cancel(&mut self) {
102 match mem::replace(self, XhciTransferState::Created) {
103 XhciTransferState::Submitted { cancel_callback } => {
104 *self = XhciTransferState::Cancelling;
105 cancel_callback();
106 }
107 XhciTransferState::Cancelling => {
108 error!("Another cancellation is already issued.");
109 }
110 _ => {
111 *self = XhciTransferState::Cancelled;
112 }
113 }
114 }
115}
116
117pub enum XhciTransferType {
119 Normal,
122 SetupStage,
125 DataStage,
126 StatusStage,
127 Isochronous,
129 Noop,
131}
132
133impl Display for XhciTransferType {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 use self::XhciTransferType::*;
136
137 match self {
138 Normal => write!(f, "Normal"),
139 SetupStage => write!(f, "SetupStage"),
140 DataStage => write!(f, "DataStage"),
141 StatusStage => write!(f, "StatusStage"),
142 Isochronous => write!(f, "Isochronous"),
143 Noop => write!(f, "Noop"),
144 }
145 }
146}
147
148#[derive(Clone)]
151pub struct XhciTransferManager {
152 transfers: Arc<Mutex<Vec<Weak<Mutex<XhciTransferState>>>>>,
153 device_slot: Weak<DeviceSlot>,
154 stop_callback: Arc<Mutex<Vec<RingBufferStopCallback>>>,
155}
156
157impl XhciTransferManager {
158 pub fn new(device_slot: Weak<DeviceSlot>) -> XhciTransferManager {
160 XhciTransferManager {
161 transfers: Arc::new(Mutex::new(Vec::new())),
162 device_slot,
163 stop_callback: Arc::new(Mutex::new(Vec::new())),
164 }
165 }
166
167 pub fn create_transfer(
169 &self,
170 mem: GuestMemory,
171 port: Arc<UsbPort>,
172 interrupter: Arc<Mutex<Interrupter>>,
173 slot_id: u8,
174 endpoint_id: u8,
175 transfer_trbs: TransferDescriptor,
176 completion_event: Event,
177 stream_id: Option<u16>,
178 ) -> XhciTransfer {
179 assert!(!transfer_trbs.is_empty());
180 let transfer_dir = {
181 if endpoint_id == 0 {
182 TransferDirection::Control
183 } else if (endpoint_id % 2) == 0 {
184 TransferDirection::Out
185 } else {
186 TransferDirection::In
187 }
188 };
189 let t = XhciTransfer {
190 manager: self.clone(),
191 state: Arc::new(Mutex::new(XhciTransferState::Created)),
192 mem,
193 port,
194 interrupter,
195 transfer_completion_event: completion_event,
196 slot_id,
197 endpoint_id,
198 transfer_dir,
199 transfer_trbs,
200 device_slot: self.device_slot.clone(),
201 stream_id,
202 };
203 self.transfers.lock().push(Arc::downgrade(&t.state));
204 t
205 }
206
207 pub fn cancel_all(&self) {
209 self.transfers.lock().iter().for_each(|t| {
210 let state = match t.upgrade() {
211 Some(state) => state,
212 None => {
213 error!("transfer is already cancelled or finished");
214 return;
215 }
216 };
217 state.lock().try_cancel();
218 });
219 }
220
221 pub fn set_stop_callback(&self, callback: RingBufferStopCallback) {
224 if !self.transfers.lock().is_empty() {
225 self.stop_callback.lock().push(callback);
226 }
227 }
228
229 fn remove_transfer(&self, t: &Arc<Mutex<XhciTransferState>>) {
230 let mut transfers = self.transfers.lock();
231 match transfers.iter().position(|wt| match wt.upgrade() {
232 Some(wt) => Arc::ptr_eq(&wt, t),
233 None => false,
234 }) {
235 None => error!("attempted to remove unknown transfer"),
236 Some(i) => {
237 transfers.swap_remove(i);
238 }
239 }
240 if transfers.is_empty() {
241 self.stop_callback.lock().clear();
242 }
243 }
244}
245
246impl Default for XhciTransferManager {
247 fn default() -> Self {
248 Self::new(Weak::new())
249 }
250}
251
252pub struct XhciTransfer {
255 manager: XhciTransferManager,
256 state: Arc<Mutex<XhciTransferState>>,
257 mem: GuestMemory,
258 port: Arc<UsbPort>,
259 interrupter: Arc<Mutex<Interrupter>>,
260 slot_id: u8,
261 endpoint_id: u8,
263 transfer_dir: TransferDirection,
264 transfer_trbs: TransferDescriptor,
265 transfer_completion_event: Event,
266 device_slot: Weak<DeviceSlot>,
267 stream_id: Option<u16>,
268}
269
270impl Drop for XhciTransfer {
271 fn drop(&mut self) {
272 self.manager.remove_transfer(&self.state);
273 }
274}
275
276impl fmt::Debug for XhciTransfer {
277 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
278 write!(
279 f,
280 "xhci_transfer slot id: {}, endpoint id {}, transfer_dir {:?}, transfer_trbs {:?}",
281 self.slot_id, self.endpoint_id, self.transfer_dir, self.transfer_trbs
282 )
283 }
284}
285
286impl XhciTransfer {
287 pub fn state(&self) -> &Arc<Mutex<XhciTransferState>> {
289 &self.state
290 }
291
292 pub fn get_transfer_type(&self) -> Result<XhciTransferType> {
294 match self.transfer_trbs[0]
297 .trb
298 .get_trb_type()
299 .map_err(Error::TrbType)?
300 {
301 TrbType::Normal => Ok(XhciTransferType::Normal),
302 TrbType::SetupStage => Ok(XhciTransferType::SetupStage),
303 TrbType::DataStage => Ok(XhciTransferType::DataStage),
304 TrbType::StatusStage => Ok(XhciTransferType::StatusStage),
305 TrbType::Isoch => Ok(XhciTransferType::Isochronous),
306 TrbType::Noop => Ok(XhciTransferType::Noop),
307 t => Err(Error::BadTrbType(t)),
308 }
309 }
310
311 pub fn create_buffer(&self) -> Result<ScatterGatherBuffer> {
313 ScatterGatherBuffer::new(self.mem.clone(), self.transfer_trbs.clone())
314 .map_err(Error::CreateBuffer)
315 }
316
317 pub fn create_usb_request_setup(&self) -> Result<UsbRequestSetup> {
319 let trb = self.transfer_trbs[0]
320 .trb
321 .checked_cast::<SetupStageTrb>()
322 .map_err(Error::CastTrb)?;
323 Ok(UsbRequestSetup::new(
324 trb.get_request_type(),
325 trb.get_request(),
326 trb.get_value(),
327 trb.get_index(),
328 trb.get_length(),
329 ))
330 }
331
332 pub fn get_endpoint_number(&self) -> u8 {
334 self.endpoint_id / 2
336 }
337
338 pub fn get_transfer_dir(&self) -> TransferDirection {
340 self.transfer_dir
341 }
342
343 pub fn get_stream_id(&self) -> Option<u16> {
345 self.stream_id
346 }
347
348 pub fn get_max_payload(&self) -> Result<u32> {
350 let Some(device_slot) = self.device_slot.upgrade() else {
351 return Err(Error::GetMaxPayload(self.endpoint_id));
352 };
353 device_slot
354 .get_max_esit_payload(self.endpoint_id)
355 .map_err(|_| Error::GetMaxPayload(self.endpoint_id))
356 }
357
358 pub fn on_transfer_complete(
360 &self,
361 status: &TransferStatus,
362 bytes_transferred: u32,
363 ) -> Result<()> {
364 match status {
365 TransferStatus::NoDevice => {
366 info!("xhci: device disconnected, detaching from port");
367 return match self.port.detach() {
370 Ok(()) => Ok(()),
371 Err(HubError::AlreadyDetached(_e)) => Ok(()),
374 Err(e) => Err(Error::DetachPort(e)),
375 };
376 }
377 TransferStatus::Cancelled => {
378 return self
381 .transfer_completion_event
382 .signal()
383 .map_err(Error::WriteCompletionEvent);
384 }
385 TransferStatus::Completed => {
386 self.transfer_completion_event
387 .signal()
388 .map_err(Error::WriteCompletionEvent)?;
389 }
390 TransferStatus::Stalled => {
391 warn!("xhci: endpoint is stalled. set state to Halted");
392 if let Some(device_slot) = self.device_slot.upgrade() {
393 device_slot
394 .halt_endpoint(self.endpoint_id)
395 .map_err(|_| Error::HaltEndpoint(self.endpoint_id))?;
396 }
397 self.transfer_completion_event
398 .signal()
399 .map_err(Error::WriteCompletionEvent)?;
400 }
401 _ => {
402 self.transfer_completion_event
406 .signal()
407 .map_err(Error::WriteCompletionEvent)?;
408 }
409 }
410
411 let mut edtla: u32 = 0;
412 for atrb in &self.transfer_trbs {
419 edtla += atrb.trb.transfer_length().map_err(Error::TransferLength)?;
420 if atrb.trb.interrupt_on_completion()
421 || (atrb.trb.interrupt_on_short_packet() && edtla > bytes_transferred)
422 {
423 if atrb.trb.get_trb_type().map_err(Error::TrbType)? == TrbType::EventData {
425 let tlength = min(edtla, bytes_transferred);
426 self.interrupter
427 .lock()
428 .send_transfer_event_trb(
429 TrbCompletionCode::Success,
430 atrb.trb
431 .cast::<EventDataTrb>()
432 .map_err(Error::CastTrb)?
433 .get_event_data(),
434 tlength,
435 true,
436 self.slot_id,
437 self.endpoint_id,
438 )
439 .map_err(Error::SendInterrupt)?;
440 } else if *status == TransferStatus::Stalled {
441 debug!("xhci: on transfer complete stalled");
442 let residual_transfer_length = edtla - bytes_transferred;
443 self.interrupter
444 .lock()
445 .send_transfer_event_trb(
446 TrbCompletionCode::StallError,
447 atrb.gpa,
448 residual_transfer_length,
449 true,
450 self.slot_id,
451 self.endpoint_id,
452 )
453 .map_err(Error::SendInterrupt)?;
454 } else {
455 if edtla > bytes_transferred {
457 debug!("xhci: on transfer complete short packet");
458 let residual_transfer_length = edtla - bytes_transferred;
459 self.interrupter
460 .lock()
461 .send_transfer_event_trb(
462 TrbCompletionCode::ShortPacket,
463 atrb.gpa,
464 residual_transfer_length,
465 true,
466 self.slot_id,
467 self.endpoint_id,
468 )
469 .map_err(Error::SendInterrupt)?;
470 } else {
471 debug!("xhci: on transfer complete success");
472 self.interrupter
473 .lock()
474 .send_transfer_event_trb(
475 TrbCompletionCode::Success,
476 atrb.gpa,
477 0, true,
479 self.slot_id,
480 self.endpoint_id,
481 )
482 .map_err(Error::SendInterrupt)?;
483 }
484 }
485 }
486 }
487 Ok(())
488 }
489
490 pub fn send_to_backend_if_valid(self) -> Result<()> {
492 if self.validate_transfer()? {
493 let port = self.port.clone();
495 let mut backend = port.backend_device();
496 match &mut *backend {
497 Some(backend) => backend
498 .lock()
499 .submit_xhci_transfer(self)
500 .map_err(|_| Error::SubmitTransfer)?,
501 None => {
502 error!("backend is already disconnected");
503 self.transfer_completion_event
504 .signal()
505 .map_err(Error::WriteCompletionEvent)?;
506 }
507 }
508 } else {
509 error!("invalid td on transfer ring");
510 self.transfer_completion_event
511 .signal()
512 .map_err(Error::WriteCompletionEvent)?;
513 }
514 Ok(())
515 }
516
517 fn validate_transfer(&self) -> Result<bool> {
520 let mut valid = true;
521 for atrb in &self.transfer_trbs {
522 if !trb_is_valid(atrb) {
523 self.interrupter
524 .lock()
525 .send_transfer_event_trb(
526 TrbCompletionCode::TrbError,
527 atrb.gpa,
528 0,
529 false,
530 self.slot_id,
531 self.endpoint_id,
532 )
533 .map_err(Error::SendInterrupt)?;
534 valid = false;
535 }
536 }
537 Ok(valid)
538 }
539
540 pub fn proceed(&self) -> Result<()> {
541 self.transfer_completion_event
542 .signal()
543 .map_err(Error::WriteCompletionEvent)
544 }
545
546 pub fn append_trbs(&mut self, mut transfer: XhciTransfer) {
547 self.transfer_trbs.append(&mut transfer.transfer_trbs);
548 }
549}
550
551fn trb_is_valid(atrb: &AddressedTrb) -> bool {
552 let can_be_in_transfer_ring = match atrb.trb.can_be_in_transfer_ring() {
553 Ok(v) => v,
554 Err(e) => {
555 error!("unknown error {:?}", e);
556 return false;
557 }
558 };
559 can_be_in_transfer_ring && (atrb.trb.interrupter_target() < MAX_INTERRUPTER)
560}