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), ECIC,
14 ENOL,
15 EADR,
16 EARG,
17 ESAC,
18 EABO,
19 ENEB,
20 EDMA,
21 EOIP,
22 ECAP,
23 EFSO(i64), 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 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 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}