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_descriptor: TransferDescriptor,
171 completion_event: Event,
172 stream_id: Option<u16>,
173 ) -> XhciTransfer {
174 let transfer_dir = {
175 if endpoint_id == 0 {
176 TransferDirection::Control
177 } else if (endpoint_id % 2) == 0 {
178 TransferDirection::Out
179 } else {
180 TransferDirection::In
181 }
182 };
183 let t = XhciTransfer {
184 manager: self.clone(),
185 state: Arc::new(Mutex::new(XhciTransferState::Created)),
186 mem,
187 port,
188 interrupter,
189 transfer_completion_event: completion_event,
190 slot_id,
191 endpoint_id,
192 transfer_dir,
193 transfer_descriptor,
194 device_slot: self.device_slot.clone(),
195 stream_id,
196 };
197 self.transfers.lock().push(Arc::downgrade(&t.state));
198 t
199 }
200
201 pub fn cancel_all(&self) {
203 self.transfers.lock().iter().for_each(|t| {
204 let state = match t.upgrade() {
205 Some(state) => state,
206 None => {
207 error!("transfer is already cancelled or finished");
208 return;
209 }
210 };
211 state.lock().try_cancel();
212 });
213 }
214
215 fn remove_transfer(&self, t: &Arc<Mutex<XhciTransferState>>) {
216 let mut transfers = self.transfers.lock();
217 match transfers.iter().position(|wt| match wt.upgrade() {
218 Some(wt) => Arc::ptr_eq(&wt, t),
219 None => false,
220 }) {
221 None => error!("attempted to remove unknown transfer"),
222 Some(i) => {
223 transfers.swap_remove(i);
224 }
225 }
226 }
227}
228
229impl Default for XhciTransferManager {
230 fn default() -> Self {
231 Self::new(Weak::new())
232 }
233}
234
235pub struct XhciTransfer {
238 manager: XhciTransferManager,
239 state: Arc<Mutex<XhciTransferState>>,
240 mem: GuestMemory,
241 port: Arc<UsbPort>,
242 interrupter: Arc<Mutex<Interrupter>>,
243 slot_id: u8,
244 endpoint_id: u8,
246 transfer_dir: TransferDirection,
247 transfer_descriptor: TransferDescriptor,
248 transfer_completion_event: Event,
249 device_slot: Weak<DeviceSlot>,
250 stream_id: Option<u16>,
251}
252
253impl Drop for XhciTransfer {
254 fn drop(&mut self) {
255 self.manager.remove_transfer(&self.state);
256 }
257}
258
259impl fmt::Debug for XhciTransfer {
260 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
261 write!(
262 f,
263 "xhci_transfer slot id: {}, endpoint id {}, transfer_dir {:?}, transfer_descriptor {:?}",
264 self.slot_id, self.endpoint_id, self.transfer_dir, self.transfer_descriptor
265 )
266 }
267}
268
269impl XhciTransfer {
270 pub fn state(&self) -> &Arc<Mutex<XhciTransferState>> {
272 &self.state
273 }
274
275 pub fn get_transfer_type(&self) -> Result<XhciTransferType> {
277 match self
280 .transfer_descriptor
281 .first_atrb()
282 .trb
283 .get_trb_type()
284 .map_err(Error::TrbType)?
285 {
286 TrbType::Normal => Ok(XhciTransferType::Normal),
287 TrbType::SetupStage => Ok(XhciTransferType::SetupStage),
288 TrbType::DataStage => Ok(XhciTransferType::DataStage),
289 TrbType::StatusStage => Ok(XhciTransferType::StatusStage),
290 TrbType::Isoch => Ok(XhciTransferType::Isochronous),
291 TrbType::Noop => Ok(XhciTransferType::Noop),
292 t => Err(Error::BadTrbType(t)),
293 }
294 }
295
296 pub fn create_buffer(&self) -> Result<ScatterGatherBuffer> {
298 ScatterGatherBuffer::new(self.mem.clone(), self.transfer_descriptor.clone())
299 .map_err(Error::CreateBuffer)
300 }
301
302 pub fn create_usb_request_setup(&self) -> Result<UsbRequestSetup> {
304 let first_atrb = self.transfer_descriptor.first_atrb();
305 let trb = first_atrb
306 .trb
307 .checked_cast::<SetupStageTrb>()
308 .map_err(Error::CastTrb)?;
309 Ok(UsbRequestSetup::new(
310 trb.get_request_type(),
311 trb.get_request(),
312 trb.get_value(),
313 trb.get_index(),
314 trb.get_length(),
315 ))
316 }
317
318 pub fn get_endpoint_number(&self) -> u8 {
320 self.endpoint_id / 2
322 }
323
324 pub fn get_transfer_dir(&self) -> TransferDirection {
326 self.transfer_dir
327 }
328
329 pub fn get_stream_id(&self) -> Option<u16> {
331 self.stream_id
332 }
333
334 pub fn on_transfer_complete(
336 &self,
337 status: &TransferStatus,
338 bytes_transferred: u32,
339 ) -> Result<()> {
340 match status {
341 TransferStatus::NoDevice => {
342 info!("xhci: device disconnected, detaching from port");
343 return match self.port.detach() {
346 Ok(()) => Ok(()),
347 Err(HubError::AlreadyDetached(_e)) => Ok(()),
350 Err(e) => Err(Error::DetachPort(e)),
351 };
352 }
353 TransferStatus::Cancelled => {
354 return self
357 .transfer_completion_event
358 .signal()
359 .map_err(Error::WriteCompletionEvent);
360 }
361 TransferStatus::Completed => {
362 self.transfer_completion_event
363 .signal()
364 .map_err(Error::WriteCompletionEvent)?;
365 }
366 TransferStatus::Stalled => {
367 warn!("xhci: endpoint is stalled. set state to Halted");
368 if let Some(device_slot) = self.device_slot.upgrade() {
369 device_slot
370 .halt_endpoint(self.endpoint_id)
371 .map_err(|_| Error::HaltEndpoint(self.endpoint_id))?;
372 }
373 self.transfer_completion_event
374 .signal()
375 .map_err(Error::WriteCompletionEvent)?;
376 }
377 _ => {
378 self.transfer_completion_event
382 .signal()
383 .map_err(Error::WriteCompletionEvent)?;
384 }
385 }
386
387 let mut edtla: u32 = 0;
388 for atrb in &self.transfer_descriptor {
395 edtla += atrb.trb.transfer_length().map_err(Error::TransferLength)?;
396 if atrb.trb.interrupt_on_completion()
397 || (atrb.trb.interrupt_on_short_packet() && edtla > bytes_transferred)
398 {
399 if atrb.trb.get_trb_type().map_err(Error::TrbType)? == TrbType::EventData {
401 let tlength = min(edtla, bytes_transferred);
402 self.interrupter
403 .lock()
404 .send_transfer_event_trb(
405 TrbCompletionCode::Success,
406 atrb.trb
407 .cast::<EventDataTrb>()
408 .map_err(Error::CastTrb)?
409 .get_event_data(),
410 tlength,
411 true,
412 self.slot_id,
413 self.endpoint_id,
414 )
415 .map_err(Error::SendInterrupt)?;
416 } else if *status == TransferStatus::Stalled {
417 debug!("xhci: on transfer complete stalled");
418 let residual_transfer_length = edtla - bytes_transferred;
419 self.interrupter
420 .lock()
421 .send_transfer_event_trb(
422 TrbCompletionCode::StallError,
423 atrb.gpa,
424 residual_transfer_length,
425 true,
426 self.slot_id,
427 self.endpoint_id,
428 )
429 .map_err(Error::SendInterrupt)?;
430 } else {
431 if edtla > bytes_transferred {
433 debug!("xhci: on transfer complete short packet");
434 let residual_transfer_length = edtla - bytes_transferred;
435 self.interrupter
436 .lock()
437 .send_transfer_event_trb(
438 TrbCompletionCode::ShortPacket,
439 atrb.gpa,
440 residual_transfer_length,
441 true,
442 self.slot_id,
443 self.endpoint_id,
444 )
445 .map_err(Error::SendInterrupt)?;
446 } else {
447 debug!("xhci: on transfer complete success");
448 self.interrupter
449 .lock()
450 .send_transfer_event_trb(
451 TrbCompletionCode::Success,
452 atrb.gpa,
453 0, true,
455 self.slot_id,
456 self.endpoint_id,
457 )
458 .map_err(Error::SendInterrupt)?;
459 }
460 }
461 }
462 }
463 Ok(())
464 }
465
466 pub fn send_to_backend_if_valid(self) -> Result<()> {
468 if self.validate_transfer()? {
469 let port = self.port.clone();
471 let mut backend = port.backend_device();
472 match &mut *backend {
473 Some(backend) => backend
474 .lock()
475 .submit_xhci_transfer(self)
476 .map_err(|_| Error::SubmitTransfer)?,
477 None => {
478 error!("backend is already disconnected");
479 self.transfer_completion_event
480 .signal()
481 .map_err(Error::WriteCompletionEvent)?;
482 }
483 }
484 } else {
485 error!("invalid td on transfer ring");
486 self.transfer_completion_event
487 .signal()
488 .map_err(Error::WriteCompletionEvent)?;
489 }
490 Ok(())
491 }
492
493 fn validate_transfer(&self) -> Result<bool> {
496 let mut valid = true;
497 for atrb in &self.transfer_descriptor {
498 if !trb_is_valid(atrb) {
499 self.interrupter
500 .lock()
501 .send_transfer_event_trb(
502 TrbCompletionCode::TrbError,
503 atrb.gpa,
504 0,
505 false,
506 self.slot_id,
507 self.endpoint_id,
508 )
509 .map_err(Error::SendInterrupt)?;
510 valid = false;
511 }
512 }
513 Ok(valid)
514 }
515}
516
517fn trb_is_valid(atrb: &AddressedTrb) -> bool {
518 let can_be_in_transfer_ring = match atrb.trb.can_be_in_transfer_ring() {
519 Ok(v) => v,
520 Err(e) => {
521 error!("unknown error {:?}", e);
522 return false;
523 }
524 };
525 can_be_in_transfer_ring && (atrb.trb.interrupter_target() < MAX_INTERRUPTER)
526}