tuneutils/protocols/isotp/
mod.rs

1use std::time;
2use std::default::Default;
3
4pub mod can;
5
6pub use self::can::IsotpCan;
7use crate::error::{Error, Result};
8
9use std::cmp;
10
11pub struct Options {
12    pub source_id: u32,
13    pub dest_id: u32,
14    pub timeout: time::Duration,
15}
16
17impl Default for Options {
18    fn default() -> Options {
19        Options {
20            source_id: 0x7e0,
21            dest_id: 0x7e8,
22            timeout: time::Duration::from_secs(1),
23        }
24    }
25}
26
27pub enum FrameType {
28    Single,
29    First,
30    Consecutive,
31    Flow,
32}
33
34#[derive(Debug)]
35pub enum FCFlag {
36    Continue = 0,
37    Wait = 1,
38    Overflow = 2,
39}
40
41#[derive(Debug)]
42pub struct FlowControlFrame {
43    flag: FCFlag,
44    block_size: u8,
45    separation_time: time::Duration,
46}
47
48#[derive(Debug)]
49pub struct SingleFrame {
50    length: u8,
51    data: [u8; 7],
52}
53
54impl SingleFrame {
55    fn new(frame: &[u8]) -> Result<SingleFrame> {
56        if frame.is_empty() {
57            return Err(Error::InvalidFrame);
58        }
59        if frame[0] & 0xF0 != 0 {
60            // Not a single frame
61            return Err(Error::InvalidFrame);
62        }
63        let len = cmp::min(7, frame[0] & 0x0F) as usize;
64        let mut data = [0; 7];
65        data[0..len].copy_from_slice(&frame[1..=len]);
66        Ok(SingleFrame {
67            data,
68            length: len as u8,
69        })
70    }
71}
72
73#[derive(Debug)]
74pub struct FirstFrame {
75    length: u16,
76    data: [u8; 6],
77}
78
79impl FirstFrame {
80    fn new(frame: &[u8]) -> Result<FirstFrame> {
81        assert!(frame.len() <= 8);
82        if frame.len() < 2 {
83            return Err(Error::InvalidFrame);
84        }
85        if frame[0] & 0xF0 != 0x10 {
86            // Not a first frame
87            return Err(Error::InvalidFrame);
88        }
89        let length = ((frame[0] as u16 & 0x0F) << 8) | frame[1] as u16;
90        let data_length = cmp::min(frame.len() - 2, cmp::min(length as usize, 6));
91        let mut data = [0; 6];
92        data[..data_length].copy_from_slice(&frame[2..data_length+2]);
93        Ok(FirstFrame {
94            length,
95            data,
96        })
97    }
98}
99
100pub struct ConsecutiveFrame {
101    index: u8,
102    data: [u8; 7],
103    data_length: u8,
104}
105
106#[derive(Debug)]
107pub struct Frame {
108    data: [u8; 8],
109}
110
111pub trait IsotpInterface {
112    /// Receives an ISO-TP packet
113    fn recv(&self) -> Result<Vec<u8>>;
114
115    /// Sends an ISO-TP packet
116    fn send(&self, data: &[u8]) -> Result<()>;
117
118    fn request(&self, request: &[u8]) -> Result<Vec<u8>> {
119        self.send(&request)?;
120        self.recv()
121    }
122    
123
124}
125
126fn duration_to_st(duration: time::Duration) -> u8 {
127    if duration.subsec_micros() <= 900 && duration.subsec_micros() >= 100 {
128        return (cmp::max(duration.subsec_micros() / 100, 1) + 0xF0) as u8;
129    }
130    duration.subsec_micros() as u8
131}
132
133impl Frame {
134    fn new(data: [u8; 8]) -> Frame {
135        Frame {data}
136    }
137
138    fn from_single_data(data: &[u8]) -> Frame {
139        assert!(data.len() <= 7);
140
141        let mut d = [0; 8];
142        d[0] = data.len() as u8; // Single Frame id (0 << 4) | size
143        d[1..=data.len()].copy_from_slice(&data);
144        Frame {
145            data: d,
146        }
147    }
148
149    fn from_flow(flow: FlowControlFrame) -> Frame {
150        let mut frame = Frame {data: [0; 8]};
151        frame.data[0] = 0x30 | (flow.flag as u8);
152        frame.data[1] = flow.block_size;
153        frame.data[2] = duration_to_st(flow.separation_time);
154        frame
155    }
156
157    fn from_first_data(data: &[u8], size: u16) -> Frame {
158        assert!(data.len() <= 6);
159
160        let mut d = [0; 8];
161        d[0] = (0x10 | ((size & 0xF00) >> 8)) as u8;
162        d[1] = (size & 0xFF) as u8;
163        d[2..data.len() + 2].copy_from_slice(&data);
164        Frame {
165            data: d
166        }
167    }
168
169    fn from_consec_data(data: &[u8], index: u8) -> Frame {
170        assert!(data.len() <= 7);
171
172        let mut d = [0; 8];
173        d[0] = ((0x20) | (index & 0xF)) as u8;
174        d[1..=data.len()].copy_from_slice(&data);
175        Frame {
176            data: d
177        }
178    }
179
180    pub fn from_single(frame: &SingleFrame) -> Frame {
181        Self::from_single_data(&frame.data[..frame.length as usize])
182    }
183
184    fn get_type(&self) -> Option<FrameType> {
185        if self.data.is_empty() {
186            return None;
187        }
188
189        let b_type = self.data[0] & 0xF0;
190
191        match b_type {
192            0 => Some(FrameType::Single),
193            1 => Some(FrameType::First),
194            2 => Some(FrameType::Consecutive),
195            3 => Some(FrameType::Flow),
196            _ => None,
197        }
198    }
199}