linux_gpib_rs/
error.rs

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