Skip to main content

crab_usb/
err.rs

1use core::fmt::Display;
2
3pub use usb_if::err::{TransferError, USBError};
4use xhci::ring::trb::event::CompletionCode;
5
6pub type Result<T = ()> = core::result::Result<T, USBError>;
7
8pub trait ConvertXhciError {
9    fn to_result(self) -> core::result::Result<(), TransferError>;
10}
11
12impl ConvertXhciError for CompletionCode {
13    fn to_result(self) -> core::result::Result<(), TransferError> {
14        match self {
15            CompletionCode::Success => Ok(()),
16            CompletionCode::ShortPacket => Ok(()),
17            CompletionCode::StallError => Err(TransferError::Stall),
18            CompletionCode::MissedServiceError => {
19                // MissedServiceError 通常是暂时性的,可以重试
20                Err(TransferError::Other(anyhow!(
21                    "XHCI temporary error: {self:?}"
22                )))
23            }
24            _ => Err(TransferError::Other(anyhow!("XHCI error: {self:?}"))),
25        }
26    }
27}
28
29#[derive(thiserror::Error, Debug)]
30pub struct HostError(USBError);
31
32impl Display for HostError {
33    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
34        write!(f, "{}", self.0)
35    }
36}
37
38impl From<dma_api::DmaError> for HostError {
39    fn from(value: dma_api::DmaError) -> Self {
40        match value {
41            dma_api::DmaError::NoMemory => Self(USBError::NoMemory),
42            dma_api::DmaError::DmaMaskNotMatch { .. } => Self(USBError::NoMemory),
43            e => Self(USBError::Other(e.into())),
44        }
45    }
46}
47
48impl From<HostError> for USBError {
49    fn from(value: HostError) -> Self {
50        value.0
51    }
52}