pub mod isotp;
pub use self::isotp::UdsIsotp;
use crate::error::{Error, Result};
use byteorder::{BigEndian, WriteBytesExt};
pub struct Response {
pub data: Vec<u8>,
}
pub const UDS_REQ_SESSION: u8 = 0x10;
pub const UDS_REQ_SECURITY: u8 = 0x27;
pub const UDS_REQ_READMEM: u8 = 0x23;
pub const UDS_REQ_REQUESTDOWNLOAD: u8 = 0x34;
pub const UDS_REQ_REQUESTUPLOAD: u8 = 0x35;
pub const UDS_REQ_TRANSFERDATA: u8 = 0x36;
pub const UDS_REQ_READDATABYID: u8 = 0x22;
pub const UDS_NRES_RCRRP: u8 = 0x78;
pub trait UdsInterface {
fn request(&self, request_sid: u8, data: &[u8]) -> Result<Vec<u8>>;
fn request_session(&self, session_type: u8) -> Result<Vec<u8>> {
let mut response = self.request(UDS_REQ_SESSION, &[session_type])?;
if response.is_empty() {
return Err(Error::InvalidPacket);
}
if response[0] != session_type {
return Err(Error::InvalidPacket);
}
response.remove(0);
Ok(response)
}
fn request_security_seed(&self) -> Result<Vec<u8>> {
let mut response = self.request(UDS_REQ_SECURITY, &[1])?;
if response.is_empty() {
return Err(Error::InvalidPacket);
}
if response[0] != 1 {
return Err(Error::InvalidPacket);
}
response.remove(0);
Ok(response)
}
fn request_security_key(&self, key: &[u8]) -> Result<()> {
let mut request = Vec::with_capacity(key.len() + 1);
request.push(2);
request.extend_from_slice(&key);
let _response = self.request(UDS_REQ_SECURITY, &request)?;
Ok(())
}
fn request_read_memory_address(&self, address: u32, length: u16) -> Result<Vec<u8>> {
let mut request = [0; 6];
{
let mut writer: &mut [u8] = &mut request;
writer.write_u32::<BigEndian>(address).unwrap();
writer.write_u16::<BigEndian>(length).unwrap();
}
self.request(UDS_REQ_READMEM, &request)
}
fn read_data_by_identifier(&self, id: u16) -> Result<Vec<u8>> {
let request = &[(id >> 8) as u8, (id & 0xFF) as u8];
let mut res = self.request(UDS_REQ_READDATABYID, request)?;
if res.len() < 2 {
return Err(Error::InvalidPacket);
}
if res[0] != request[0] || res[1] != request[1] {
return Err(Error::InvalidPacket);
}
res.remove(0);
res.remove(0);
Ok(res)
}
}