Thanks to visit codestin.com
Credit goes to docs.rs

socketcan/
errors.rs

1// socketcan/src/errors.rs
2//
3// Implements errors for Rust SocketCAN library on Linux.
4//
5// This file is part of the Rust 'socketcan-rs' library.
6//
7// Licensed under the MIT license:
8//   <LICENSE or http://opensource.org/licenses/MIT>
9// This file may not be copied, modified, or distributed except according
10// to those terms.
11
12//! CAN bus errors.
13//!
14//! Most information about the errors on the CANbus are determined from an
15//! error frame. To receive them, the error mask must be set on the socket
16//! for the types of errors that the application would like to receive.
17//!
18//! See [RAW Socket Option CAN_RAW_ERR_FILTER](https://docs.kernel.org/networking/can.html#raw-socket-option-can-raw-err-filter)
19//!
20//! The general types of errors are encoded in the error bits of the CAN ID
21//! of an error frame. This is reported with [`CanError`]. Specific errors
22//! might indicate that more information can be obtained from the data bytes
23//! in the error frame.
24//!
25//! ```text
26//! Lost Arbitration   (0x02) => data[0]
27//! Controller Problem (0x04) => data[1]
28//! Protocol Violation (0x08) => data[2..3]
29//! Transceiver Status (0x10) => data[4]
30//!
31//! Error Counters (0x200) =>
32//!   TX Error Counter => data[6]
33//!   RX Error Counter => data[7]
34//! ```
35//!
36//! All of this error information is not well documented, but can be extracted
37//! from the Linux kernel header file:
38//! [linux/can/error.h](https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/can/error.h)
39//!
40
41use crate::{CanErrorFrame, EmbeddedFrame, Frame};
42use std::{convert::TryFrom, error, fmt, io};
43use thiserror::Error;
44
45// ===== Composite Error for the crate =====
46
47/// Composite SocketCAN error.
48///
49/// This can be any of the underlying errors from this library. The two main
50/// error sources are either CAN errors coming in through received error
51/// frames or from typical system I/O errors.
52#[derive(Error, Debug)]
53pub enum Error {
54    /// A CANbus error, usually from an error frmae
55    #[error(transparent)]
56    Can(#[from] CanError),
57    /// An I/O Error
58    #[error(transparent)]
59    Io(#[from] io::Error),
60}
61
62impl embedded_can::Error for Error {
63    fn kind(&self) -> embedded_can::ErrorKind {
64        match *self {
65            Error::Can(err) => err.kind(),
66            _ => embedded_can::ErrorKind::Other,
67        }
68    }
69}
70
71impl From<CanErrorFrame> for Error {
72    fn from(frame: CanErrorFrame) -> Self {
73        Error::Can(CanError::from(frame))
74    }
75}
76
77impl From<io::ErrorKind> for Error {
78    /// Creates an Io error straight from an io::ErrorKind
79    fn from(ek: io::ErrorKind) -> Self {
80        Self::from(io::Error::from(ek))
81    }
82}
83
84#[cfg(feature = "enumerate")]
85impl From<libudev::Error> for Error {
86    /// Creates an Io error straight from a libudev::Error
87    fn from(e: libudev::Error) -> Error {
88        match e.kind() {
89            libudev::ErrorKind::NoMem => Self::from(io::ErrorKind::OutOfMemory),
90            libudev::ErrorKind::InvalidInput => Self::from(io::ErrorKind::InvalidInput),
91            libudev::ErrorKind::Io(ek) => Self::from(ek),
92        }
93    }
94}
95
96/// A result that can derive from any of the CAN errors.
97pub type Result<T> = std::result::Result<T, Error>;
98
99/// An I/O specific error
100pub type IoError = io::Error;
101
102/// A kind of I/O error
103pub type IoErrorKind = io::ErrorKind;
104
105/// An I/O specific result
106pub type IoResult<T> = io::Result<T>;
107
108// ===== CanError ====
109
110/// A CAN bus error derived from an error frame.
111///
112/// An CAN interface device driver can send detailed error information up
113/// to the application in an "error frame". These are selectable by the
114/// application by applying an error bitmask to the socket to choose which
115/// types of errors to receive.
116///
117/// The error frame can then be converted into this `CanError` which is a
118/// proper Rust error type which implements std::error::Error.
119///
120/// Most error types here corresponds to a bit in the error mask of a CAN ID
121/// word of an error frame - a frame in which the CAN error flag
122/// (`CAN_ERR_FLAG`) is set. But there are additional types to handle any
123/// problems decoding the error frame.
124#[derive(Debug, Clone, Copy)]
125pub enum CanError {
126    /// TX timeout (by netdevice driver)
127    TransmitTimeout,
128    /// Arbitration was lost.
129    /// Contains the bit number after which arbitration was lost or 0 if unspecified.
130    LostArbitration(u8),
131    /// Controller problem
132    ControllerProblem(ControllerProblem),
133    /// Protocol violation at the specified [`Location`].
134    ProtocolViolation {
135        /// The type of protocol violation
136        vtype: ViolationType,
137        /// The location (field or bit) of the violation
138        location: Location,
139    },
140    /// Transceiver Error.
141    TransceiverError,
142    /// No ACK received for current CAN frame.
143    NoAck,
144    /// Bus off (due to too many detected errors)
145    BusOff,
146    /// Bus error (due to too many detected errors)
147    BusError,
148    /// The bus has been restarted
149    Restarted,
150    /// There was an error decoding the error frame
151    DecodingFailure(CanErrorDecodingFailure),
152    /// Unknown, possibly invalid, error
153    Unknown(u32),
154}
155
156impl error::Error for CanError {}
157
158impl fmt::Display for CanError {
159    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160        use CanError::*;
161        match *self {
162            TransmitTimeout => write!(f, "transmission timeout"),
163            LostArbitration(n) => write!(f, "arbitration lost after {} bits", n),
164            ControllerProblem(e) => write!(f, "controller problem: {}", e),
165            ProtocolViolation { vtype, location } => {
166                write!(f, "protocol violation at {}: {}", location, vtype)
167            }
168            TransceiverError => write!(f, "transceiver error"),
169            NoAck => write!(f, "no ack"),
170            BusOff => write!(f, "bus off"),
171            BusError => write!(f, "bus error"),
172            Restarted => write!(f, "restarted"),
173            DecodingFailure(err) => write!(f, "decoding failure: {}", err),
174            Unknown(err) => write!(f, "unknown error ({})", err),
175        }
176    }
177}
178
179impl embedded_can::Error for CanError {
180    fn kind(&self) -> embedded_can::ErrorKind {
181        match *self {
182            CanError::ControllerProblem(cp) => {
183                use ControllerProblem::*;
184                match cp {
185                    ReceiveBufferOverflow | TransmitBufferOverflow => {
186                        embedded_can::ErrorKind::Overrun
187                    }
188                    _ => embedded_can::ErrorKind::Other,
189                }
190            }
191            CanError::NoAck => embedded_can::ErrorKind::Acknowledge,
192            _ => embedded_can::ErrorKind::Other,
193        }
194    }
195}
196
197impl From<CanErrorFrame> for CanError {
198    /// Constructs a CAN error from an error frame.
199    fn from(frame: CanErrorFrame) -> Self {
200        // Note that the CanErrorFrame is guaranteed to have the full 8-byte
201        // data payload.
202        match frame.error_bits() {
203            0x0001 => CanError::TransmitTimeout,
204            0x0002 => CanError::LostArbitration(frame.data()[0]),
205            0x0004 => match ControllerProblem::try_from(frame.data()[1]) {
206                Ok(err) => CanError::ControllerProblem(err),
207                Err(err) => CanError::DecodingFailure(err),
208            },
209            0x0008 => {
210                match (
211                    ViolationType::try_from(frame.data()[2]),
212                    Location::try_from(frame.data()[3]),
213                ) {
214                    (Ok(vtype), Ok(location)) => CanError::ProtocolViolation { vtype, location },
215                    (Err(err), _) | (_, Err(err)) => CanError::DecodingFailure(err),
216                }
217            }
218            0x0010 => CanError::TransceiverError,
219            0x0020 => CanError::NoAck,
220            0x0040 => CanError::BusOff,
221            0x0080 => CanError::BusError,
222            0x0100 => CanError::Restarted,
223            err => CanError::Unknown(err),
224        }
225    }
226}
227
228// ===== ControllerProblem =====
229
230/// Error status of the CAN controller.
231///
232/// This is derived from `data[1]` of an error frame
233#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
234#[repr(u8)]
235pub enum ControllerProblem {
236    /// unspecified
237    Unspecified = 0x00,
238    /// RX buffer overflow
239    ReceiveBufferOverflow = 0x01,
240    /// TX buffer overflow
241    TransmitBufferOverflow = 0x02,
242    /// reached warning level for RX errors
243    ReceiveErrorWarning = 0x04,
244    /// reached warning level for TX errors
245    TransmitErrorWarning = 0x08,
246    /// reached error passive status RX
247    ReceiveErrorPassive = 0x10,
248    /// reached error passive status TX
249    TransmitErrorPassive = 0x20,
250    /// recovered to error active state
251    Active = 0x40,
252}
253
254impl error::Error for ControllerProblem {}
255
256impl fmt::Display for ControllerProblem {
257    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258        use ControllerProblem::*;
259        let msg = match *self {
260            Unspecified => "unspecified controller problem",
261            ReceiveBufferOverflow => "receive buffer overflow",
262            TransmitBufferOverflow => "transmit buffer overflow",
263            ReceiveErrorWarning => "ERROR WARNING (receive)",
264            TransmitErrorWarning => "ERROR WARNING (transmit)",
265            ReceiveErrorPassive => "ERROR PASSIVE (receive)",
266            TransmitErrorPassive => "ERROR PASSIVE (transmit)",
267            Active => "ERROR ACTIVE",
268        };
269        write!(f, "{}", msg)
270    }
271}
272
273impl TryFrom<u8> for ControllerProblem {
274    type Error = CanErrorDecodingFailure;
275
276    fn try_from(val: u8) -> std::result::Result<Self, Self::Error> {
277        use ControllerProblem::*;
278        Ok(match val {
279            0x00 => Unspecified,
280            0x01 => ReceiveBufferOverflow,
281            0x02 => TransmitBufferOverflow,
282            0x04 => ReceiveErrorWarning,
283            0x08 => TransmitErrorWarning,
284            0x10 => ReceiveErrorPassive,
285            0x20 => TransmitErrorPassive,
286            0x40 => Active,
287            _ => return Err(CanErrorDecodingFailure::InvalidControllerProblem),
288        })
289    }
290}
291
292// ===== ViolationType =====
293
294/// The type of protocol violation error.
295///
296/// This is derived from `data[2]` of an error frame.
297#[derive(Debug, Clone, Copy, PartialEq, Eq)]
298#[repr(u8)]
299pub enum ViolationType {
300    /// Unspecified Violation
301    Unspecified = 0x00,
302    /// Single Bit Error
303    SingleBitError = 0x01,
304    /// Frame formatting error
305    FrameFormatError = 0x02,
306    /// Bit stuffing error
307    BitStuffingError = 0x04,
308    /// A dominant bit was sent, but not received
309    UnableToSendDominantBit = 0x08,
310    /// A recessive bit was sent, but not received
311    UnableToSendRecessiveBit = 0x10,
312    /// Bus overloaded
313    BusOverload = 0x20,
314    /// Bus is active (again)
315    Active = 0x40,
316    /// Transmission Error
317    TransmissionError = 0x80,
318}
319
320impl error::Error for ViolationType {}
321
322impl fmt::Display for ViolationType {
323    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
324        use ViolationType::*;
325        let msg = match *self {
326            Unspecified => "unspecified",
327            SingleBitError => "single bit error",
328            FrameFormatError => "frame format error",
329            BitStuffingError => "bit stuffing error",
330            UnableToSendDominantBit => "unable to send dominant bit",
331            UnableToSendRecessiveBit => "unable to send recessive bit",
332            BusOverload => "bus overload",
333            Active => "active",
334            TransmissionError => "transmission error",
335        };
336        write!(f, "{}", msg)
337    }
338}
339
340impl TryFrom<u8> for ViolationType {
341    type Error = CanErrorDecodingFailure;
342
343    fn try_from(val: u8) -> std::result::Result<Self, Self::Error> {
344        use ViolationType::*;
345        Ok(match val {
346            0x00 => Unspecified,
347            0x01 => SingleBitError,
348            0x02 => FrameFormatError,
349            0x04 => BitStuffingError,
350            0x08 => UnableToSendDominantBit,
351            0x10 => UnableToSendRecessiveBit,
352            0x20 => BusOverload,
353            0x40 => Active,
354            0x80 => TransmissionError,
355            _ => return Err(CanErrorDecodingFailure::InvalidViolationType),
356        })
357    }
358}
359
360/// The location of a CANbus protocol violation.
361///
362/// This describes the position inside a received frame (as in the field
363/// or bit) at which an error occurred.
364///
365/// This is derived from `data[3]` of an error frame.
366#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
367#[repr(u8)]
368pub enum Location {
369    /// Unspecified
370    Unspecified = 0x00,
371    /// Start of frame.
372    StartOfFrame = 0x03,
373    /// ID bits 28-21 (SFF: 10-3)
374    Id2821 = 0x02,
375    /// ID bits 20-18 (SFF: 2-0)
376    Id2018 = 0x06,
377    /// substitute RTR (SFF: RTR)
378    SubstituteRtr = 0x04,
379    /// extension of identifier
380    IdentifierExtension = 0x05,
381    /// ID bits 17-13
382    Id1713 = 0x07,
383    /// ID bits 12-5
384    Id1205 = 0x0F,
385    /// ID bits 4-0
386    Id0400 = 0x0E,
387    /// RTR bit
388    Rtr = 0x0C,
389    /// Reserved bit 1
390    Reserved1 = 0x0D,
391    /// Reserved bit 0
392    Reserved0 = 0x09,
393    /// Data length
394    DataLengthCode = 0x0B,
395    /// Data section
396    DataSection = 0x0A,
397    /// CRC sequence
398    CrcSequence = 0x008,
399    /// CRC delimiter
400    CrcDelimiter = 0x18,
401    /// ACK slot
402    AckSlot = 0x19,
403    /// ACK delimiter
404    AckDelimiter = 0x1B,
405    /// End-of-frame
406    EndOfFrame = 0x1A,
407    /// Intermission (between frames)
408    Intermission = 0x12,
409}
410
411impl fmt::Display for Location {
412    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
413        use Location::*;
414        let msg = match *self {
415            Unspecified => "unspecified location",
416            StartOfFrame => "start of frame",
417            Id2821 => "ID, bits 28-21",
418            Id2018 => "ID, bits 20-18",
419            SubstituteRtr => "substitute RTR bit",
420            IdentifierExtension => "ID, extension",
421            Id1713 => "ID, bits 17-13",
422            Id1205 => "ID, bits 12-05",
423            Id0400 => "ID, bits 04-00",
424            Rtr => "RTR bit",
425            Reserved1 => "reserved bit 1",
426            Reserved0 => "reserved bit 0",
427            DataLengthCode => "data length code",
428            DataSection => "data section",
429            CrcSequence => "CRC sequence",
430            CrcDelimiter => "CRC delimiter",
431            AckSlot => "ACK slot",
432            AckDelimiter => "ACK delimiter",
433            EndOfFrame => "end of frame",
434            Intermission => "intermission",
435        };
436        write!(f, "{}", msg)
437    }
438}
439impl TryFrom<u8> for Location {
440    type Error = CanErrorDecodingFailure;
441
442    fn try_from(val: u8) -> std::result::Result<Self, Self::Error> {
443        use Location::*;
444        Ok(match val {
445            0x00 => Unspecified,
446            0x03 => StartOfFrame,
447            0x02 => Id2821,
448            0x06 => Id2018,
449            0x04 => SubstituteRtr,
450            0x05 => IdentifierExtension,
451            0x07 => Id1713,
452            0x0F => Id1205,
453            0x0E => Id0400,
454            0x0C => Rtr,
455            0x0D => Reserved1,
456            0x09 => Reserved0,
457            0x0B => DataLengthCode,
458            0x0A => DataSection,
459            0x08 => CrcSequence,
460            0x18 => CrcDelimiter,
461            0x19 => AckSlot,
462            0x1B => AckDelimiter,
463            0x1A => EndOfFrame,
464            0x12 => Intermission,
465            _ => return Err(CanErrorDecodingFailure::InvalidLocation),
466        })
467    }
468}
469
470// ===== TransceiverError =====
471
472/// The error status of the CAN transceiver.
473///
474/// This is derived from `data[4]` of an error frame.
475#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
476#[repr(u8)]
477pub enum TransceiverError {
478    /// Unsecified
479    Unspecified = 0x00,
480    /// CAN High, no wire
481    CanHighNoWire = 0x04,
482    /// CAN High, short to BAT
483    CanHighShortToBat = 0x05,
484    /// CAN High, short to VCC
485    CanHighShortToVcc = 0x06,
486    /// CAN High, short to GND
487    CanHighShortToGnd = 0x07,
488    /// CAN Low, no wire
489    CanLowNoWire = 0x40,
490    /// CAN Low, short to BAT
491    CanLowShortToBat = 0x50,
492    /// CAN Low, short to VCC
493    CanLowShortToVcc = 0x60,
494    /// CAN Low, short to GND
495    CanLowShortToGnd = 0x70,
496    /// CAN Low short to  CAN High
497    CanLowShortToCanHigh = 0x80,
498}
499
500impl TryFrom<u8> for TransceiverError {
501    type Error = CanErrorDecodingFailure;
502
503    fn try_from(val: u8) -> std::result::Result<Self, Self::Error> {
504        use TransceiverError::*;
505        Ok(match val {
506            0x00 => Unspecified,
507            0x04 => CanHighNoWire,
508            0x05 => CanHighShortToBat,
509            0x06 => CanHighShortToVcc,
510            0x07 => CanHighShortToGnd,
511            0x40 => CanLowNoWire,
512            0x50 => CanLowShortToBat,
513            0x60 => CanLowShortToVcc,
514            0x70 => CanLowShortToGnd,
515            0x80 => CanLowShortToCanHigh,
516            _ => return Err(CanErrorDecodingFailure::InvalidTransceiverError),
517        })
518    }
519}
520
521/// Get the controller specific error information.
522pub trait ControllerSpecificErrorInformation {
523    /// Get the controller specific error information.
524    fn get_ctrl_err(&self) -> Option<&[u8]>;
525}
526
527impl<T: Frame> ControllerSpecificErrorInformation for T {
528    /// Get the controller specific error information.
529    fn get_ctrl_err(&self) -> Option<&[u8]> {
530        let data = self.data();
531
532        if data.len() == 8 {
533            Some(&data[5..])
534        } else {
535            None
536        }
537    }
538}
539
540// ===== CanErrorDecodingFailure =====
541
542/// Error decoding a CanError from a CanErrorFrame.
543#[derive(Debug, Clone, Copy)]
544pub enum CanErrorDecodingFailure {
545    /// The supplied CANFrame did not have the error bit set.
546    NotAnError,
547    /// The error type is not known and cannot be decoded.
548    UnknownErrorType(u32),
549    /// The error type indicated a need for additional information as `data`,
550    /// but the `data` field was not long enough.
551    NotEnoughData(u8),
552    /// The error type `ControllerProblem` was indicated and additional
553    /// information found, but not recognized.
554    InvalidControllerProblem,
555    /// The type of the ProtocolViolation was not valid
556    InvalidViolationType,
557    /// A location was specified for a ProtocolViolation, but the location
558    /// was not valid.
559    InvalidLocation,
560    /// The supplied transceiver error was invalid.
561    InvalidTransceiverError,
562}
563
564impl error::Error for CanErrorDecodingFailure {}
565
566impl fmt::Display for CanErrorDecodingFailure {
567    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
568        use CanErrorDecodingFailure::*;
569        let msg = match *self {
570            NotAnError => "CAN frame is not an error",
571            UnknownErrorType(_) => "unknown error type",
572            NotEnoughData(_) => "not enough data",
573            InvalidControllerProblem => "not a valid controller problem",
574            InvalidViolationType => "not a valid violation type",
575            InvalidLocation => "not a valid location",
576            InvalidTransceiverError => "not a valid transceiver error",
577        };
578        write!(f, "{}", msg)
579    }
580}
581
582// ===== ConstructionError =====
583
584#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
585/// Error that occurs when creating CAN packets
586pub enum ConstructionError {
587    /// Trying to create a specific frame type from an incompatible type
588    WrongFrameType,
589    /// CAN ID was outside the range of valid IDs
590    IDTooLarge,
591    /// Larger payload reported than can be held in the frame.
592    TooMuchData,
593}
594
595impl error::Error for ConstructionError {}
596
597impl fmt::Display for ConstructionError {
598    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
599        use ConstructionError::*;
600        let msg = match *self {
601            WrongFrameType => "Incompatible frame type",
602            IDTooLarge => "CAN ID too large",
603            TooMuchData => "Payload is too large",
604        };
605        write!(f, "{}", msg)
606    }
607}
608
609/////////////////////////////////////////////////////////////////////////////
610
611#[cfg(test)]
612mod tests {
613    use crate::Error;
614    use std::io;
615
616    #[test]
617    fn test_errors() {
618        const KIND: io::ErrorKind = io::ErrorKind::TimedOut;
619
620        // From an IO error.
621        let err = Error::from(io::Error::from(KIND));
622        if let Error::Io(ioerr) = err {
623            assert_eq!(ioerr.kind(), KIND);
624        } else {
625            panic!("Wrong error conversion");
626        }
627
628        // Straight from an ErrorKind
629        let err = Error::from(KIND);
630        if let Error::Io(ioerr) = err {
631            assert_eq!(ioerr.kind(), KIND);
632        } else {
633            panic!("Wrong error conversion");
634        }
635    }
636}