use crate::{id::CanId, CanError, ConstructionError};
use embedded_can::{ExtendedId, Frame as EmbeddedFrame, Id, StandardId};
use itertools::Itertools;
use libc::{can_frame, canfd_frame, canid_t};
use std::{
ffi::c_void,
mem::size_of,
{convert::TryFrom, fmt, matches, mem},
};
pub use crate::id::{
id_from_raw, id_is_extended, id_to_canid_t, FdFlags, IdFlags, CANFD_BRS, CANFD_ESI, CANFD_FDF,
CANFD_MAX_DLEN, CAN_EFF_FLAG, CAN_EFF_MASK, CAN_ERR_FLAG, CAN_ERR_MASK, CAN_MAX_DLEN,
CAN_RTR_FLAG, CAN_SFF_MASK, ERR_MASK_ALL, ERR_MASK_NONE,
};
#[inline(always)]
pub fn can_frame_default() -> can_frame {
unsafe { mem::zeroed() }
}
#[inline(always)]
pub fn canfd_frame_default() -> canfd_frame {
unsafe { mem::zeroed() }
}
pub trait AsPtr {
type Inner;
fn as_ptr(&self) -> *const Self::Inner;
fn as_mut_ptr(&mut self) -> *mut Self::Inner;
fn size(&self) -> usize {
size_of::<Self::Inner>()
}
fn as_bytes(&self) -> &[u8] {
unsafe {
std::slice::from_raw_parts::<'_, u8>(
self.as_ptr() as *const _ as *const u8,
self.size(),
)
}
}
fn as_bytes_mut(&mut self) -> &[u8] {
unsafe {
std::slice::from_raw_parts::<'_, u8>(
self.as_mut_ptr() as *mut _ as *mut u8,
self.size(),
)
}
}
}
#[allow(clippy::len_without_is_empty)]
pub trait Frame: EmbeddedFrame {
fn from_raw_id(id: u32, data: &[u8]) -> Option<Self> {
Self::new(id_from_raw(id)?, data)
}
fn remote_from_raw_id(id: u32, dlc: usize) -> Option<Self> {
Self::new_remote(id_from_raw(id)?, dlc)
}
fn id_word(&self) -> canid_t;
fn raw_id(&self) -> canid_t {
let mask = if self.is_extended() {
CAN_EFF_MASK
} else {
CAN_SFF_MASK
};
self.id_word() & mask
}
fn id_flags(&self) -> IdFlags {
IdFlags::from_bits_truncate(self.id_word())
}
fn can_id(&self) -> CanId {
if self.is_extended() {
ExtendedId::new(self.id_word() & CAN_EFF_MASK)
.unwrap()
.into()
} else {
StandardId::new((self.id_word() & CAN_SFF_MASK) as u16)
.unwrap()
.into()
}
}
fn hal_id(&self) -> Id {
self.can_id().as_id()
}
fn len(&self) -> usize {
self.dlc()
}
fn is_error_frame(&self) -> bool {
self.id_flags().contains(IdFlags::ERR)
}
fn set_id(&mut self, id: impl Into<Id>);
fn set_data(&mut self, data: &[u8]) -> Result<(), ConstructionError>;
}
#[allow(missing_debug_implementations)]
#[derive(Clone, Copy)]
pub enum CanRawFrame {
Classic(can_frame),
Fd(canfd_frame),
}
impl From<can_frame> for CanRawFrame {
fn from(frame: can_frame) -> Self {
Self::Classic(frame)
}
}
impl From<canfd_frame> for CanRawFrame {
fn from(frame: canfd_frame) -> Self {
Self::Fd(frame)
}
}
#[derive(Clone, Copy, Debug)]
pub enum CanAnyFrame {
Normal(CanDataFrame),
Remote(CanRemoteFrame),
Error(CanErrorFrame),
Fd(CanFdFrame),
}
impl Frame for CanAnyFrame {
fn id_word(&self) -> canid_t {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.id_word(),
Remote(frame) => frame.id_word(),
Error(frame) => frame.id_word(),
Fd(frame) => frame.id_word(),
}
}
fn set_id(&mut self, id: impl Into<Id>) {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.set_id(id),
Remote(frame) => frame.set_id(id),
Error(frame) => frame.set_id(id),
Fd(frame) => frame.set_id(id),
}
}
fn set_data(&mut self, data: &[u8]) -> Result<(), ConstructionError> {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.set_data(data),
Remote(frame) => frame.set_data(data),
Error(frame) => frame.set_data(data),
Fd(frame) => frame.set_data(data),
}
}
}
impl EmbeddedFrame for CanAnyFrame {
fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
if data.len() <= CAN_MAX_DLEN {
CanDataFrame::new(id, data).map(CanAnyFrame::Normal)
} else {
CanFdFrame::new(id, data).map(CanAnyFrame::Fd)
}
}
fn new_remote(id: impl Into<Id>, dlc: usize) -> Option<Self> {
CanRemoteFrame::new_remote(id, dlc).map(CanAnyFrame::Remote)
}
fn is_extended(&self) -> bool {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.is_extended(),
Remote(frame) => frame.is_extended(),
Error(frame) => frame.is_extended(),
Fd(frame) => frame.is_extended(),
}
}
fn is_remote_frame(&self) -> bool {
matches!(self, CanAnyFrame::Remote(_))
}
fn id(&self) -> Id {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.id(),
Remote(frame) => frame.id(),
Error(frame) => frame.id(),
Fd(frame) => frame.id(),
}
}
fn dlc(&self) -> usize {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.dlc(),
Remote(frame) => frame.dlc(),
Error(frame) => frame.dlc(),
Fd(frame) => frame.dlc(),
}
}
fn data(&self) -> &[u8] {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.data(),
Remote(frame) => frame.data(),
Error(frame) => frame.data(),
Fd(frame) => frame.data(),
}
}
}
impl fmt::UpperHex for CanAnyFrame {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.fmt(f),
Remote(frame) => frame.fmt(f),
Error(frame) => frame.fmt(f),
Fd(frame) => frame.fmt(f),
}
}
}
impl From<CanFrame> for CanAnyFrame {
fn from(frame: CanFrame) -> Self {
use CanFrame::*;
match frame {
Data(frame) => Self::Normal(frame),
Remote(frame) => Self::Remote(frame),
Error(frame) => Self::Error(frame),
}
}
}
impl From<CanDataFrame> for CanAnyFrame {
fn from(frame: CanDataFrame) -> Self {
Self::Normal(frame)
}
}
impl From<CanRemoteFrame> for CanAnyFrame {
fn from(frame: CanRemoteFrame) -> Self {
Self::Remote(frame)
}
}
impl From<CanErrorFrame> for CanAnyFrame {
fn from(frame: CanErrorFrame) -> Self {
Self::Error(frame)
}
}
impl From<CanFdFrame> for CanAnyFrame {
fn from(frame: CanFdFrame) -> Self {
Self::Fd(frame)
}
}
impl From<can_frame> for CanAnyFrame {
fn from(frame: can_frame) -> Self {
let frame = CanFrame::from(frame);
frame.into()
}
}
impl From<canfd_frame> for CanAnyFrame {
fn from(frame: canfd_frame) -> Self {
let frame = CanFdFrame::from(frame);
frame.into()
}
}
impl From<CanRawFrame> for CanAnyFrame {
fn from(frame: CanRawFrame) -> Self {
use CanRawFrame::*;
match frame {
Classic(frame) => frame.into(),
Fd(frame) => frame.into(),
}
}
}
impl AsPtr for CanAnyFrame {
type Inner = c_void;
fn as_ptr(&self) -> *const Self::Inner {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.as_ptr() as *const Self::Inner,
Remote(frame) => frame.as_ptr() as *const Self::Inner,
Error(frame) => frame.as_ptr() as *const Self::Inner,
Fd(frame) => frame.as_ptr() as *const Self::Inner,
}
}
fn as_mut_ptr(&mut self) -> *mut Self::Inner {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.as_mut_ptr() as *mut Self::Inner,
Remote(frame) => frame.as_mut_ptr() as *mut Self::Inner,
Error(frame) => frame.as_mut_ptr() as *mut Self::Inner,
Fd(frame) => frame.as_mut_ptr() as *mut Self::Inner,
}
}
fn size(&self) -> usize {
use CanAnyFrame::*;
match self {
Normal(frame) => frame.size(),
Remote(frame) => frame.size(),
Error(frame) => frame.size(),
Fd(frame) => frame.size(),
}
}
}
impl TryFrom<CanAnyFrame> for CanDataFrame {
type Error = ConstructionError;
fn try_from(frame: CanAnyFrame) -> Result<Self, Self::Error> {
match frame {
CanAnyFrame::Normal(f) => Ok(f),
_ => Err(ConstructionError::WrongFrameType),
}
}
}
impl TryFrom<CanAnyFrame> for CanRemoteFrame {
type Error = ConstructionError;
fn try_from(frame: CanAnyFrame) -> Result<Self, Self::Error> {
match frame {
CanAnyFrame::Remote(f) => Ok(f),
_ => Err(ConstructionError::WrongFrameType),
}
}
}
impl TryFrom<CanAnyFrame> for CanErrorFrame {
type Error = ConstructionError;
fn try_from(frame: CanAnyFrame) -> Result<Self, Self::Error> {
match frame {
CanAnyFrame::Error(f) => Ok(f),
_ => Err(ConstructionError::WrongFrameType),
}
}
}
impl TryFrom<CanAnyFrame> for CanFdFrame {
type Error = ConstructionError;
fn try_from(frame: CanAnyFrame) -> Result<Self, Self::Error> {
match frame {
CanAnyFrame::Fd(f) => Ok(f),
_ => Err(ConstructionError::WrongFrameType),
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum CanFrame {
Data(CanDataFrame),
Remote(CanRemoteFrame),
Error(CanErrorFrame),
}
impl AsPtr for CanFrame {
type Inner = can_frame;
fn as_ptr(&self) -> *const Self::Inner {
use CanFrame::*;
match self {
Data(frame) => frame.as_ptr(),
Remote(frame) => frame.as_ptr(),
Error(frame) => frame.as_ptr(),
}
}
fn as_mut_ptr(&mut self) -> *mut Self::Inner {
use CanFrame::*;
match self {
Data(frame) => frame.as_mut_ptr(),
Remote(frame) => frame.as_mut_ptr(),
Error(frame) => frame.as_mut_ptr(),
}
}
}
impl EmbeddedFrame for CanFrame {
fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
CanDataFrame::new(id, data).map(CanFrame::Data)
}
fn new_remote(id: impl Into<Id>, dlc: usize) -> Option<Self> {
CanRemoteFrame::new_remote(id, dlc).map(CanFrame::Remote)
}
fn is_extended(&self) -> bool {
use CanFrame::*;
match self {
Data(frame) => frame.is_extended(),
Remote(frame) => frame.is_extended(),
Error(frame) => frame.is_extended(),
}
}
fn is_remote_frame(&self) -> bool {
matches!(self, CanFrame::Remote(_))
}
fn id(&self) -> Id {
use CanFrame::*;
match self {
Data(frame) => frame.id(),
Remote(frame) => frame.id(),
Error(frame) => frame.id(),
}
}
fn dlc(&self) -> usize {
use CanFrame::*;
match self {
Data(frame) => frame.dlc(),
Remote(frame) => frame.dlc(),
Error(frame) => frame.dlc(),
}
}
fn data(&self) -> &[u8] {
use CanFrame::*;
match self {
Data(frame) => frame.data(),
Remote(frame) => frame.data(),
Error(frame) => frame.data(),
}
}
}
impl Frame for CanFrame {
fn id_word(&self) -> canid_t {
use CanFrame::*;
match self {
Data(frame) => frame.id_word(),
Remote(frame) => frame.id_word(),
Error(frame) => frame.id_word(),
}
}
fn set_id(&mut self, id: impl Into<Id>) {
use CanFrame::*;
match self {
Data(frame) => frame.set_id(id),
Remote(frame) => frame.set_id(id),
Error(frame) => frame.set_id(id),
}
}
fn set_data(&mut self, data: &[u8]) -> Result<(), ConstructionError> {
use CanFrame::*;
match self {
Data(frame) => frame.set_data(data),
Remote(frame) => frame.set_data(data),
Error(frame) => frame.set_data(data),
}
}
}
impl Default for CanFrame {
fn default() -> Self {
CanFrame::Data(CanDataFrame::default())
}
}
impl fmt::UpperHex for CanFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use CanFrame::*;
match self {
Data(frame) => fmt::UpperHex::fmt(&frame, f),
Remote(frame) => fmt::UpperHex::fmt(&frame, f),
Error(frame) => fmt::UpperHex::fmt(&frame, f),
}
}
}
impl From<can_frame> for CanFrame {
fn from(frame: can_frame) -> Self {
if frame.can_id & CAN_ERR_FLAG != 0 {
CanFrame::Error(CanErrorFrame(frame))
} else if frame.can_id & CAN_RTR_FLAG != 0 {
CanFrame::Remote(CanRemoteFrame(frame))
} else {
CanFrame::Data(CanDataFrame(frame))
}
}
}
impl From<CanDataFrame> for CanFrame {
fn from(frame: CanDataFrame) -> Self {
Self::Data(frame)
}
}
impl From<CanRemoteFrame> for CanFrame {
fn from(frame: CanRemoteFrame) -> Self {
Self::Remote(frame)
}
}
impl From<CanErrorFrame> for CanFrame {
fn from(frame: CanErrorFrame) -> Self {
Self::Error(frame)
}
}
impl AsRef<can_frame> for CanFrame {
fn as_ref(&self) -> &can_frame {
use CanFrame::*;
match self {
Data(frame) => frame.as_ref(),
Remote(frame) => frame.as_ref(),
Error(frame) => frame.as_ref(),
}
}
}
impl TryFrom<CanFrame> for CanDataFrame {
type Error = ConstructionError;
fn try_from(frame: CanFrame) -> Result<Self, Self::Error> {
match frame {
CanFrame::Data(f) => Ok(f),
_ => Err(ConstructionError::WrongFrameType),
}
}
}
impl TryFrom<CanFrame> for CanRemoteFrame {
type Error = ConstructionError;
fn try_from(frame: CanFrame) -> Result<Self, Self::Error> {
match frame {
CanFrame::Remote(f) => Ok(f),
_ => Err(ConstructionError::WrongFrameType),
}
}
}
impl TryFrom<CanFrame> for CanErrorFrame {
type Error = ConstructionError;
fn try_from(frame: CanFrame) -> Result<Self, Self::Error> {
match frame {
CanFrame::Error(f) => Ok(f),
_ => Err(ConstructionError::WrongFrameType),
}
}
}
impl TryFrom<CanFdFrame> for CanFrame {
type Error = ConstructionError;
fn try_from(frame: CanFdFrame) -> Result<Self, <Self as TryFrom<CanFdFrame>>::Error> {
CanDataFrame::try_from(frame).map(CanFrame::Data)
}
}
#[derive(Clone, Copy)]
pub struct CanDataFrame(can_frame);
impl CanDataFrame {
pub(crate) fn init(can_id: canid_t, data: &[u8]) -> Result<Self, ConstructionError> {
match data.len() {
n if n <= CAN_MAX_DLEN => {
let mut frame = can_frame_default();
frame.can_id = can_id;
frame.can_dlc = n as u8;
frame.data[..n].copy_from_slice(data);
Ok(Self(frame))
}
_ => Err(ConstructionError::TooMuchData),
}
}
}
impl AsPtr for CanDataFrame {
type Inner = can_frame;
fn as_ptr(&self) -> *const Self::Inner {
&self.0
}
fn as_mut_ptr(&mut self) -> *mut Self::Inner {
&mut self.0
}
}
impl EmbeddedFrame for CanDataFrame {
fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
let can_id = id_to_canid_t(id);
Self::init(can_id, data).ok()
}
fn new_remote(_id: impl Into<Id>, _dlc: usize) -> Option<Self> {
None
}
fn is_extended(&self) -> bool {
self.id_flags().contains(IdFlags::EFF)
}
fn is_remote_frame(&self) -> bool {
false
}
fn id(&self) -> Id {
self.hal_id()
}
fn dlc(&self) -> usize {
self.0.can_dlc as usize
}
fn data(&self) -> &[u8] {
&self.0.data[..(self.0.can_dlc as usize)]
}
}
impl Frame for CanDataFrame {
fn id_word(&self) -> canid_t {
self.0.can_id
}
fn set_id(&mut self, id: impl Into<Id>) {
self.0.can_id = id_to_canid_t(id);
}
fn set_data(&mut self, data: &[u8]) -> Result<(), ConstructionError> {
match data.len() {
n if n <= CAN_MAX_DLEN => {
self.0.can_dlc = n as u8;
self.0.data[..n].copy_from_slice(data);
Ok(())
}
_ => Err(ConstructionError::TooMuchData),
}
}
}
impl Default for CanDataFrame {
fn default() -> Self {
Self(can_frame_default())
}
}
impl fmt::Debug for CanDataFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CanDataFrame {{ ")?;
fmt::UpperHex::fmt(self, f)?;
write!(f, " }}")
}
}
impl fmt::UpperHex for CanDataFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{:X}#", self.0.can_id)?;
let mut parts = self.data().iter().map(|v| format!("{:02X}", v));
write!(f, "{}", parts.join(" "))
}
}
impl TryFrom<can_frame> for CanDataFrame {
type Error = ConstructionError;
fn try_from(frame: can_frame) -> Result<Self, Self::Error> {
if frame.can_id & (CAN_ERR_FLAG | CAN_RTR_FLAG) == 0 {
Ok(Self(frame))
} else {
Err(ConstructionError::WrongFrameType)
}
}
}
impl TryFrom<CanFdFrame> for CanDataFrame {
type Error = ConstructionError;
fn try_from(frame: CanFdFrame) -> Result<Self, Self::Error> {
match frame.len() {
n if n > CAN_MAX_DLEN => Err(ConstructionError::TooMuchData),
n => CanDataFrame::init(frame.id_word(), &frame.data()[..n]),
}
}
}
impl AsRef<can_frame> for CanDataFrame {
fn as_ref(&self) -> &can_frame {
&self.0
}
}
#[derive(Clone, Copy)]
pub struct CanRemoteFrame(can_frame);
impl CanRemoteFrame {
pub(crate) fn init(can_id: canid_t, len: usize) -> Result<Self, ConstructionError> {
match len {
n if n <= CAN_MAX_DLEN => {
let mut frame = can_frame_default();
frame.can_id = can_id | CAN_RTR_FLAG;
frame.can_dlc = n as u8;
Ok(Self(frame))
}
_ => Err(ConstructionError::TooMuchData),
}
}
pub fn set_dlc(&mut self, dlc: usize) -> Result<(), ConstructionError> {
if dlc <= CAN_MAX_DLEN {
self.0.can_dlc = dlc as u8;
Ok(())
} else {
Err(ConstructionError::TooMuchData)
}
}
}
impl AsPtr for CanRemoteFrame {
type Inner = can_frame;
fn as_ptr(&self) -> *const Self::Inner {
&self.0
}
fn as_mut_ptr(&mut self) -> *mut Self::Inner {
&mut self.0
}
}
impl EmbeddedFrame for CanRemoteFrame {
fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
Self::new_remote(id, data.len())
}
fn new_remote(id: impl Into<Id>, dlc: usize) -> Option<Self> {
let can_id = id_to_canid_t(id);
Self::init(can_id, dlc).ok()
}
fn is_extended(&self) -> bool {
self.id_flags().contains(IdFlags::EFF)
}
fn is_remote_frame(&self) -> bool {
true
}
fn id(&self) -> Id {
self.hal_id()
}
fn dlc(&self) -> usize {
self.0.can_dlc as usize
}
fn data(&self) -> &[u8] {
&self.0.data[..self.dlc()]
}
}
impl Frame for CanRemoteFrame {
fn id_word(&self) -> canid_t {
self.0.can_id
}
fn set_id(&mut self, id: impl Into<Id>) {
self.0.can_id = id_to_canid_t(id) | CAN_RTR_FLAG;
}
fn set_data(&mut self, data: &[u8]) -> Result<(), ConstructionError> {
self.set_dlc(data.len())
}
}
impl Default for CanRemoteFrame {
fn default() -> Self {
let mut frame = can_frame_default();
frame.can_id |= CAN_RTR_FLAG;
Self(frame)
}
}
impl fmt::Debug for CanRemoteFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CanRemoteFrame {{ ")?;
fmt::UpperHex::fmt(self, f)?;
write!(f, " }}")
}
}
impl fmt::UpperHex for CanRemoteFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{:X}#", self.0.can_id)?;
let mut parts = self.data().iter().map(|v| format!("{:02X}", v));
write!(f, "{}", parts.join(" "))
}
}
impl TryFrom<can_frame> for CanRemoteFrame {
type Error = ConstructionError;
fn try_from(frame: can_frame) -> Result<Self, Self::Error> {
if frame.can_id & CAN_RTR_FLAG != 0 {
Ok(Self(frame))
} else {
Err(ConstructionError::WrongFrameType)
}
}
}
impl AsRef<can_frame> for CanRemoteFrame {
fn as_ref(&self) -> &can_frame {
&self.0
}
}
#[derive(Clone, Copy)]
pub struct CanErrorFrame(can_frame);
impl CanErrorFrame {
pub fn new_error(can_id: canid_t, data: &[u8]) -> Result<Self, ConstructionError> {
match data.len() {
n if n <= CAN_MAX_DLEN => {
let mut frame = can_frame_default();
frame.can_id = (can_id & CAN_ERR_MASK) | CAN_ERR_FLAG;
frame.can_dlc = CAN_MAX_DLEN as u8;
frame.data[..n].copy_from_slice(data);
Ok(Self(frame))
}
_ => Err(ConstructionError::TooMuchData),
}
}
pub fn error_bits(&self) -> u32 {
self.id_word() & CAN_ERR_MASK
}
pub fn into_error(self) -> CanError {
CanError::from(self)
}
}
impl AsPtr for CanErrorFrame {
type Inner = can_frame;
fn as_ptr(&self) -> *const Self::Inner {
&self.0
}
fn as_mut_ptr(&mut self) -> *mut Self::Inner {
&mut self.0
}
}
impl EmbeddedFrame for CanErrorFrame {
fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
let can_id = id_to_canid_t(id);
Self::new_error(can_id, data).ok()
}
fn new_remote(_id: impl Into<Id>, _dlc: usize) -> Option<Self> {
None
}
fn is_extended(&self) -> bool {
self.id_flags().contains(IdFlags::EFF)
}
fn is_remote_frame(&self) -> bool {
false
}
fn is_data_frame(&self) -> bool {
false
}
fn id(&self) -> Id {
self.hal_id()
}
fn dlc(&self) -> usize {
self.0.can_dlc as usize
}
fn data(&self) -> &[u8] {
&self.0.data[..]
}
}
impl Frame for CanErrorFrame {
fn id_word(&self) -> canid_t {
self.0.can_id
}
fn set_id(&mut self, _id: impl Into<Id>) {}
fn set_data(&mut self, _data: &[u8]) -> Result<(), ConstructionError> {
Err(ConstructionError::WrongFrameType)
}
}
impl fmt::Debug for CanErrorFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CanErrorFrame {{ ")?;
fmt::UpperHex::fmt(self, f)?;
write!(f, " }}")
}
}
impl fmt::UpperHex for CanErrorFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{:X}#", self.0.can_id)?;
let mut parts = self.data().iter().map(|v| format!("{:02X}", v));
write!(f, "{}", parts.join(" "))
}
}
impl TryFrom<can_frame> for CanErrorFrame {
type Error = ConstructionError;
fn try_from(frame: can_frame) -> Result<Self, Self::Error> {
if frame.can_id & CAN_ERR_FLAG != 0 {
Ok(Self(frame))
} else {
Err(ConstructionError::WrongFrameType)
}
}
}
impl From<CanError> for CanErrorFrame {
fn from(err: CanError) -> Self {
use CanError::*;
let mut data = [0u8; CAN_MAX_DLEN];
let id: canid_t = match err {
TransmitTimeout => 0x0001,
LostArbitration(bit) => {
data[0] = bit;
0x0002
}
ControllerProblem(prob) => {
data[1] = prob as u8;
0x0004
}
ProtocolViolation { vtype, location } => {
data[2] = vtype as u8;
data[3] = location as u8;
0x0008
}
TransceiverError => 0x0010,
NoAck => 0x0020,
BusOff => 0x0040,
BusError => 0x0080,
Restarted => 0x0100,
DecodingFailure(_failure) => 0,
Unknown(e) => e,
};
Self::new_error(id, &data).unwrap()
}
}
impl AsRef<can_frame> for CanErrorFrame {
fn as_ref(&self) -> &can_frame {
&self.0
}
}
const VALID_EXT_DLENGTHS: [usize; 7] = [12, 16, 20, 24, 32, 48, 64];
#[derive(Clone, Copy)]
pub struct CanFdFrame(canfd_frame);
impl CanFdFrame {
pub fn with_flags(id: impl Into<Id>, data: &[u8], flags: FdFlags) -> Option<Self> {
let can_id = id_to_canid_t(id);
Self::init(can_id, data, flags).ok()
}
pub(crate) fn init(
can_id: u32,
data: &[u8],
fd_flags: FdFlags,
) -> Result<Self, ConstructionError> {
match data.len() {
n if n <= CANFD_MAX_DLEN => {
let mut frame = canfd_frame_default();
frame.can_id = can_id;
frame.flags = (fd_flags | FdFlags::FDF).bits();
frame.data[..n].copy_from_slice(data);
frame.len = Self::next_valid_ext_dlen(n) as u8;
Ok(Self(frame))
}
_ => Err(ConstructionError::TooMuchData),
}
}
pub fn flags(&self) -> FdFlags {
FdFlags::from_bits_truncate(self.0.flags)
}
pub fn is_brs(&self) -> bool {
self.flags().contains(FdFlags::BRS)
}
pub fn set_brs(&mut self, on: bool) {
if on {
self.0.flags |= CANFD_BRS as u8;
} else {
self.0.flags &= !(CANFD_BRS as u8);
}
}
pub fn is_esi(&self) -> bool {
self.flags().contains(FdFlags::ESI)
}
pub fn set_esi(&mut self, on: bool) {
if on {
self.0.flags |= CANFD_ESI as u8;
} else {
self.0.flags &= !CANFD_ESI as u8;
}
}
pub fn is_valid_data_len(len: usize) -> bool {
len <= CAN_MAX_DLEN || VALID_EXT_DLENGTHS.contains(&len)
}
pub fn next_valid_ext_dlen(len: usize) -> usize {
if len <= CAN_MAX_DLEN {
return len;
}
for valid_ext_len in VALID_EXT_DLENGTHS {
if valid_ext_len >= len {
return valid_ext_len;
}
}
CANFD_MAX_DLEN
}
}
impl AsPtr for CanFdFrame {
type Inner = canfd_frame;
fn as_ptr(&self) -> *const Self::Inner {
&self.0
}
fn as_mut_ptr(&mut self) -> *mut Self::Inner {
&mut self.0
}
}
impl EmbeddedFrame for CanFdFrame {
fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
let can_id = id_to_canid_t(id);
Self::init(can_id, data, FdFlags::empty()).ok()
}
fn new_remote(_id: impl Into<Id>, _dlc: usize) -> Option<Self> {
None
}
fn is_extended(&self) -> bool {
self.id_flags().contains(IdFlags::EFF)
}
fn is_remote_frame(&self) -> bool {
false
}
fn id(&self) -> Id {
self.hal_id()
}
fn dlc(&self) -> usize {
match self.0.len {
0..=8 => self.0.len as usize,
12 => 0x09,
16 => 0x0A,
20 => 0x0B,
24 => 0x0C,
32 => 0x0D,
48 => 0x0E,
64 => 0x0F,
_ => 0x00,
}
}
fn data(&self) -> &[u8] {
&self.0.data[..(self.0.len as usize)]
}
}
impl Frame for CanFdFrame {
fn id_word(&self) -> canid_t {
self.0.can_id
}
fn len(&self) -> usize {
self.0.len as usize
}
fn set_id(&mut self, id: impl Into<Id>) {
self.0.can_id = id_to_canid_t(id);
}
fn set_data(&mut self, data: &[u8]) -> Result<(), ConstructionError> {
match data.len() {
n if n <= CANFD_MAX_DLEN => {
self.0.data[..n].copy_from_slice(data);
self.0.data[n..].fill(0);
self.0.len = Self::next_valid_ext_dlen(n) as u8;
Ok(())
}
_ => Err(ConstructionError::TooMuchData),
}
}
}
impl Default for CanFdFrame {
fn default() -> Self {
let mut frame = canfd_frame_default();
frame.flags |= CANFD_FDF as u8;
Self(frame)
}
}
impl fmt::Debug for CanFdFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CanFdFrame {{ ")?;
fmt::UpperHex::fmt(self, f)?;
write!(f, " }}")
}
}
impl fmt::UpperHex for CanFdFrame {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{:X}##", self.0.can_id)?;
write!(f, "{} ", self.0.flags)?;
let mut parts = self.data().iter().map(|v| format!("{:02X}", v));
write!(f, "{}", parts.join(" "))
}
}
impl From<CanDataFrame> for CanFdFrame {
fn from(frame: CanDataFrame) -> Self {
let n = frame.len();
let mut fdframe = canfd_frame_default();
fdframe.can_id = frame.id_word();
fdframe.flags = CANFD_FDF as u8;
fdframe.len = n as u8;
fdframe.data[..n].copy_from_slice(&frame.data()[..n]);
Self(fdframe)
}
}
impl From<canfd_frame> for CanFdFrame {
fn from(mut frame: canfd_frame) -> Self {
frame.flags |= CANFD_FDF as u8;
Self(frame)
}
}
impl AsRef<canfd_frame> for CanFdFrame {
fn as_ref(&self) -> &canfd_frame {
&self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::errors;
const STD_ID: Id = Id::Standard(StandardId::MAX);
const EXT_ID: Id = Id::Extended(ExtendedId::MAX);
const EXT_LOW_ID: Id = Id::Extended(unsafe { ExtendedId::new_unchecked(0x7FF) });
const DATA: &[u8] = &[0, 1, 2, 3];
const DATA_LEN: usize = DATA.len();
const EXT_DATA: &[u8] = &[0xAB; 32];
const EXT_DATA_DLC: usize = 0x0D;
const EXT_DATA_INVALID_DLEN: &[u8] =
&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA];
const EXT_DATA_PADDED: &[u8] = &[
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0x00, 0x00,
];
const EXT_DATA_PADDED_DLC: usize = 0x09;
const EMPTY_DATA: &[u8] = &[];
const ZERO_DATA: &[u8] = &[0u8; DATA_LEN];
fn id_to_raw(id: Id) -> u32 {
match id {
Id::Standard(id) => id.as_raw() as u32,
Id::Extended(id) => id.as_raw(),
}
}
#[test]
fn test_bit_flags() {
let mut flags = IdFlags::RTR;
assert_eq!(CAN_RTR_FLAG, flags.bits());
flags.set(IdFlags::EFF, true);
assert_eq!(CAN_RTR_FLAG, flags.bits() & CAN_RTR_FLAG);
assert_eq!(CAN_EFF_FLAG, flags.bits() & CAN_EFF_FLAG);
flags.set(IdFlags::EFF, false);
assert_eq!(CAN_RTR_FLAG, flags.bits() & CAN_RTR_FLAG);
assert_eq!(0, flags.bits() & CAN_EFF_FLAG);
}
#[test]
fn test_defaults() {
let frame = CanFrame::default();
assert_eq!(0, frame.id_word());
assert_eq!(0, frame.raw_id());
assert!(frame.id_flags().is_empty());
assert_eq!(0, frame.dlc());
assert_eq!(0, frame.len());
assert_eq!(EMPTY_DATA, frame.data());
}
#[test]
fn test_data_frame() {
let frame = CanDataFrame::new(STD_ID, DATA).unwrap();
assert_eq!(STD_ID, frame.id());
assert_eq!(id_to_raw(STD_ID), frame.raw_id());
assert!(frame.is_standard());
assert!(!frame.is_extended());
assert!(frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(frame.data(), DATA);
assert_eq!(frame.len(), DATA.len());
assert_eq!(frame.data().len(), DATA.len());
assert_eq!(frame.dlc(), DATA.len());
let frame = CanFrame::from(frame);
assert_eq!(STD_ID, frame.id());
assert_eq!(id_to_raw(STD_ID), frame.raw_id());
assert!(frame.is_standard());
assert!(!frame.is_extended());
assert!(frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(frame.data(), DATA);
assert_eq!(frame.len(), DATA.len());
assert_eq!(frame.data().len(), DATA.len());
assert_eq!(frame.dlc(), DATA.len());
let frame = CanDataFrame::from_raw_id(StandardId::MAX.as_raw() as u32, DATA).unwrap();
assert_eq!(STD_ID, frame.id());
assert_eq!(id_to_raw(STD_ID), frame.raw_id());
assert!(frame.is_standard());
assert!(!frame.is_extended());
assert!(frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(frame.data(), DATA);
assert_eq!(frame.len(), DATA.len());
assert_eq!(frame.data().len(), DATA.len());
assert_eq!(frame.dlc(), DATA.len());
let frame = CanFrame::new(EXT_ID, DATA).unwrap();
assert_eq!(EXT_ID, frame.id());
assert_eq!(id_to_raw(EXT_ID), frame.raw_id());
assert!(!frame.is_standard());
assert!(frame.is_extended());
assert!(frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(frame.data(), DATA);
assert_eq!(frame.len(), DATA.len());
assert_eq!(frame.data().len(), DATA.len());
assert_eq!(frame.dlc(), DATA.len());
let frame = CanFrame::from_raw_id(ExtendedId::MAX.as_raw(), DATA).unwrap();
assert_eq!(EXT_ID, frame.id());
assert_eq!(id_to_raw(EXT_ID), frame.raw_id());
assert!(!frame.is_standard());
assert!(frame.is_extended());
assert!(frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(frame.data(), DATA);
assert_eq!(frame.len(), DATA.len());
assert_eq!(frame.data().len(), DATA.len());
assert_eq!(frame.dlc(), DATA.len());
let frame = CanFrame::new(EXT_LOW_ID, DATA).unwrap();
assert_eq!(EXT_LOW_ID, frame.id());
assert!(!frame.is_standard());
assert!(frame.is_extended());
}
#[test]
fn test_remote_frame() {
let frame = CanRemoteFrame::default();
assert_eq!(CAN_RTR_FLAG, frame.id_word());
assert!(frame.is_remote_frame());
assert_eq!(0, frame.dlc());
assert_eq!(0, frame.len());
assert_eq!(EMPTY_DATA, frame.data());
assert!(frame.id_flags().contains(IdFlags::RTR));
assert_eq!(CAN_RTR_FLAG, frame.id_word() & CAN_RTR_FLAG);
let frame = CanRemoteFrame::new_remote(STD_ID, DATA_LEN).unwrap();
assert_eq!(STD_ID, frame.id());
assert_eq!(id_to_raw(STD_ID), frame.raw_id());
assert!(frame.is_standard());
assert!(!frame.is_extended());
assert!(!frame.is_data_frame());
assert!(frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(DATA_LEN, frame.dlc());
assert_eq!(DATA_LEN, frame.len());
assert_eq!(ZERO_DATA, frame.data());
assert!(frame.id_flags().contains(IdFlags::RTR));
assert_eq!(CAN_RTR_FLAG, frame.id_word() & CAN_RTR_FLAG);
let frame = CanFrame::from(frame);
assert_eq!(STD_ID, frame.id());
assert_eq!(id_to_raw(STD_ID), frame.raw_id());
assert!(frame.is_standard());
assert!(!frame.is_extended());
assert!(!frame.is_data_frame());
assert!(frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(ZERO_DATA, frame.data());
assert!(matches!(frame, CanFrame::Remote(_)));
assert!(frame.id_flags().contains(IdFlags::RTR));
assert_eq!(CAN_RTR_FLAG, frame.id_word() & CAN_RTR_FLAG);
let frame = CanFrame::new_remote(STD_ID, DATA_LEN).unwrap();
assert_eq!(STD_ID, frame.id());
assert_eq!(id_to_raw(STD_ID), frame.raw_id());
assert!(frame.is_standard());
assert!(!frame.is_extended());
assert!(!frame.is_data_frame());
assert!(frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(ZERO_DATA, frame.data());
assert!(matches!(frame, CanFrame::Remote(_)));
assert!(frame.id_flags().contains(IdFlags::RTR));
assert_eq!(CAN_RTR_FLAG, frame.id_word() & CAN_RTR_FLAG);
let frame = CanRemoteFrame::new_remote(STD_ID, CAN_MAX_DLEN + 1);
assert!(frame.is_none());
}
#[test]
fn test_error_frame() {
let mut frame = can_frame_default();
frame.can_id = CAN_ERR_FLAG | 0x0010;
let err = CanError::from(CanErrorFrame(frame));
assert!(matches!(err, CanError::TransceiverError));
let id = StandardId::new(0x0010).unwrap();
let frame = CanErrorFrame::new(id, &[]).unwrap();
assert!(!frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(frame.is_error_frame());
let err = CanError::from(frame);
assert!(matches!(err, CanError::TransceiverError));
let id = ExtendedId::new(0x0020).unwrap();
let frame = CanErrorFrame::new(id, &[]).unwrap();
assert!(!frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(frame.is_error_frame());
let err = CanError::from(frame);
assert!(matches!(err, CanError::NoAck));
let frame = CanErrorFrame::from(CanError::TransmitTimeout);
assert!(!frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(frame.is_error_frame());
let err = frame.into_error();
assert!(matches!(err, CanError::TransmitTimeout));
let err = CanError::ProtocolViolation {
vtype: errors::ViolationType::BitStuffingError,
location: errors::Location::Id0400,
};
let frame = CanErrorFrame::from(err);
assert!(!frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(frame.is_error_frame());
match frame.into_error() {
CanError::ProtocolViolation { vtype, location } => {
assert_eq!(vtype, errors::ViolationType::BitStuffingError);
assert_eq!(location, errors::Location::Id0400);
}
_ => assert!(false),
}
}
#[test]
fn test_fd_frame() {
let frame = CanFdFrame::new(STD_ID, DATA).unwrap();
assert_eq!(STD_ID, frame.id());
assert_eq!(id_to_raw(STD_ID), frame.raw_id());
assert!(frame.is_standard());
assert!(!frame.is_extended());
assert!(frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(DATA, frame.data());
let frame = CanFdFrame::new(EXT_ID, DATA).unwrap();
assert_eq!(EXT_ID, frame.id());
assert_eq!(id_to_raw(EXT_ID), frame.raw_id());
assert!(!frame.is_standard());
assert!(frame.is_extended());
assert!(frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert_eq!(DATA, frame.data());
let frame = CanFdFrame::new(EXT_LOW_ID, DATA).unwrap();
assert_eq!(EXT_LOW_ID, frame.id());
assert!(!frame.is_standard());
assert!(frame.is_extended());
}
#[test]
fn test_fd_ext_data_len() {
assert!(CanFdFrame::is_valid_data_len(8));
assert!(CanFdFrame::is_valid_data_len(12));
assert!(CanFdFrame::is_valid_data_len(24));
assert!(CanFdFrame::is_valid_data_len(64));
assert!(!CanFdFrame::is_valid_data_len(28));
assert!(!CanFdFrame::is_valid_data_len(42));
assert!(!CanFdFrame::is_valid_data_len(65));
assert_eq!(CanFdFrame::next_valid_ext_dlen(9), 12);
assert_eq!(CanFdFrame::next_valid_ext_dlen(13), 16);
assert_eq!(CanFdFrame::next_valid_ext_dlen(17), 20);
assert_eq!(CanFdFrame::next_valid_ext_dlen(21), 24);
assert_eq!(CanFdFrame::next_valid_ext_dlen(25), 32);
assert_eq!(CanFdFrame::next_valid_ext_dlen(33), 48);
assert_eq!(CanFdFrame::next_valid_ext_dlen(49), 64);
assert_eq!(CanFdFrame::next_valid_ext_dlen(99), 64);
}
#[test]
fn test_fd_frame_padding() {
let mut frame = CanFdFrame::new(STD_ID, EXT_DATA_INVALID_DLEN).unwrap();
assert_eq!(frame.data(), EXT_DATA_PADDED);
assert_eq!(frame.len(), EXT_DATA_PADDED.len());
assert_eq!(frame.data().len(), frame.len());
assert_eq!(frame.dlc(), EXT_DATA_PADDED_DLC);
frame = CanFdFrame::new(STD_ID, EXT_DATA).unwrap();
assert_eq!(frame.data(), EXT_DATA);
assert_eq!(frame.len(), EXT_DATA.len());
assert_eq!(frame.data().len(), frame.len());
assert_eq!(frame.dlc(), EXT_DATA_DLC);
frame.set_data(EXT_DATA_INVALID_DLEN).unwrap();
assert_eq!(frame.data(), EXT_DATA_PADDED);
assert_eq!(frame.len(), EXT_DATA_PADDED.len());
assert_eq!(frame.data().len(), frame.len());
assert_eq!(frame.dlc(), EXT_DATA_PADDED_DLC);
}
#[test]
fn test_to_fd_frame() {
let data_frame = CanDataFrame::new(STD_ID, DATA).unwrap();
let frame = CanFdFrame::from(data_frame);
assert_eq!(STD_ID, frame.id());
assert!(frame.is_standard());
assert!(frame.is_data_frame());
assert!(!frame.is_remote_frame());
assert!(!frame.is_error_frame());
assert!(frame.flags().contains(FdFlags::FDF));
assert_eq!(frame.len(), DATA_LEN);
assert_eq!(frame.data().len(), DATA_LEN);
assert_eq!(frame.data(), DATA);
let fdframe = canfd_frame_default();
let frame = CanFdFrame::from(fdframe);
assert!(frame.flags().contains(FdFlags::FDF));
}
#[test]
fn test_fd_to_data_frame() {
let fdframe = CanFdFrame::new(STD_ID, DATA).unwrap();
assert!(fdframe.flags().contains(FdFlags::FDF));
let frame = CanDataFrame::try_from(fdframe).unwrap();
assert_eq!(STD_ID, frame.id());
assert_eq!(frame.len(), DATA_LEN);
assert_eq!(frame.data().len(), DATA_LEN);
assert_eq!(frame.data(), DATA);
let mut fdframe = canfd_frame_default();
crate::as_bytes_mut(&mut fdframe)[..size_of::<can_frame>()]
.clone_from_slice(crate::as_bytes(&frame.0));
assert_eq!(fdframe.flags, 0);
}
}