1use rusb::Error as UsbLibError;
2use std::fmt;
3
4pub type Result<T> = std::result::Result<T, Error>;
5
6#[derive(Debug)]
7pub enum Error {
8 DeviceNotOpen,
9 DeviceNotFound {
10 vid: u16,
11 pid: u16,
12 },
13 FeatureUnavailable(&'static str),
14 InvalidBitfile(&'static str),
15 NotProgrammed,
16 Timeout(&'static str),
17 UnexpectedResponse(&'static str),
18 VersionMismatch {
19 expected: u16,
20 actual: u16,
21 },
22 Usb {
23 source: UsbLibError,
24 context: &'static str,
25 },
26 Io(std::io::Error),
27}
28
29impl fmt::Display for Error {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 Error::DeviceNotOpen => write!(f, "device is not open"),
33 Error::DeviceNotFound { vid, pid } => {
34 write!(f, "device {vid:#06x}:{pid:#06x} not found")
35 }
36 Error::FeatureUnavailable(feature) => write!(f, "feature `{feature}` is unavailable"),
37 Error::InvalidBitfile(reason) => write!(f, "invalid bitfile: {reason}"),
38 Error::NotProgrammed => write!(f, "FPGA is not programmed"),
39 Error::Timeout(context) => write!(f, "operation `{context}` timed out"),
40 Error::UnexpectedResponse(context) => {
41 write!(f, "unexpected response during `{context}`")
42 }
43 Error::VersionMismatch { expected, actual } => write!(
44 f,
45 "SMIMS version mismatch (expected {expected:#06x}, found {actual:#06x})"
46 ),
47 Error::Usb { source, context } => {
48 write!(f, "usb error {source} in `{context}`")
49 }
50 Error::Io(err) => err.fmt(f),
51 }
52 }
53}
54
55impl std::error::Error for Error {
56 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
57 match self {
58 Error::Usb { source, .. } => Some(source),
59 Error::Io(err) => Some(err),
60 _ => None,
61 }
62 }
63}
64
65impl From<std::io::Error> for Error {
66 fn from(value: std::io::Error) -> Self {
67 Self::Io(value)
68 }
69}