tegra_rcm/
error.rs

1use std::fmt::Display;
2
3use thiserror::Error;
4
5/// A result of a function that may return a `Error`.
6pub(crate) type Result<T> = std::result::Result<T, SwitchError>;
7
8/// An error interacting with the Switch in RCM mode
9#[derive(Error, Debug, Clone, PartialEq, Eq)]
10#[non_exhaustive]
11pub enum SwitchError {
12    /// Expected to get a timeout after smashing the stack but we did not
13    #[error("expected timeout error after smashing the stack")]
14    ExpectedError,
15
16    /// Cannot find a switch in RCM mode connected
17    #[error("switch in RCM mode not found")]
18    SwitchNotFound,
19
20    /// Usb device was not initialized
21    #[error("usb device was not initialized")]
22    NotInit,
23
24    /// Unable to claim the Switches interface
25    #[error("unable to claim interface: `{0}`")]
26    UsbBadInterface(u8),
27
28    /// A linux environment error such as not having the correct usb driver support
29    #[error(
30        "linux environment error, typically this means the system lacks a supported USB driver"
31    )]
32    LinuxEnv,
33
34    /// USB permission error
35    /// See <https://github.com/budde25/switcheroo#linux-permission-denied-error>
36    #[error("access denied (insufficient permissions)")]
37    AccessDenied,
38
39    /// Running on an unsupported platform
40    #[error("platform not supported")]
41    PlatformNotSupported,
42
43    /// A Windows error that the switch RCM has the wrong driver, please install libusbK
44    /// See <https://github.com/budde25/switcheroo#windows-wrong-driver-error>
45    #[error("wrong RCM USB driver installed (installed: `{0}` but must be libusbK)")]
46    WindowsWrongDriver(WindowsDriver),
47
48    /// udev rules not installed
49    #[error("udev rules not found at `/etc/udev/rules.d/99-switch.rules`")]
50    UdevRulesNotFound,
51
52    /// This is a catchall error for various other things that can go wrong with underlying usb library.
53    /// It has been converted to a string to not expose the underlying api
54    #[error("usb error: `{0}`")]
55    Usb(String),
56}
57
58/// Defines the installed driver on windows
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum WindowsDriver {
61    LibUsbK,
62    LibUsb0,
63    WinUsb,
64    LibUsb0Filter,
65    Count,
66}
67
68impl Display for WindowsDriver {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        match self {
71            Self::LibUsbK => write!(f, "libusbK"),
72            Self::LibUsb0 => write!(f, "libusb0"),
73            Self::WinUsb => write!(f, "winusb"),
74            Self::LibUsb0Filter => write!(f, "libusb0 filter"),
75            Self::Count => write!(f, "count"),
76        }
77    }
78}
79
80#[cfg(target_os = "windows")]
81impl From<libusbk::DriverId> for WindowsDriver {
82    fn from(driver: libusbk::DriverId) -> Self {
83        use libusbk::DriverId;
84
85        match driver {
86            DriverId::LibUsbK => Self::LibUsbK,
87            DriverId::LibUsb0 => Self::LibUsb0,
88            DriverId::WinUsb => Self::WinUsb,
89            DriverId::LibUsb0Filter => Self::LibUsb0Filter,
90            DriverId::Count => Self::Count,
91        }
92    }
93}
94
95#[cfg(target_os = "windows")]
96impl From<libusbk::Error> for SwitchError {
97    fn from(err: libusbk::Error) -> Self {
98        Self::Usb(err.to_string())
99    }
100}
101
102#[cfg(any(target_os = "macos", target_os = "linux"))]
103impl From<rusb::Error> for SwitchError {
104    fn from(err: rusb::Error) -> Self {
105        match err {
106            rusb::Error::Access => Self::AccessDenied,
107            rusb::Error::NoDevice => Self::SwitchNotFound,
108            rusb::Error::NotFound => Self::SwitchNotFound,
109            _ => Self::Usb(err.to_string()),
110        }
111    }
112}