1use super::*;
8use crate::uds::uds_definitions::SEND_RECEIVE_SID_OFFSET;
9use num_enum::{IntoPrimitive, TryFromPrimitive};
10
11const ECU_RESET_SID: u8 = 0x11;
12
13#[derive(IntoPrimitive, TryFromPrimitive, Debug, PartialEq)]
14#[repr(u8)]
15pub enum ResetType {
16 HardReset = 1,
17 KeyOffOnReset = 2,
18 SoftReset = 3,
19 EnableRapidPowerShutDown = 4,
20 DisableRapidPowerShutDown = 5,
21}
22
23#[derive(Debug, PartialEq)]
24pub struct EcuResetResponse {
25 reset_type: ResetType,
26 power_down_time: Option<u8>,
27}
28
29impl UdsClient {
30 pub async fn ecu_reset(&self, reset_type: ResetType) -> EcuResponseResult {
31 let request = compose_ecu_reset_request(reset_type);
32 let raw_response = self.send_and_receive(&request).await?;
33 let response = parse_ecu_reset_response(&raw_response);
34 response
35 }
36}
37
38fn compose_ecu_reset_request(reset_type: ResetType) -> Vec<u8> {
39 vec![ECU_RESET_SID, reset_type as u8]
40}
41
42fn parse_ecu_reset_response(raw_response: &[u8]) -> EcuResponseResult {
43 let mut response_iter = raw_response.iter();
44 let sid = *response_iter.next().ok_or(UdsError::ResponseEmpty)?;
45 if sid != ECU_RESET_SID + SEND_RECEIVE_SID_OFFSET {
46 return Err(UdsError::SidMismatch {
47 expected: ECU_RESET_SID + SEND_RECEIVE_SID_OFFSET,
48 received: sid,
49 raw_message: raw_response.to_vec(),
50 });
51 }
52 let reset_type_byte = *response_iter.next().ok_or(UdsError::InvalidLength {
53 raw_message: raw_response.to_vec(),
54 })?;
55 let reset_type: ResetType = ResetType::try_from_primitive(reset_type_byte).map_err(|_| {
56 UdsError::ResponseIncorrect {
57 raw_message: raw_response.to_vec(),
58 }
59 })?;
60 let mut power_down_time = None;
61 if reset_type == ResetType::EnableRapidPowerShutDown {
62 power_down_time = Some(*response_iter.next().ok_or(UdsError::InvalidLength {
63 raw_message: raw_response.to_vec(),
64 })?);
65 }
66 let response = UdsResponse::EcuReset(DataFormat::Parsed(EcuResetResponse {
67 reset_type,
68 power_down_time,
69 }));
70 Ok(response)
71}