linux_gpib_rs/
error.rs

1use crate::status::IbStatus;
2use std::error::Error;
3use std::ffi::NulError;
4use std::fmt;
5use std::num::TryFromIntError;
6use std::str::Utf8Error;
7use std::string::FromUtf8Error;
8#[cfg(feature = "async-tokio")]
9use tokio::task::JoinError;
10
11pub enum IbError {
12    EDVR(i64), // In this case, we hold also ibcntl value
13    ECIC,
14    ENOL,
15    EADR,
16    EARG,
17    ESAC,
18    EABO,
19    ENEB,
20    EDMA,
21    EOIP,
22    ECAP,
23    EFSO(i64), // In this case, we hold also ibcntl value
24    EBUS,
25    ESTB,
26    ESRQ,
27    ETAB,
28}
29
30pub enum GpibError {
31    DriverError(IbStatus, IbError),
32    Timeout,
33    ValueError(String),
34    #[cfg(feature = "async-tokio")]
35    TokioError(JoinError),
36}
37
38impl Error for GpibError {}
39
40impl fmt::Display for GpibError {
41    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42        match self {
43            GpibError::DriverError(status, error) => {
44                write!(f, "GpibError({}, {})", status, error)
45            }
46            GpibError::Timeout => {
47                write!(f, "Timeout")
48            }
49            GpibError::ValueError(desc) => {
50                write!(f, "ValueError({})", desc)
51            }
52            #[cfg(feature = "async-tokio")]
53            GpibError::TokioError(e) => {
54                write!(f, "Tokio Error ({})", e)
55            }
56        }
57    }
58}
59
60impl fmt::Debug for GpibError {
61    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62        match self {
63            GpibError::DriverError(status, error) => {
64                write!(f, "GpibError({:?}, {:?})", status, error)
65            }
66            GpibError::Timeout => {
67                write!(f, "Timeout")
68            }
69            GpibError::ValueError(desc) => {
70                write!(f, "ValueError({})", desc)
71            }
72            #[cfg(feature = "async-tokio")]
73            GpibError::TokioError(e) => {
74                write!(f, "Tokio Error ({:?})", e)
75            }
76        }
77    }
78}
79
80impl fmt::Display for IbError {
81    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82        match self {
83            IbError::EDVR(ibcntl) => {
84                write!(f, "EDVR  (ibcntl = {ibcntl})")
85            }
86            IbError::ECIC => {
87                write!(f, "ECIC")
88            }
89            IbError::ENOL => {
90                write!(f, "ENOL")
91            }
92            IbError::EADR => {
93                write!(f, "EADR")
94            }
95            IbError::EARG => {
96                write!(f, "EARG")
97            }
98            IbError::ESAC => {
99                write!(f, "ESAC")
100            }
101            IbError::EABO => {
102                write!(f, "EABO")
103            }
104            IbError::ENEB => {
105                write!(f, "ENEB")
106            }
107            IbError::EDMA => {
108                write!(f, "EDMA")
109            }
110            IbError::EOIP => {
111                write!(f, "EOIP")
112            }
113            IbError::ECAP => {
114                write!(f, "ECAP")
115            }
116            IbError::EFSO(ibcntl) => {
117                write!(f, "EFSO (ibcntl = {ibcntl})")
118            }
119            IbError::EBUS => {
120                write!(f, "EBUS")
121            }
122            IbError::ESTB => {
123                write!(f, "ESTB")
124            }
125            IbError::ESRQ => {
126                write!(f, "ESRQ")
127            }
128            IbError::ETAB => {
129                write!(f, "ETAB")
130            }
131        }
132    }
133}
134
135impl fmt::Debug for IbError {
136    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137        match self {
138            IbError::EDVR(ibcntl) => {
139                write!(f, "EDVR  (A system call has failed. ibcntl = {ibcntl})")
140            }
141            IbError::ECIC => {
142                write!(
143                    f,
144                    "ECIC (Your interface board needs to be controller-in-charge, but is not)"
145                )
146            }
147            IbError::ENOL => {
148                write!(f, "ENOL (You have attempted to write data or command bytes, but there are no listeners currently addressed)")
149            }
150            IbError::EADR => {
151                write!(f, "EADR (The interface board has failed to address itself properly before starting an io operation)")
152            }
153            IbError::EARG => {
154                write!(
155                    f,
156                    "EARG (One or more arguments to the function call were invalid)"
157                )
158            }
159            IbError::ESAC => {
160                write!(
161                    f,
162                    "ESAC (The interface board needs to be system controller, but is not)"
163                )
164            }
165            IbError::EABO => {
166                write!(f, "EABO (A read or write of data bytes has been aborted, possibly due to a timeout or reception of a device clear command)")
167            }
168            IbError::ENEB => {
169                write!(f, "ENEB (The GPIB interface board does not exist, its driver is not loaded, or it is not configured properly)")
170            }
171            IbError::EDMA => {
172                write!(
173                    f,
174                    "EDMA (Not used DMA error, included for compatibility purposes)"
175                )
176            }
177            IbError::EOIP => {
178                write!(f, "EOIP (Function call can not proceed due to an asynchronous IO operation in progress)")
179            }
180            IbError::ECAP => {
181                write!(f, "ECAP (incapable of executing function call, due the GPIB board lacking the capability, or the capability being disabled in software)")
182            }
183            IbError::EFSO(ibcntl) => {
184                write!(f, "EFSO (file system error, ibcntl = {ibcntl})")
185            }
186            IbError::EBUS => {
187                write!(
188                    f,
189                    "EBUS (an attempt to write command bytes to the bus has timed out)"
190                )
191            }
192            IbError::ESTB => {
193                write!(f, "ESTB (one or more serial poll status bytes have been lost. This can occur due to too many status bytes accumulating, through automatic serial polling, without being read)")
194            }
195            IbError::ESRQ => {
196                write!(f, "ESRQ (the serial poll request service line is stuck on. This can occur if a physical device on the bus requests service, but its GPIB address has not been opened by any process. Thus the automatic serial polling routines are unaware of the device's existence and will never serial poll it)")
197            }
198            IbError::ETAB => {
199                write!(f, "ETAB (this error can be returned by ibevent(), FindLstn(), or FindRQS(). See their descriptions for more information)")
200            }
201        }
202    }
203}
204
205impl IbError {
206    /// Create IbError from iberr value
207    pub fn from_iberr(iberr: i32) -> Result<IbError, GpibError> {
208        match iberr {
209            0 => Ok(IbError::EDVR(unsafe { linux_gpib_sys::ibcntl })),
210            1 => Ok(IbError::ECIC),
211            2 => Ok(IbError::ENOL),
212            3 => Ok(IbError::EADR),
213            4 => Ok(IbError::EARG),
214            5 => Ok(IbError::ESAC),
215            6 => Ok(IbError::EABO),
216            7 => Ok(IbError::ENEB),
217            8 => Ok(IbError::EDMA),
218            10 => Ok(IbError::EOIP),
219            11 => Ok(IbError::ECAP),
220            12 => Ok(IbError::EFSO(unsafe { linux_gpib_sys::ibcntl })),
221            14 => Ok(IbError::EBUS),
222            15 => Ok(IbError::ESTB),
223            16 => Ok(IbError::ESRQ),
224            20 => Ok(IbError::ETAB),
225            other => Err(GpibError::ValueError(format!(
226                "Unexpected iberr value = {}.",
227                other
228            ))),
229        }
230    }
231
232    /// Create IbError from current Linux-GPIB global iberr variable
233    pub fn current_error() -> Result<IbError, GpibError> {
234        let status = IbStatus::current_status();
235        if status.err {
236            IbError::from_iberr(unsafe { linux_gpib_sys::iberr })
237        } else {
238            Err(GpibError::ValueError(format!(
239                "Unable to get error because is not ERR (status = {:?})",
240                status
241            )))
242        }
243    }
244}
245
246impl From<NulError> for GpibError {
247    fn from(e: NulError) -> GpibError {
248        GpibError::ValueError(format!("{:?}", e))
249    }
250}
251
252impl From<TryFromIntError> for GpibError {
253    fn from(e: TryFromIntError) -> GpibError {
254        GpibError::ValueError(format!("{:?}", e,))
255    }
256}
257
258impl From<FromUtf8Error> for GpibError {
259    fn from(e: FromUtf8Error) -> GpibError {
260        GpibError::ValueError(format!("{:?}", e,))
261    }
262}
263
264impl From<Utf8Error> for GpibError {
265    fn from(e: Utf8Error) -> GpibError {
266        GpibError::ValueError(format!("{:?}", e,))
267    }
268}
269
270#[cfg(feature = "async-tokio")]
271impl From<JoinError> for GpibError {
272    fn from(e: JoinError) -> GpibError {
273        GpibError::TokioError(e)
274    }
275}