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