1use super::CanFrame;
5use std::{
6 convert::TryFrom,
7 error,
8 fmt,
9 io,
10};
11
12
13#[inline]
14fn 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#[derive(Copy, Clone, Debug)]
25pub enum CanErrorDecodingFailure {
26 NotAnError,
28
29 UnknownErrorType(u32),
31
32 NotEnoughData(u8),
35
36 InvalidControllerProblem,
39
40 InvalidViolationType,
42
43 InvalidLocation,
46
47 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 TransmitTimeout,
73
74 LostArbitration(u8),
77
78 ControllerProblem(ControllerProblem),
80
81 ProtocolViolation {
84 vtype: ViolationType,
85 location: Location,
86 },
87
88 TransceiverError,
90
91 NoAck,
93
94 BusOff,
96
97 BusError,
99
100 Restarted,
102
103 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,
133
134 ReceiveBufferOverflow,
136
137 TransmitBufferOverflow,
139
140 ReceiveErrorWarning,
142
143 TransmitErrorWarning,
145
146 ReceiveErrorPassive,
148
149 TransmitErrorPassive,
151
152 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,
196
197 SingleBitError,
199
200 FrameFormatError,
202
203 BitStuffingError,
205
206 UnableToSendDominantBit,
208
209 UnableToSendRecessiveBit,
211
212 BusOverload,
214
215 Active,
217
218 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#[derive(Copy, Clone, Debug)]
264pub enum Location {
265 Unspecified,
267
268 StartOfFrame,
270
271 Id2821,
273
274 Id2018,
276
277 SubstituteRtr,
279
280 IdentifierExtension,
282
283 Id1713,
285
286 Id1205,
288
289 Id0400,
291
292 Rtr,
294
295 Reserved1,
297
298 Reserved0,
300
301 DataLengthCode,
303
304 DataSection,
306
307 CrcSequence,
309
310 CrcDelimiter,
312
313 AckSlot,
315
316 AckDelimiter,
318
319 EndOfFrame,
321
322 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)]
464pub enum CanSocketOpenError {
466 LookupError(nix::Error),
468
469 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)]
485pub enum ConstructionError {
487 IDTooLarge,
489 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