isotp_rs/
can.rs

1mod constant;
2pub use constant::*;
3
4pub mod driver;
5
6pub mod frame;
7pub mod identifier;
8
9pub mod isotp;
10
11#[cfg(feature = "j1939")]
12pub mod j1939;
13
14mod utils;
15
16use crate::{FlowControlContext, FlowControlState, FrameType, IsoTpFrame};
17// use crate::can::constant::{CAN_FRAME_MAX_SIZE, DEFAULT_PADDING};
18use crate::error::Error;
19
20/// ISO-TP address format.
21#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
22pub enum AddressFormat {
23    // UNKNOWN = 0xFF,
24    // None = 0x00,
25    #[default]
26    Normal = 0x01,      // 11bit CAN-ID
27    NormalFixed = 0x02, // 29bit CAN-ID
28    Extend = 0x03,      // 11bit Remote CAN-ID
29    ExtendMixed = 0x04, // 11bit and 11bit Remote CAN-ID mixed
30    Enhanced = 0x05,    // 11bit(Remote) and 29bot CAN-ID
31}
32
33/// ISO-TP address
34///
35/// * `tx_id`: transmit identifier.
36/// * `rx_id`: receive identifier.
37/// * `fid`: functional address identifier.
38#[derive(Debug, Copy, Clone, Eq, PartialEq)]
39pub struct Address {
40    pub tx_id: u32,
41    pub rx_id: u32,
42    pub fid: u32,
43}
44
45/// ISO-TP address type.
46#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)]
47pub enum AddressType {
48    #[default]
49    Physical,
50    Functional,
51}
52
53/// ISO-TP frame define.
54#[derive(Debug, Clone)]
55pub enum CanIsoTpFrame {
56    /// The ISO-TP single frame.
57    SingleFrame { data: Vec<u8> },
58    /// The ISO-TP first frame.
59    FirstFrame { length: u32, data: Vec<u8> },
60    /// The ISO-TP consecutive frame.
61    ConsecutiveFrame { sequence: u8, data: Vec<u8> },
62    /// The ISO-TP flow control frame.
63    FlowControlFrame(FlowControlContext)
64}
65
66impl<'a> From<&'a CanIsoTpFrame> for FrameType {
67    fn from(value: &'a CanIsoTpFrame) -> Self {
68        match value {
69            CanIsoTpFrame::SingleFrame { .. } => Self::Single,
70            CanIsoTpFrame::FirstFrame { .. } => Self::First,
71            CanIsoTpFrame::ConsecutiveFrame { .. } => Self::Consecutive,
72            CanIsoTpFrame::FlowControlFrame(_) => Self::FlowControl,
73        }
74    }
75}
76
77unsafe impl Send for CanIsoTpFrame {}
78
79impl IsoTpFrame for CanIsoTpFrame {
80    fn decode<T: AsRef<[u8]>>(data: T) -> Result<Self, Error> {
81        let data = data.as_ref();
82        let length = data.len();
83        match length {
84            0 => Err(Error::EmptyPdu),
85            1..=2 => Err(Error::InvalidPdu(data.to_vec())),
86            3.. => {
87                let byte0 = data[0];
88                match FrameType::try_from(byte0)? {
89                    FrameType::Single => {   // Single frame
90                        utils::decode_single(data, byte0, length)
91                    },
92                    FrameType::First => {   // First frame
93                        utils::decode_first(data, byte0, length)
94                    },
95                    FrameType::Consecutive => {
96                        let sequence = byte0 & 0x0F;
97                        Ok(Self::ConsecutiveFrame { sequence, data: Vec::from(&data[1..]) })
98                    },
99                    FrameType::FlowControl => {
100                        // let suppress_positive = (data1 & 0x80) == 0x80;
101                        let state = FlowControlState::try_from(byte0 & 0x0F)?;
102                        let fc = FlowControlContext::new(state, data[1], data[2])?;
103                        Ok(Self::FlowControlFrame(fc))
104                    },
105                }
106            }
107            // v => Err(IsoTpError::LengthOutOfRange(v)),
108        }
109    }
110
111    fn encode(self, padding: Option<u8>) -> Vec<u8> {
112        match self {
113            Self::SingleFrame { data } => {
114                utils::encode_single(data, padding)
115            },
116            Self::FirstFrame { length, data } => {
117                utils::encode_first(length, data)
118            },
119            Self::ConsecutiveFrame { sequence, mut data } => {
120                let mut result = vec![FrameType::Consecutive as u8 | sequence];
121                result.append(&mut data);
122                result.resize(CAN_FRAME_MAX_SIZE, padding.unwrap_or(DEFAULT_PADDING));
123                result
124            },
125            Self::FlowControlFrame(context) => {
126                let byte0_h: u8 = FrameType::FlowControl.into();
127                let byte0_l: u8 = context.state().into();
128                let mut result = vec![
129                    byte0_h | byte0_l,
130                    context.block_size(),
131                    context.st_min(),
132                ];
133                result.resize(CAN_FRAME_MAX_SIZE, padding.unwrap_or(DEFAULT_PADDING));
134                result
135            },
136        }
137    }
138
139    fn from_data<T: AsRef<[u8]>>(data: T) -> Result<Vec<Self>, Error> {
140        utils::from_data(data.as_ref())
141    }
142
143    fn single_frame<T: AsRef<[u8]>>(data: T) -> Result<Self, Error> {
144        utils::new_single(data)
145    }
146
147    fn flow_ctrl_frame(state: FlowControlState,
148                       block_size: u8,
149                       st_min: u8,
150    ) -> Result<Self, Error> {
151        Ok(Self::FlowControlFrame(
152            FlowControlContext::new(state, block_size, st_min)?
153        ))
154    }
155}
156
157#[cfg(test)]
158mod tests {
159    use hex_literal::hex;
160    use crate::can::{CAN_FRAME_MAX_SIZE, CanIsoTpFrame, CONSECUTIVE_FRAME_SIZE, DEFAULT_PADDING, FIRST_FRAME_SIZE_2004};
161    use crate::{FlowControlState, IsoTpFrame};
162
163    #[test]
164    fn test_single() -> anyhow::Result<()> {
165        let data = hex!("02 10 01 00 00 00 00 00").as_slice();
166        let frame = CanIsoTpFrame::decode(data)?;
167        match frame.clone() {
168            CanIsoTpFrame::SingleFrame { data } => {
169                assert_eq!(data, hex!("1001"));
170            },
171            _ => {
172                panic!("Invalid frame type");
173            }
174        }
175        assert_eq!(frame.encode(Some(0x00)), data.to_vec());
176
177        let frame = CanIsoTpFrame::SingleFrame { data: hex!("1001").to_vec() };
178        assert_eq!(frame.encode(Some(0x00)), data.to_vec());
179        Ok(())
180    }
181
182    #[test]
183    fn test_first() -> anyhow::Result<()> {
184        let data = hex!("10 0f 62 f1 87 44 56 43");
185        let frame = CanIsoTpFrame::decode(data)?;
186        match frame.clone() {
187            CanIsoTpFrame::FirstFrame { length, data } => {
188                assert_eq!(length, 0x0f);
189                assert_eq!(data, hex!("62 f1 87 44 56 43"));
190            },
191            _ => {
192                panic!("Invalid frame type");
193            }
194        }
195        assert_eq!(frame.encode(None), data.to_vec());
196
197        let frame = CanIsoTpFrame::FirstFrame {
198            length: 0x0f,
199            data: hex!("62 f1 87 44 56 43").to_vec()
200        };
201        assert_eq!(frame.encode(None), data.to_vec());
202
203        Ok(())
204    }
205
206    #[test]
207    fn test_consecutive() -> anyhow::Result<()> {
208        let data = hex!("21 37 45 32 30 30 30 30");
209        let frame = CanIsoTpFrame::decode(data)?;
210        match frame.clone() {
211            CanIsoTpFrame::ConsecutiveFrame { sequence, data } => {
212                assert_eq!(sequence, 1);
213                assert_eq!(data, hex!("37 45 32 30 30 30 30"));
214            },
215            _ => {
216                panic!("Invalid frame type");
217            }
218        }
219        assert_eq!(frame.encode(None), data.to_vec());
220
221        let frame = CanIsoTpFrame::ConsecutiveFrame {
222            sequence: 1,
223            data: hex!("37 45 32 30 30 30 30").to_vec()
224        };
225        assert_eq!(frame.encode(None), data.to_vec());
226        Ok(())
227    }
228
229    #[test]
230    fn test_flow_control() -> anyhow::Result<()> {
231        let data = hex!("30 80 01 55 55 55 55 55").as_slice();
232        let frame = CanIsoTpFrame::decode(data)?;
233        match frame.clone() {
234            CanIsoTpFrame::FlowControlFrame(context) => {
235                assert_eq!(context.state(), FlowControlState::Continues);
236                assert_eq!(context.block_size(), 0x80);
237                assert_eq!(context.st_min(), 0x01);
238            },
239            _ => {
240                panic!("Invalid frame type");
241            }
242        }
243        assert_eq!(frame.encode(Some(0x55)), data.to_vec());
244
245        let frame = CanIsoTpFrame::default_flow_ctrl_frame();
246        assert_eq!(frame.encode(Some(0x55)), hex!("30 00 0a 55 55 55 55 55"));
247        Ok(())
248    }
249
250    #[test]
251    fn test_data_to_multi() -> anyhow::Result<()> {
252        let data = hex!("62 f1 87 44 56 43 37 45 32 30 30 30 30 30 37").as_slice();
253        let frames = CanIsoTpFrame::from_data(data)?;
254        for (index, frame) in frames.into_iter().enumerate() {
255            match index {
256                0 => {
257                    assert_eq!(frame.encode(None), hex!("10 0f 62 f1 87 44 56 43").to_vec());
258                },
259                1 => {
260                    assert_eq!(frame.encode(None), hex!("21 37 45 32 30 30 30 30").to_vec());
261                },
262                2 => assert_eq!(frame.encode(None), hex!("22 30 37 aa aa aa aa aa").to_vec()),
263                _ => panic!()
264            }
265        }
266
267        let mut size = 0x96;
268        let data = vec![0x30; size];
269        let frames = CanIsoTpFrame::from_data(data)?;
270        for (index, frame) in frames.into_iter().enumerate() {
271            match index {
272                0 => {
273                    size -= FIRST_FRAME_SIZE_2004;
274                    assert_eq!(frame.encode(None), hex!("10 96 30 30 30 30 30 30"))
275                },
276                1..=15 => {
277                    size -= CONSECUTIVE_FRAME_SIZE;
278                    let expect = vec![0x20 + index as u8, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30];
279                    assert_eq!(frame.encode(None), expect);
280                }
281                _ => {
282                    if size > CONSECUTIVE_FRAME_SIZE {
283                        size -= CONSECUTIVE_FRAME_SIZE;
284                        let expect = vec![0x20 + (index % 16) as u8, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30];
285                        assert_eq!(frame.encode(None), expect);
286                    }
287                    else {
288                        let mut expect = vec![0x20 + (index % 16) as u8];
289                        for _ in 0..size {
290                            expect.push(0x30);
291                        }
292                        expect.resize(CAN_FRAME_MAX_SIZE, DEFAULT_PADDING);
293                        assert_eq!(frame.encode(None), expect);
294                    }
295                },
296            }
297        }
298        Ok(())
299    }
300}