use automotive_diag::uds::{UdsCommand, UdsError};
use super::PciType;
#[derive(Debug, Clone, thiserror::Error)]
pub enum FrameError {
#[error("Invalid UDS frame type.")]
InvalidFrameType,
#[error("Frame size is incorrect.")]
InvalidSize,
#[error("Invalid Service Identifier (SID).")]
InvalidSid,
#[error("Invalid Negative Response Code (NRC).")]
InvalidNrc,
#[error("Invalid CAN message length.")]
InvalidCanLength,
#[error("An unknown error occurred.")]
Others,
}
#[derive(Debug, Clone, PartialEq)]
pub enum UdsFrame {
Single(UdsSingleFrame),
First(UdsFirstFrame),
Consecutive(UdsConsecutiveFrame),
FlowControl(UdsFlowControlFrame),
NegativeResp(UdsNegativeResponse),
}
impl UdsFrame {
pub fn default() -> Self {
UdsFrame::Single(UdsSingleFrame {
size: 0,
sid: 0,
did: None,
payload: Vec::new(),
})
}
pub fn pci_type(&self) -> PciType {
match self {
UdsFrame::Single(_) => PciType::SingleFrame,
UdsFrame::First(_) => PciType::FirstFrame,
UdsFrame::Consecutive(_) => PciType::ConsecutiveFrame,
UdsFrame::FlowControl(_) => PciType::FlowControl,
UdsFrame::NegativeResp(_) => PciType::SingleFrame,
}
}
pub fn is_negative_frame(&self) -> bool {
matches!(self, UdsFrame::NegativeResp(_frame))
}
pub fn is_single_frame(&self) -> bool {
matches!(self, UdsFrame::Single(_frame))
}
pub fn is_first_frame(&self) -> bool {
matches!(self, UdsFrame::First(_frame))
}
pub fn is_consecutive_frame(&self) -> bool {
matches!(self, UdsFrame::Consecutive(_frame))
}
pub fn is_flow_control_frame(&self) -> bool {
matches!(self, UdsFrame::FlowControl(_frame))
}
pub fn to_vec(&self) -> Result<Vec<u8>, FrameError> {
match self {
UdsFrame::Single(uds_single_frame) => uds_single_frame.to_vec(),
UdsFrame::First(uds_first_frame) => uds_first_frame.to_vec(),
UdsFrame::Consecutive(uds_consecutive_frame) => uds_consecutive_frame.to_vec(),
UdsFrame::FlowControl(uds_flow_control_frame) => uds_flow_control_frame.to_vec(),
UdsFrame::NegativeResp(uds_negative_response) => Ok(uds_negative_response.to_vec()),
}
}
pub fn from_vec(data: Vec<u8>) -> Result<Self, FrameError> {
let frame_type = data
.first()
.map(|b| b >> 4)
.ok_or(FrameError::InvalidCanLength)?;
match frame_type {
0x0 => {
let size = data[0] & 0x0F;
let sid = *data.get(1).ok_or(FrameError::InvalidSize)?;
if sid == 0x7F {
let rsid = UdsCommand::from_repr(*data.get(2).ok_or(FrameError::InvalidSid)?)
.ok_or(FrameError::InvalidSid)?;
let nrc = UdsError::from_repr(*data.get(3).ok_or(FrameError::InvalidNrc)?)
.ok_or(FrameError::InvalidNrc)?;
return Ok(UdsFrame::NegativeResp(UdsNegativeResponse {
size,
rsid,
nrc,
}));
}
let did = if data.len() > 2 {
Some(u16::from_be_bytes([data[2], *data.get(3).unwrap_or(&0)]))
} else {
None
};
let payload_start = if did.is_some() { 4 } else { 2 };
let payload = data.get(payload_start..).unwrap_or(&[]).to_vec();
Ok(UdsFrame::Single(UdsSingleFrame {
size,
sid,
did,
payload,
}))
}
0x1 => {
let size = (((data[0] & 0x0F) as u16) << 8)
| (*data.get(1).ok_or(FrameError::InvalidSize)? as u16);
let sid = *data.get(2).ok_or(FrameError::InvalidSize)?;
let did = data
.get(3..5)
.map(|bytes| u16::from_be_bytes([bytes[0], bytes[1]]));
let payload_start = if did.is_some() { 5 } else { 3 };
let payload = data.get(payload_start..).unwrap_or(&[]).to_vec();
Ok(UdsFrame::First(UdsFirstFrame {
size,
sid,
did,
payload,
}))
}
0x2 => {
let seq_num = data[0] & 0x0F;
let payload = data.get(1..).unwrap_or(&[]).to_vec();
Ok(UdsFrame::Consecutive(UdsConsecutiveFrame {
seq_num,
payload,
}))
}
0x3 => {
let (flag, block_size, separation_time) = (
data[0] & 0x0F,
*data.get(1).ok_or(FrameError::InvalidSize)?,
*data.get(2).ok_or(FrameError::InvalidSize)?,
);
let padding = data.get(3..).unwrap_or(&[]).to_vec();
Ok(UdsFrame::FlowControl(UdsFlowControlFrame {
flag,
block_size,
separation_time,
padding,
}))
}
_ => Err(FrameError::InvalidFrameType),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct UdsNegativeResponse {
pub size: u8,
pub rsid: UdsCommand,
pub nrc: UdsError,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UdsSingleFrame {
pub size: u8,
pub sid: u8,
pub did: Option<u16>,
pub payload: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UdsFirstFrame {
pub size: u16,
pub sid: u8,
pub did: Option<u16>,
pub payload: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UdsConsecutiveFrame {
pub seq_num: u8,
pub payload: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UdsFlowControlFrame {
pub flag: u8,
pub block_size: u8,
pub separation_time: u8,
pub padding: Vec<u8>,
}
impl UdsNegativeResponse {
pub fn new(rsid: UdsCommand, nrc: UdsError, size: u8) -> Self {
Self { size, rsid, nrc }
}
pub fn to_vec(&self) -> Vec<u8> {
vec![self.size & 0x0F, 0x7F, self.rsid.into(), self.nrc.into()]
}
}
impl UdsSingleFrame {
pub fn new(sid: u8, did: Option<u16>, payload: Vec<u8>) -> Result<Self, FrameError> {
if payload.len() > 7 {
return Err(FrameError::InvalidCanLength);
}
let size = if did.is_some() {
payload.len() + 3
} else {
payload.len() + 1
} as u8;
Ok(Self {
size,
sid,
did,
payload,
})
}
pub fn to_vec(&self) -> Result<Vec<u8>, FrameError> {
if self.payload.len() > 7 {
return Err(FrameError::InvalidSize);
}
let mut frame = Vec::new();
frame.push(self.size & 0x0F); frame.push(self.sid);
if let Some(did) = self.did {
frame.extend_from_slice(&did.to_be_bytes());
}
frame.extend_from_slice(&self.payload);
Ok(frame)
}
}
impl UdsFirstFrame {
pub fn new(sid: u8, size: u16, did: Option<u16>, payload: Vec<u8>) -> Result<Self, FrameError> {
if payload.len() > 6 {
return Err(FrameError::InvalidCanLength);
}
Ok(Self {
size,
sid,
did,
payload,
})
}
pub fn to_vec(&self) -> Result<Vec<u8>, FrameError> {
if self.payload.len() > 6 {
return Err(FrameError::InvalidSize);
}
let mut frame = Vec::new();
frame.push(0x10 | ((self.size >> 8) as u8 & 0x0F)); frame.push((self.size & 0xFF) as u8); frame.push(self.sid);
if let Some(did) = self.did {
frame.extend_from_slice(&did.to_be_bytes());
}
frame.extend_from_slice(&self.payload);
Ok(frame)
}
}
impl UdsConsecutiveFrame {
pub fn new(seq_num: u8, payload: Vec<u8>) -> Result<Self, FrameError> {
if payload.len() > 7 {
return Err(FrameError::InvalidCanLength);
}
Ok(Self { seq_num, payload })
}
pub fn to_vec(&self) -> Result<Vec<u8>, FrameError> {
if self.payload.len() > 7 {
return Err(FrameError::InvalidSize);
}
let mut frame = Vec::new();
frame.push(0x20 | (self.seq_num & 0x0F)); frame.extend_from_slice(&self.payload);
Ok(frame)
}
}
impl UdsFlowControlFrame {
pub fn new(
flag: u8,
block_size: u8,
separation_time: u8,
padding: Vec<u8>,
) -> Result<Self, FrameError> {
if padding.len() > 5 {
return Err(FrameError::InvalidCanLength);
}
Ok(Self {
flag,
block_size,
separation_time,
padding,
})
}
pub fn to_vec(&self) -> Result<Vec<u8>, FrameError> {
let mut frame = vec![
0x30 | (self.flag & 0x0F), self.block_size,
self.separation_time,
];
frame.extend_from_slice(&self.padding);
Ok(frame)
}
}