use std::time;
use std::default::Default;
pub mod can;
pub use self::can::IsotpCan;
use crate::error::{Error, Result};
use std::cmp;
pub struct Options {
pub source_id: u32,
pub dest_id: u32,
pub timeout: time::Duration,
}
impl Default for Options {
fn default() -> Options {
Options {
source_id: 0x7e0,
dest_id: 0x7e8,
timeout: time::Duration::from_secs(1),
}
}
}
pub enum FrameType {
Single,
First,
Consecutive,
Flow,
}
#[derive(Debug)]
pub enum FCFlag {
Continue = 0,
Wait = 1,
Overflow = 2,
}
#[derive(Debug)]
pub struct FlowControlFrame {
flag: FCFlag,
block_size: u8,
separation_time: time::Duration,
}
#[derive(Debug)]
pub struct SingleFrame {
length: u8,
data: [u8; 7],
}
impl SingleFrame {
fn new(frame: &[u8]) -> Result<SingleFrame> {
if frame.is_empty() {
return Err(Error::InvalidFrame);
}
if frame[0] & 0xF0 != 0 {
return Err(Error::InvalidFrame);
}
let len = cmp::min(7, frame[0] & 0x0F) as usize;
let mut data = [0; 7];
data[0..len].copy_from_slice(&frame[1..=len]);
Ok(SingleFrame {
data,
length: len as u8,
})
}
}
#[derive(Debug)]
pub struct FirstFrame {
length: u16,
data: [u8; 6],
}
impl FirstFrame {
fn new(frame: &[u8]) -> Result<FirstFrame> {
assert!(frame.len() <= 8);
if frame.len() < 2 {
return Err(Error::InvalidFrame);
}
if frame[0] & 0xF0 != 0x10 {
return Err(Error::InvalidFrame);
}
let length = ((frame[0] as u16 & 0x0F) << 8) | frame[1] as u16;
let data_length = cmp::min(frame.len() - 2, cmp::min(length as usize, 6));
let mut data = [0; 6];
data[..data_length].copy_from_slice(&frame[2..data_length+2]);
Ok(FirstFrame {
length,
data,
})
}
}
pub struct ConsecutiveFrame {
index: u8,
data: [u8; 7],
data_length: u8,
}
#[derive(Debug)]
pub struct Frame {
data: [u8; 8],
}
pub trait IsotpInterface {
fn recv(&self) -> Result<Vec<u8>>;
fn send(&self, data: &[u8]) -> Result<()>;
fn request(&self, request: &[u8]) -> Result<Vec<u8>> {
self.send(&request)?;
self.recv()
}
}
fn duration_to_st(duration: time::Duration) -> u8 {
if duration.subsec_micros() <= 900 && duration.subsec_micros() >= 100 {
return (cmp::max(duration.subsec_micros() / 100, 1) + 0xF0) as u8;
}
duration.subsec_micros() as u8
}
impl Frame {
fn new(data: [u8; 8]) -> Frame {
Frame {data}
}
fn from_single_data(data: &[u8]) -> Frame {
assert!(data.len() <= 7);
let mut d = [0; 8];
d[0] = data.len() as u8; d[1..=data.len()].copy_from_slice(&data);
Frame {
data: d,
}
}
fn from_flow(flow: FlowControlFrame) -> Frame {
let mut frame = Frame {data: [0; 8]};
frame.data[0] = 0x30 | (flow.flag as u8);
frame.data[1] = flow.block_size;
frame.data[2] = duration_to_st(flow.separation_time);
frame
}
fn from_first_data(data: &[u8], size: u16) -> Frame {
assert!(data.len() <= 6);
let mut d = [0; 8];
d[0] = (0x10 | ((size & 0xF00) >> 8)) as u8;
d[1] = (size & 0xFF) as u8;
d[2..data.len() + 2].copy_from_slice(&data);
Frame {
data: d
}
}
fn from_consec_data(data: &[u8], index: u8) -> Frame {
assert!(data.len() <= 7);
let mut d = [0; 8];
d[0] = ((0x20) | (index & 0xF)) as u8;
d[1..=data.len()].copy_from_slice(&data);
Frame {
data: d
}
}
pub fn from_single(frame: &SingleFrame) -> Frame {
Self::from_single_data(&frame.data[..frame.length as usize])
}
fn get_type(&self) -> Option<FrameType> {
if self.data.is_empty() {
return None;
}
let b_type = self.data[0] & 0xF0;
match b_type {
0 => Some(FrameType::Single),
1 => Some(FrameType::First),
2 => Some(FrameType::Consecutive),
3 => Some(FrameType::Flow),
_ => None,
}
}
}