uds_rs/uds/
ecu_reset.rs

1//! # Implementation of EcuReset 0x11 service
2//!
3//! This module provides following methods for UdsClient:
4//!
5//! [UdsClient::ecu_reset]
6//!
7use 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}