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::scatter_gather_buffer::Error as BufferError;
31use super::scatter_gather_buffer::ScatterGatherBuffer;
32use super::usb_hub::Error as HubError;
33use super::usb_hub::UsbPort;
34use super::xhci_abi::AddressedTrb;
35use super::xhci_abi::Error as TrbError;
36use super::xhci_abi::EventDataTrb;
37use super::xhci_abi::SetupStageTrb;
38use super::xhci_abi::TransferDescriptor;
39use super::xhci_abi::TrbCast;
40use super::xhci_abi::TrbCompletionCode;
41use super::xhci_abi::TrbType;
42use super::xhci_regs::MAX_INTERRUPTER;
43
44#[sorted]
45#[derive(Error, Debug)]
46pub enum Error {
47 #[error("unexpected trb type: {0:?}")]
48 BadTrbType(TrbType),
49 #[error("cannot cast trb: {0}")]
50 CastTrb(TrbError),
51 #[error("cannot create transfer buffer: {0}")]
52 CreateBuffer(BufferError),
53 #[error("cannot detach from port: {0}")]
54 DetachPort(HubError),
55 #[error("failed to halt the endpoint: {0}")]
56 HaltEndpoint(u8),
57 #[error("failed to read guest memory: {0}")]
58 ReadGuestMemory(GuestMemoryError),
59 #[error("cannot send interrupt: {0}")]
60 SendInterrupt(InterrupterError),
61 #[error("failed to submit transfer to backend")]
62 SubmitTransfer,
63 #[error("cannot get transfer length: {0}")]
64 TransferLength(TrbError),
65 #[error("cannot get trb type: {0}")]
66 TrbType(BitFieldError),
67 #[error("cannot write completion event: {0}")]
68 WriteCompletionEvent(SysError),
69 #[error("failed to write guest memory: {0}")]
70 WriteGuestMemory(GuestMemoryError),
71}
72
73type Result<T> = std::result::Result<T, Error>;
74
75#[derive(PartialEq, Eq, Clone, Copy, Debug)]
77pub enum TransferDirection {
78 In,
79 Out,
80 Control,
81}
82
83pub enum XhciTransferState {
85 Created,
86 Submitted {
89 cancel_callback: Box<dyn FnOnce() + Send>,
90 },
91 Cancelling,
92 Cancelled,
93 Completed,
94}
95
96impl XhciTransferState {
97 pub fn try_cancel(&mut self) {
99 match mem::replace(self, XhciTransferState::Created) {
100 XhciTransferState::Submitted { cancel_callback } => {
101 *self = XhciTransferState::Cancelling;
102 cancel_callback();
103 }
104 XhciTransferState::Cancelling => {
105 error!("Another cancellation is already issued.");
106 }
107 _ => {
108 *self = XhciTransferState::Cancelled;
109 }
110 }
111 }
112}
113
114pub enum XhciTransferType {
116 Normal,
119 SetupStage,
122 DataStage,
123 StatusStage,
124 Isochronous,
126 Noop,
128}
129
130impl Display for XhciTransferType {
131 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132 use self::XhciTransferType::*;
133
134 match self {
135 Normal => write!(f, "Normal"),
136 SetupStage => write!(f, "SetupStage"),
137 DataStage => write!(f, "DataStage"),
138 StatusStage => write!(f, "StatusStage"),
139 Isochronous => write!(f, "Isochronous"),
140 Noop => write!(f, "Noop"),
141 }
142 }
143}
144
145#[derive(Clone)]
148pub struct XhciTransferManager {
149 transfers: Arc<Mutex<Vec<Weak<Mutex<XhciTransferState>>>>>,
150 device_slot: Weak<DeviceSlot>,
151}
152
153impl XhciTransferManager {
154 pub fn new(device_slot: Weak<DeviceSlot>) -> XhciTransferManager {
156 XhciTransferManager {
157 transfers: Arc::new(Mutex::new(Vec::new())),
158 device_slot,
159 }
160 }
161
162 pub fn create_transfer(
164 &self,
165 mem: GuestMemory,
166 port: Arc<UsbPort>,
167 interrupter: Arc<Mutex<Interrupter>>,
168 slot_id: u8,
169 endpoint_id: u8,
170 transfer_trbs: TransferDescriptor,
171 completion_event: Event,
172 stream_id: Option<u16>,
173 ) -> XhciTransfer {
174 assert!(!transfer_trbs.is_empty());
175 let transfer_dir = {
176 if endpoint_id == 0 {
177 TransferDirection::Control
178 } else if (endpoint_id % 2) == 0 {
179 TransferDirection::Out
180 } else {
181 TransferDirection::In
182 }
183 };
184 let t = XhciTransfer {
185 manager: self.clone(),
186 state: Arc::new(Mutex::new(XhciTransferState::Created)),
187 mem,
188 port,
189 interrupter,
190 transfer_completion_event: completion_event,
191 slot_id,
192 endpoint_id,
193 transfer_dir,
194 transfer_trbs,
195 device_slot: self.device_slot.clone(),
196 stream_id,
197 };
198 self.transfers.lock().push(Arc::downgrade(&t.state));
199 t
200 }
201
202 pub fn cancel_all(&self) {
204 self.transfers.lock().iter().for_each(|t| {
205 let state = match t.upgrade() {
206 Some(state) => state,
207 None => {
208 error!("transfer is already cancelled or finished");
209 return;
210 }
211 };
212 state.lock().try_cancel();
213 });
214 }
215
216 fn remove_transfer(&self, t: &Arc<Mutex<XhciTransferState>>) {
217 let mut transfers = self.transfers.lock();
218 match transfers.iter().position(|wt| match wt.upgrade() {
219 Some(wt) => Arc::ptr_eq(&wt, t),
220 None => false,
221 }) {
222 None => error!("attempted to remove unknow transfer"),
223 Some(i) => {
224 transfers.swap_remove(i);
225 }
226 }
227 }
228}
229
230impl Default for XhciTransferManager {
231 fn default() -> Self {
232 Self::new(Weak::new())
233 }
234}
235
236pub struct XhciTransfer {
239 manager: XhciTransferManager,
240 state: Arc<Mutex<XhciTransferState>>,
241 mem: GuestMemory,
242 port: Arc<UsbPort>,
243 interrupter: Arc<Mutex<Interrupter>>,
244 slot_id: u8,
245 endpoint_id: u8,
247 transfer_dir: TransferDirection,
248 transfer_trbs: TransferDescriptor,
249 transfer_completion_event: Event,
250 device_slot: Weak<DeviceSlot>,
251 stream_id: Option<u16>,
252}
253
254impl Drop for XhciTransfer {
255 fn drop(&mut self) {
256 self.manager.remove_transfer(&self.state);
257 }
258}
259
260impl fmt::Debug for XhciTransfer {
261 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
262 write!(
263 f,
264 "xhci_transfer slot id: {}, endpoint id {}, transfer_dir {:?}, transfer_trbs {:?}",
265 self.slot_id, self.endpoint_id, self.transfer_dir, self.transfer_trbs
266 )
267 }
268}
269
270impl XhciTransfer {
271 pub fn state(&self) -> &Arc<Mutex<XhciTransferState>> {
273 &self.state
274 }
275
276 pub fn get_transfer_type(&self) -> Result<XhciTransferType> {
278 match self.transfer_trbs[0]
281 .trb
282 .get_trb_type()
283 .map_err(Error::TrbType)?
284 {
285 TrbType::Normal => Ok(XhciTransferType::Normal),
286 TrbType::SetupStage => Ok(XhciTransferType::SetupStage),
287 TrbType::DataStage => Ok(XhciTransferType::DataStage),
288 TrbType::StatusStage => Ok(XhciTransferType::StatusStage),
289 TrbType::Isoch => Ok(XhciTransferType::Isochronous),
290 TrbType::Noop => Ok(XhciTransferType::Noop),
291 t => Err(Error::BadTrbType(t)),
292 }
293 }
294
295 pub fn create_buffer(&self) -> Result<ScatterGatherBuffer> {
297 ScatterGatherBuffer::new(self.mem.clone(), self.transfer_trbs.clone())
298 .map_err(Error::CreateBuffer)
299 }
300
301 pub fn create_usb_request_setup(&self) -> Result<UsbRequestSetup> {
303 let trb = self.transfer_trbs[0]
304 .trb
305 .checked_cast::<SetupStageTrb>()
306 .map_err(Error::CastTrb)?;
307 Ok(UsbRequestSetup::new(
308 trb.get_request_type(),
309 trb.get_request(),
310 trb.get_value(),
311 trb.get_index(),
312 trb.get_length(),
313 ))
314 }
315
316 pub fn get_endpoint_number(&self) -> u8 {
318 self.endpoint_id / 2
320 }
321
322 pub fn get_transfer_dir(&self) -> TransferDirection {
324 self.transfer_dir
325 }
326
327 pub fn get_stream_id(&self) -> Option<u16> {
329 self.stream_id
330 }
331
332 pub fn on_transfer_complete(
334 &self,
335 status: &TransferStatus,
336 bytes_transferred: u32,
337 ) -> Result<()> {
338 match status {
339 TransferStatus::NoDevice => {
340 info!("xhci: device disconnected, detaching from port");
341 return match self.port.detach() {
344 Ok(()) => Ok(()),
345 Err(HubError::AlreadyDetached(_e)) => Ok(()),
348 Err(e) => Err(Error::DetachPort(e)),
349 };
350 }
351 TransferStatus::Cancelled => {
352 return self
355 .transfer_completion_event
356 .signal()
357 .map_err(Error::WriteCompletionEvent);
358 }
359 TransferStatus::Completed => {
360 self.transfer_completion_event
361 .signal()
362 .map_err(Error::WriteCompletionEvent)?;
363 }
364 TransferStatus::Stalled => {
365 warn!("xhci: endpoint is stalled. set state to Halted");
366 if let Some(device_slot) = self.device_slot.upgrade() {
367 device_slot
368 .halt_endpoint(self.endpoint_id)
369 .map_err(|_| Error::HaltEndpoint(self.endpoint_id))?;
370 }
371 self.transfer_completion_event
372 .signal()
373 .map_err(Error::WriteCompletionEvent)?;
374 }
375 _ => {
376 self.transfer_completion_event
380 .signal()
381 .map_err(Error::WriteCompletionEvent)?;
382 }
383 }
384
385 let mut edtla: u32 = 0;
386 for atrb in &self.transfer_trbs {
393 edtla += atrb.trb.transfer_length().map_err(Error::TransferLength)?;
394 if atrb.trb.interrupt_on_completion()
395 || (atrb.trb.interrupt_on_short_packet() && edtla > bytes_transferred)
396 {
397 if atrb.trb.get_trb_type().map_err(Error::TrbType)? == TrbType::EventData {
399 let tlength = min(edtla, bytes_transferred);
400 self.interrupter
401 .lock()
402 .send_transfer_event_trb(
403 TrbCompletionCode::Success,
404 atrb.trb
405 .cast::<EventDataTrb>()
406 .map_err(Error::CastTrb)?
407 .get_event_data(),
408 tlength,
409 true,
410 self.slot_id,
411 self.endpoint_id,
412 )
413 .map_err(Error::SendInterrupt)?;
414 } else if *status == TransferStatus::Stalled {
415 debug!("xhci: on transfer complete stalled");
416 let residual_transfer_length = edtla - bytes_transferred;
417 self.interrupter
418 .lock()
419 .send_transfer_event_trb(
420 TrbCompletionCode::StallError,
421 atrb.gpa,
422 residual_transfer_length,
423 true,
424 self.slot_id,
425 self.endpoint_id,
426 )
427 .map_err(Error::SendInterrupt)?;
428 } else {
429 if edtla > bytes_transferred {
431 debug!("xhci: on transfer complete short packet");
432 let residual_transfer_length = edtla - bytes_transferred;
433 self.interrupter
434 .lock()
435 .send_transfer_event_trb(
436 TrbCompletionCode::ShortPacket,
437 atrb.gpa,
438 residual_transfer_length,
439 true,
440 self.slot_id,
441 self.endpoint_id,
442 )
443 .map_err(Error::SendInterrupt)?;
444 } else {
445 debug!("xhci: on transfer complete success");
446 self.interrupter
447 .lock()
448 .send_transfer_event_trb(
449 TrbCompletionCode::Success,
450 atrb.gpa,
451 0, true,
453 self.slot_id,
454 self.endpoint_id,
455 )
456 .map_err(Error::SendInterrupt)?;
457 }
458 }
459 }
460 }
461 Ok(())
462 }
463
464 pub fn send_to_backend_if_valid(self) -> Result<()> {
466 if self.validate_transfer()? {
467 let port = self.port.clone();
469 let mut backend = port.backend_device();
470 match &mut *backend {
471 Some(backend) => backend
472 .lock()
473 .submit_xhci_transfer(self)
474 .map_err(|_| Error::SubmitTransfer)?,
475 None => {
476 error!("backend is already disconnected");
477 self.transfer_completion_event
478 .signal()
479 .map_err(Error::WriteCompletionEvent)?;
480 }
481 }
482 } else {
483 error!("invalid td on transfer ring");
484 self.transfer_completion_event
485 .signal()
486 .map_err(Error::WriteCompletionEvent)?;
487 }
488 Ok(())
489 }
490
491 fn validate_transfer(&self) -> Result<bool> {
494 let mut valid = true;
495 for atrb in &self.transfer_trbs {
496 if !trb_is_valid(atrb) {
497 self.interrupter
498 .lock()
499 .send_transfer_event_trb(
500 TrbCompletionCode::TrbError,
501 atrb.gpa,
502 0,
503 false,
504 self.slot_id,
505 self.endpoint_id,
506 )
507 .map_err(Error::SendInterrupt)?;
508 valid = false;
509 }
510 }
511 Ok(valid)
512 }
513}
514
515fn trb_is_valid(atrb: &AddressedTrb) -> bool {
516 let can_be_in_transfer_ring = match atrb.trb.can_be_in_transfer_ring() {
517 Ok(v) => v,
518 Err(e) => {
519 error!("unknown error {:?}", e);
520 return false;
521 }
522 };
523 can_be_in_transfer_ring && (atrb.trb.interrupter_target() < MAX_INTERRUPTER)
524}