use thiserror::Error;
pub type Result<T> = std::result::Result<T, GsUsbError>;
#[derive(Error, Debug)]
pub enum GsUsbError {
#[error("USB error: {0}")]
Usb(#[from] rusb::Error),
#[error("No GS-USB device found")]
DeviceNotFound,
#[error("Device is not open")]
DeviceNotOpen,
#[error("Failed to claim USB interface: {0}")]
ClaimInterface(rusb::Error),
#[error("Failed to detach kernel driver: {0}")]
DetachKernelDriver(rusb::Error),
#[error("Unsupported bitrate {bitrate} for clock {clock_hz} Hz")]
UnsupportedBitrate { bitrate: u32, clock_hz: u32 },
#[error("Unsupported data bitrate {bitrate} for clock {clock_hz} Hz")]
UnsupportedDataBitrate { bitrate: u32, clock_hz: u32 },
#[error("Device does not support CAN FD")]
FdNotSupported,
#[error("Device does not support feature: {0}")]
FeatureNotSupported(&'static str),
#[error("Read timeout")]
ReadTimeout,
#[error("Write timeout")]
WriteTimeout,
#[error("Invalid response from device: expected {expected} bytes, got {actual}")]
InvalidResponse { expected: usize, actual: usize },
#[error("Control transfer failed: {0}")]
ControlTransfer(rusb::Error),
#[error("Bulk transfer failed: {0}")]
BulkTransfer(rusb::Error),
#[error("Device is already started")]
AlreadyStarted,
#[error("Device is not started")]
NotStarted,
#[error("Invalid channel number: {channel} (device has {max_channels} channels)")]
InvalidChannel { channel: u8, max_channels: u8 },
#[error("Device does not support GET_STATE feature")]
GetStateNotSupported,
}
impl GsUsbError {
pub fn is_timeout(&self) -> bool {
matches!(
self,
GsUsbError::ReadTimeout
| GsUsbError::WriteTimeout
| GsUsbError::Usb(rusb::Error::Timeout)
)
}
pub fn is_usb_error(&self) -> bool {
matches!(
self,
GsUsbError::Usb(_)
| GsUsbError::ClaimInterface(_)
| GsUsbError::DetachKernelDriver(_)
| GsUsbError::ControlTransfer(_)
| GsUsbError::BulkTransfer(_)
)
}
}