tuneutils/protocols/isotp/
mod.rs1use 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 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 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 fn recv(&self) -> Result<Vec<u8>>;
114
115 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; 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}