Skip to main content

rs_can/frame/
identifier.rs

1use crate::{
2    constants::{EFF_MASK, SFF_MASK},
3    error::Error,
4    CanResult,
5};
6use bitflags::bitflags;
7use serde::{Deserialize, Serialize};
8
9bitflags! {
10    /// Identifier flags for indicating various frame types.
11    ///
12    /// These flags are applied logically in `can`, but flag values themselves correspond to the
13    /// format used by the Linux [SocketCAN][socketcan] library.  This lets flags be applied
14    /// logically to identifiers such that callers can construct their calls to the underlying CAN
15    /// transceivers/controllers in whatever way is required, but also provides a happy path for
16    /// SocketCAN users by allowing generation of the all-in-one 32-bit identifier value.
17    ///
18    /// [socketcan]: https://www.kernel.org/doc/Documentation/networking/can.txt
19    #[repr(transparent)]
20    pub struct IdentifierFlags: u32 {
21        /// The frame is using the extended format i.e. 29-bit extended identifiers.
22        const EXTENDED = 0x8000_0000;
23        /// The frame is a remote transmission request.
24        const REMOTE = 0x4000_0000;
25        /// The frame is an error frame.
26        const ERROR = 0x2000_0000;
27    }
28}
29
30bitflags! {
31    #[repr(transparent)]
32    pub struct CanFdFlags: u8 {
33        /// bit rate switch (second bitrate for payload data)
34        const BRS = 0x01;
35        /// error state indicator of the transmitting node
36        const ESI = 0x02;
37        /// if set, the frame is a CAN FD frame;
38        /// if not set, the frame may be a CAN CC frame or a CAN FD frame.
39        const FDF = 0x04;
40    }
41}
42
43bitflags! {
44    #[repr(transparent)]
45    pub struct CanXlFlags: u8 {
46        /// Simple Extended Content.
47        const SEC = 0x01;
48        /// Remote Request Substitution.
49        const RRS = 0x02;
50        /// if set, the frame is a CAN XL frame;
51        /// if not set, the frame is a CAN CC frame or a CAN FD frame.
52        const XLF = 0x80;
53    }
54}
55
56#[derive(Debug, Copy, Clone, Eq, PartialEq, Deserialize, Serialize, Hash)]
57pub enum Filter {
58    Standard { id: StandardId, mask: u16 },
59    Extended { id: ExtendedId, mask: u32 },
60}
61
62impl Default for Filter {
63    fn default() -> Self {
64        Self::Standard {
65            id: StandardId::default(),
66            mask: 0,
67        }
68    }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Hash)]
72pub enum Id {
73    Standard(StandardId),
74    Extended(ExtendedId),
75}
76
77#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Hash)]
78pub struct StandardId(u16);
79
80#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Hash)]
81pub struct ExtendedId(u32);
82
83impl StandardId {
84    pub const MAX: u16 = 0x7FF;
85
86    pub fn new(id: u16) -> CanResult<Self> {
87        if id > Self::MAX {
88            Err(Error::InvalidIdentifier(id as u32))
89        } else {
90            Ok(Self(id))
91        }
92    }
93
94    #[inline]
95    pub fn as_raw(self) -> u16 {
96        self.0
97    }
98}
99
100impl ExtendedId {
101    pub const MAX: u32 = 0x1FFF_FFFF;
102
103    pub fn new(id: u32) -> CanResult<Self> {
104        if id > Self::MAX {
105            Err(Error::InvalidIdentifier(id))
106        } else {
107            Ok(Self(id))
108        }
109    }
110
111    #[inline]
112    pub fn as_raw(self) -> u32 {
113        self.0
114    }
115}
116
117impl Into<u32> for Id {
118    /// 32-bit integer with extended flag
119    fn into(self) -> u32 {
120        self.into_socketcan_bits()
121    }
122}
123
124impl TryFrom<u32> for Id {
125    type Error = Error;
126
127    fn try_from(v: u32) -> Result<Self, Self::Error> {
128        let flag_mask =
129            (IdentifierFlags::EXTENDED | IdentifierFlags::REMOTE | IdentifierFlags::ERROR).bits();
130        let raw = v & !flag_mask;
131
132        if v & IdentifierFlags::EXTENDED.bits() != 0 {
133            ExtendedId::new(raw & EFF_MASK).map(Id::Extended)
134        } else {
135            StandardId::new((raw & SFF_MASK) as u16).map(Id::Standard)
136        }
137    }
138}
139
140impl Id {
141    #[inline]
142    pub fn from_bits(raw: u32, extended: Option<bool>) -> CanResult<Self> {
143        match extended {
144            Some(true) => ExtendedId::new(raw & EFF_MASK).map(Self::Extended),
145            Some(false) => StandardId::new((raw & SFF_MASK) as u16).map(Self::Standard),
146            None => Self::try_from(raw),
147        }
148    }
149
150    #[inline]
151    pub fn as_raw(self) -> u32 {
152        match self {
153            Self::Standard(id) => id.as_raw() as u32,
154            Self::Extended(id) => id.as_raw(),
155        }
156    }
157
158    #[inline]
159    pub fn is_extended(&self) -> bool {
160        matches!(self, Self::Extended(_))
161    }
162
163    #[inline]
164    pub fn into_socketcan_bits(self) -> u32 {
165        match self {
166            Self::Standard(id) => id.as_raw() as u32,
167            Self::Extended(id) => id.as_raw() | IdentifierFlags::EXTENDED.bits(),
168        }
169    }
170
171    /// Display [`Id`] as hex string.
172    #[inline]
173    pub fn into_hex(self) -> String {
174        format!("{:08X}", self.into_socketcan_bits())
175    }
176}
177
178#[cfg(test)]
179mod tests {
180    use super::*;
181
182    #[test]
183    fn id_into_u32_uses_socketcan_bits() {
184        let extended = Id::Extended(ExtendedId::new(0x123456).unwrap());
185        let raw: u32 = extended.into();
186
187        assert_eq!(raw, 0x0012_3456 | IdentifierFlags::EXTENDED.bits());
188    }
189
190    #[test]
191    fn try_from_socketcan_bits_masks_non_identifier_flags() {
192        let bits = 0x0012_3456
193            | IdentifierFlags::EXTENDED.bits()
194            | IdentifierFlags::REMOTE.bits()
195            | IdentifierFlags::ERROR.bits();
196
197        let id = Id::try_from(bits).unwrap();
198        assert_eq!(id, Id::Extended(ExtendedId::new(0x0012_3456).unwrap()));
199    }
200}