socketcan_hal/
err.rs

1// information from https://raw.githubusercontent.com/torvalds/linux/master/
2//                  /include/uapi/linux/can/error.h
3
4use super::CanFrame;
5use std::{
6    convert::TryFrom,
7    error,
8    fmt,
9    io,
10};
11
12
13#[inline]
14/// Helper function to retrieve a specific byte of frame data or returning an
15/// `Err(..)` otherwise.
16fn get_data(frame: &CanFrame, idx: u8) -> Result<u8, CanErrorDecodingFailure> {
17    Ok(*(frame.data()
18        .get(idx as usize)
19        .ok_or(CanErrorDecodingFailure::NotEnoughData(idx)))?)
20}
21
22
23/// Error decoding a CanError from a CanFrame.
24#[derive(Copy, Clone, Debug)]
25pub enum CanErrorDecodingFailure {
26    /// The supplied CanFrame did not have the error bit set.
27    NotAnError,
28
29    /// The error type is not known and cannot be decoded.
30    UnknownErrorType(u32),
31
32    /// The error type indicated a need for additional information as `data`,
33    /// but the `data` field was not long enough.
34    NotEnoughData(u8),
35
36    /// The error type `ControllerProblem` was indicated and additional
37    /// information found, but not recognized.
38    InvalidControllerProblem,
39
40    /// The type of the ProtocolViolation was not valid
41    InvalidViolationType,
42
43    /// A location was specified for a ProtocolViolation, but the location
44    /// was not valid.
45    InvalidLocation,
46
47    /// The supplied transciever error was invalid.
48    InvalidTransceiverError,
49}
50
51impl error::Error for CanErrorDecodingFailure {}
52
53impl fmt::Display for CanErrorDecodingFailure {
54    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55        let msg = match *self {
56            CanErrorDecodingFailure::NotAnError => "CAN frame is not an error",
57            CanErrorDecodingFailure::UnknownErrorType(_) => "unknown error type",
58            CanErrorDecodingFailure::NotEnoughData(_) => "not enough data",
59            CanErrorDecodingFailure::InvalidControllerProblem => "not a valid controller problem",
60            CanErrorDecodingFailure::InvalidViolationType => "not a valid violation type",
61            CanErrorDecodingFailure::InvalidLocation => "not a valid location",
62            CanErrorDecodingFailure::InvalidTransceiverError => "not a valid transceiver error",
63        };
64        write!(f, "{}", msg)
65    }
66}
67
68
69#[derive(Copy, Clone, Debug)]
70pub enum CanError {
71    /// TX timeout (by netdevice driver)
72    TransmitTimeout,
73
74    /// Arbitration was lost. Contains the number after which arbitration was
75    /// lost or 0 if unspecified
76    LostArbitration(u8),
77
78    /// Controller problem, see `ControllerProblem`
79    ControllerProblem(ControllerProblem),
80
81    /// Protocol violation at the specified `Location`. See `ProtocolViolation`
82    /// for details.
83    ProtocolViolation {
84        vtype: ViolationType,
85        location: Location,
86    },
87
88    /// Transceiver Error.
89    TransceiverError,
90
91    /// No ACK received for current CAN frame.
92    NoAck,
93
94    /// Bus off (due to too many detected errors)
95    BusOff,
96
97    /// Bus error (due to too many detected errors)
98    BusError,
99
100    /// The bus has been restarted
101    Restarted,
102
103    /// Unknown, possibly invalid, error
104    Unknown(u32),
105}
106
107impl error::Error for CanError {}
108
109impl fmt::Display for CanError {
110    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111        match *self {
112            CanError::TransmitTimeout => write!(f, "transmission timeout"),
113            CanError::LostArbitration(n) => write!(f, "arbitration lost after {} bits", n),
114            CanError::ControllerProblem(e) => write!(f, "controller problem: {}", e),
115            CanError::ProtocolViolation { vtype, location } => {
116                write!(f, "protocol violation at {}: {}", location, vtype)
117            }
118            CanError::TransceiverError => write!(f, "transceiver error"),
119            CanError::NoAck => write!(f, "no ack"),
120            CanError::BusOff => write!(f, "bus off"),
121            CanError::BusError => write!(f, "bus error"),
122            CanError::Restarted => write!(f, "restarted"),
123            CanError::Unknown(errno) => write!(f, "unknown error ({})", errno),
124        }
125    }
126}
127
128
129#[derive(Copy, Clone, Debug)]
130pub enum ControllerProblem {
131    // unspecified
132    Unspecified,
133
134    // RX buffer overflow
135    ReceiveBufferOverflow,
136
137    // TX buffer overflow
138    TransmitBufferOverflow,
139
140    // reached warning level for RX errors
141    ReceiveErrorWarning,
142
143    // reached warning level for TX errors
144    TransmitErrorWarning,
145
146    // reached error passive status RX
147    ReceiveErrorPassive,
148
149    // reached error passive status TX
150    TransmitErrorPassive,
151
152    // recovered to error active state
153    Active,
154}
155
156impl error::Error for ControllerProblem {}
157
158impl fmt::Display for ControllerProblem {
159    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160        let msg = match *self {
161            ControllerProblem::Unspecified => "unspecified controller problem",
162            ControllerProblem::ReceiveBufferOverflow => "receive buffer overflow",
163            ControllerProblem::TransmitBufferOverflow => "transmit buffer overflow",
164            ControllerProblem::ReceiveErrorWarning => "ERROR WARNING (receive)",
165            ControllerProblem::TransmitErrorWarning => "ERROR WARNING (transmit)",
166            ControllerProblem::ReceiveErrorPassive => "ERROR PASSIVE (receive)",
167            ControllerProblem::TransmitErrorPassive => "ERROR PASSIVE (transmit)",
168            ControllerProblem::Active => "ERROR ACTIVE",
169        };
170        write!(f, "{}", msg)
171    }
172}
173
174impl TryFrom<u8> for ControllerProblem {
175    type Error = CanErrorDecodingFailure;
176
177    fn try_from(val: u8) -> Result<Self, Self::Error> {
178        Ok(match val {
179            0x00 => ControllerProblem::Unspecified,
180            0x01 => ControllerProblem::ReceiveBufferOverflow,
181            0x02 => ControllerProblem::TransmitBufferOverflow,
182            0x04 => ControllerProblem::ReceiveErrorWarning,
183            0x08 => ControllerProblem::TransmitErrorWarning,
184            0x10 => ControllerProblem::ReceiveErrorPassive,
185            0x20 => ControllerProblem::TransmitErrorPassive,
186            0x40 => ControllerProblem::Active,
187            _ => return Err(CanErrorDecodingFailure::InvalidControllerProblem),
188        })
189    }
190}
191
192#[derive(Copy, Clone, Debug)]
193pub enum ViolationType {
194    /// Unspecified Violation
195    Unspecified,
196
197    /// Single Bit Error
198    SingleBitError,
199
200    /// Frame formatting error
201    FrameFormatError,
202
203    /// Bit stuffing error
204    BitStuffingError,
205
206    /// A dominant bit was sent, but not received
207    UnableToSendDominantBit,
208
209    /// A recessive bit was sent, but not received
210    UnableToSendRecessiveBit,
211
212    /// Bus overloaded
213    BusOverload,
214
215    /// Bus is active (again)
216    Active,
217
218    /// Transmission Error
219    TransmissionError,
220}
221
222impl error::Error for ViolationType {}
223
224impl fmt::Display for ViolationType {
225    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226        let msg = match *self {
227            ViolationType::Unspecified => "unspecified",
228            ViolationType::SingleBitError => "single bit error",
229            ViolationType::FrameFormatError => "frame format error",
230            ViolationType::BitStuffingError => "bit stuffing error",
231            ViolationType::UnableToSendDominantBit => "unable to send dominant bit",
232            ViolationType::UnableToSendRecessiveBit => "unable to send recessive bit",
233            ViolationType::BusOverload => "bus overload",
234            ViolationType::Active => "active",
235            ViolationType::TransmissionError => "transmission error",
236        };
237        write!(f, "{}", msg)
238    }
239}
240
241impl TryFrom<u8> for ViolationType {
242    type Error = CanErrorDecodingFailure;
243
244    fn try_from(val: u8) -> Result<Self, Self::Error> {
245        Ok(match val {
246            0x00 => ViolationType::Unspecified,
247            0x01 => ViolationType::SingleBitError,
248            0x02 => ViolationType::FrameFormatError,
249            0x04 => ViolationType::BitStuffingError,
250            0x08 => ViolationType::UnableToSendDominantBit,
251            0x10 => ViolationType::UnableToSendRecessiveBit,
252            0x20 => ViolationType::BusOverload,
253            0x40 => ViolationType::Active,
254            0x80 => ViolationType::TransmissionError,
255            _ => return Err(CanErrorDecodingFailure::InvalidViolationType),
256        })
257    }
258}
259
260/// Location
261///
262/// Describes where inside a received frame an error occured.
263#[derive(Copy, Clone, Debug)]
264pub enum Location {
265    /// Unspecified
266    Unspecified,
267
268    /// Start of frame.
269    StartOfFrame,
270
271    /// ID bits 28-21 (SFF: 10-3)
272    Id2821,
273
274    /// ID bits 20-18 (SFF: 2-0)
275    Id2018,
276
277    /// substitute RTR (SFF: RTR)
278    SubstituteRtr,
279
280    /// extension of identifier
281    IdentifierExtension,
282
283    /// ID bits 17-13
284    Id1713,
285
286    /// ID bits 12-5
287    Id1205,
288
289    /// ID bits 4-0
290    Id0400,
291
292    /// RTR bit
293    Rtr,
294
295    /// Reserved bit 1
296    Reserved1,
297
298    /// Reserved bit 0
299    Reserved0,
300
301    /// Data length
302    DataLengthCode,
303
304    /// Data section
305    DataSection,
306
307    /// CRC sequence
308    CrcSequence,
309
310    /// CRC delimiter
311    CrcDelimiter,
312
313    /// ACK slot
314    AckSlot,
315
316    /// ACK delimiter
317    AckDelimiter,
318
319    /// End-of-frame
320    EndOfFrame,
321
322    /// Intermission (between frames)
323    Intermission,
324}
325
326impl fmt::Display for Location {
327    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
328        let msg = match *self {
329            Location::Unspecified => "unspecified location",
330            Location::StartOfFrame => "start of frame",
331            Location::Id2821 => "ID, bits 28-21",
332            Location::Id2018 => "ID, bits 20-18",
333            Location::SubstituteRtr => "substitute RTR bit",
334            Location::IdentifierExtension => "ID, extension",
335            Location::Id1713 => "ID, bits 17-13",
336            Location::Id1205 => "ID, bits 12-05",
337            Location::Id0400 => "ID, bits 04-00",
338            Location::Rtr => "RTR bit",
339            Location::Reserved1 => "reserved bit 1",
340            Location::Reserved0 => "reserved bit 0",
341            Location::DataLengthCode => "data length code",
342            Location::DataSection => "data section",
343            Location::CrcSequence => "CRC sequence",
344            Location::CrcDelimiter => "CRC delimiter",
345            Location::AckSlot => "ACK slot",
346            Location::AckDelimiter => "ACK delimiter",
347            Location::EndOfFrame => "end of frame",
348            Location::Intermission => "intermission",
349        };
350        write!(f, "{}", msg)
351    }
352}
353impl TryFrom<u8> for Location {
354    type Error = CanErrorDecodingFailure;
355
356    fn try_from(val: u8) -> Result<Self, Self::Error> {
357        Ok(match val {
358            0x00 => Location::Unspecified,
359            0x03 => Location::StartOfFrame,
360            0x02 => Location::Id2821,
361            0x06 => Location::Id2018,
362            0x04 => Location::SubstituteRtr,
363            0x05 => Location::IdentifierExtension,
364            0x07 => Location::Id1713,
365            0x0F => Location::Id1205,
366            0x0E => Location::Id0400,
367            0x0C => Location::Rtr,
368            0x0D => Location::Reserved1,
369            0x09 => Location::Reserved0,
370            0x0B => Location::DataLengthCode,
371            0x0A => Location::DataSection,
372            0x08 => Location::CrcSequence,
373            0x18 => Location::CrcDelimiter,
374            0x19 => Location::AckSlot,
375            0x1B => Location::AckDelimiter,
376            0x1A => Location::EndOfFrame,
377            0x12 => Location::Intermission,
378            _ => return Err(CanErrorDecodingFailure::InvalidLocation),
379        })
380    }
381}
382
383pub enum TransceiverError {
384    Unspecified,
385    CanHighNoWire,
386    CanHighShortToBat,
387    CanHighShortToVcc,
388    CanHighShortToGnd,
389    CanLowNoWire,
390    CanLowShortToBat,
391    CanLowShortToVcc,
392    CanLowShortToGnd,
393    CanLowShortToCanHigh,
394}
395
396impl TryFrom<u8> for TransceiverError {
397    type Error = CanErrorDecodingFailure;
398
399    fn try_from(val: u8) -> Result<Self, Self::Error> {
400        Ok(match val {
401            0x00 => TransceiverError::Unspecified,
402            0x04 => TransceiverError::CanHighNoWire,
403            0x05 => TransceiverError::CanHighShortToBat,
404            0x06 => TransceiverError::CanHighShortToVcc,
405            0x07 => TransceiverError::CanHighShortToGnd,
406            0x40 => TransceiverError::CanLowNoWire,
407            0x50 => TransceiverError::CanLowShortToBat,
408            0x60 => TransceiverError::CanLowShortToVcc,
409            0x70 => TransceiverError::CanLowShortToGnd,
410            0x80 => TransceiverError::CanLowShortToCanHigh,
411            _ => return Err(CanErrorDecodingFailure::InvalidTransceiverError),
412        })
413    }
414}
415
416impl CanError {
417    pub fn from_frame(frame: &CanFrame) -> Result<Self, CanErrorDecodingFailure> {
418        if !frame.is_error() {
419            return Err(CanErrorDecodingFailure::NotAnError);
420        }
421
422        match frame.err() {
423            0x00000001 => Ok(CanError::TransmitTimeout),
424            0x00000002 => Ok(CanError::LostArbitration(get_data(frame, 0)?)),
425            0x00000004 => {
426                Ok(CanError::ControllerProblem(ControllerProblem::try_from(get_data(frame, 1)?)?))
427            }
428
429            0x00000008 => {
430                Ok(CanError::ProtocolViolation {
431                    vtype: ViolationType::try_from(get_data(frame, 2)?)?,
432                    location: Location::try_from(get_data(frame, 3)?)?,
433                })
434            }
435
436            0x00000010 => Ok(CanError::TransceiverError),
437            0x00000020 => Ok(CanError::NoAck),
438            0x00000040 => Ok(CanError::BusOff),
439            0x00000080 => Ok(CanError::BusError),
440            0x00000100 => Ok(CanError::Restarted),
441            e => Err(CanErrorDecodingFailure::UnknownErrorType(e)),
442        }
443    }
444}
445
446pub trait ControllerSpecificErrorInformation {
447    fn get_ctrl_err(&self) -> Option<&[u8]>;
448}
449
450impl ControllerSpecificErrorInformation for CanFrame {
451    #[inline]
452    fn get_ctrl_err(&self) -> Option<&[u8]> {
453        let data = self.data();
454
455        if data.len() != 8 {
456            None
457        } else {
458            Some(&data[5..])
459        }
460    }
461}
462
463#[derive(Debug)]
464/// Errors opening socket
465pub enum CanSocketOpenError {
466    /// Device could not be found
467    LookupError(nix::Error),
468
469    /// System error while trying to look up device name
470    IOError(io::Error),
471}
472
473impl fmt::Display for CanSocketOpenError {
474    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
475        match *self {
476            CanSocketOpenError::LookupError(ref e) => write!(f, "CAN Device not found: {}", e),
477            CanSocketOpenError::IOError(ref e) => write!(f, "IO: {}", e),
478        }
479    }
480}
481
482impl error::Error for CanSocketOpenError {}
483
484#[derive(Debug, Copy, Clone)]
485/// Error that occurs when creating CAN packets
486pub enum ConstructionError {
487    /// CAN ID was outside the range of valid IDs
488    IDTooLarge,
489    /// More than 8 Bytes of payload data were passed in
490    TooMuchData,
491}
492
493impl fmt::Display for ConstructionError {
494    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
495        match *self {
496            ConstructionError::IDTooLarge => write!(f, "CAN ID too large"),
497            ConstructionError::TooMuchData => {
498                write!(f, "Payload is larger than CAN maximum of 8 bytes")
499            }
500        }
501    }
502}
503
504impl error::Error for ConstructionError {}
505
506impl From<nix::Error> for CanSocketOpenError {
507    fn from(e: nix::Error) -> CanSocketOpenError {
508        CanSocketOpenError::LookupError(e)
509    }
510}
511
512impl From<io::Error> for CanSocketOpenError {
513    fn from(e: io::Error) -> CanSocketOpenError {
514        CanSocketOpenError::IOError(e)
515    }
516}
517
518