1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! Wrapper for IOCTL requests
use crate::{dynamic_diag::DynamicDiagSession, DiagServerResult};
use automotive_diag::kwp2000::{KwpCommand, KwpSessionType};
/// Handler for Input output control by local identifier requests (IOCTL)
/// This allows for short term or long term actuation's of components an ECU controls,
/// or reporting a components current state.
///
/// USE WITH CAUTION!
#[derive(Debug)]
pub struct KwpIOCTLManager<'a> {
server: &'a mut DynamicDiagSession,
identifier: u8,
}
impl<'a> KwpIOCTLManager<'a> {
/// Creates an IOCTL manager
///
/// ## Parameters
/// * identifier - A identifier for the component or function to control. Valid ranges are
/// * 0x10-0xF9 - Input output local Identifier
/// * 0xFA-0xFE - System supplier specific
/// * 0xFF - Input output local identifier
/// Other values may result in an ECU rejecting the request.
/// * server - KWP2000 server reference
pub fn new(identifier: u8, server: &'a mut DynamicDiagSession) -> DiagServerResult<Self> {
// We need to be in extended mode for this SID to work, so try now
server.kwp_set_session(KwpSessionType::ExtendedDiagnostics.into())?;
Ok(Self { identifier, server })
}
/// Asks the ECU to take back control of the identifier.
pub fn return_control_to_ecu(&self) -> DiagServerResult<()> {
self.server.send_command_with_response(
KwpCommand::InputOutputControlByLocalIdentifier,
&[self.identifier, 0x00],
)?;
Ok(())
}
/// Asks the ECU to report the current state of the identifier.
pub fn report_current_state(&self) -> DiagServerResult<Vec<u8>> {
self.server.send_command_with_response(
KwpCommand::InputOutputControlByLocalIdentifier,
&[self.identifier, 0x01],
)
}
/// Asks the ECU to return the component identifier back to its default (Factory) state
pub fn reset_to_default_state(&self) -> DiagServerResult<()> {
self.server.send_command_with_response(
KwpCommand::InputOutputControlByLocalIdentifier,
&[self.identifier, 0x04],
)?;
Ok(())
}
/// Asks the ECU to freeze the current state of the identifier
pub fn freeze_current_state(&self) -> DiagServerResult<()> {
self.server.send_command_with_response(
KwpCommand::InputOutputControlByLocalIdentifier,
&[self.identifier, 0x05],
)?;
Ok(())
}
/// Actuates the component at the provided identifier. This is a short term actuation.
/// Once the ECU looses power or returns to its default session state, the component will
/// be controlled by the ECU normally
pub fn short_term_actuate(&self, args: &[u8]) -> DiagServerResult<()> {
let mut a = vec![self.identifier, 0x07];
a.extend_from_slice(args);
self.server
.send_command_with_response(KwpCommand::InputOutputControlByLocalIdentifier, &a)?;
Ok(())
}
/// Adjusts the component's value. This is an optional command and is NOT supported by all ECUs.
/// This allows for long-term adjustments (Such as fuel trims) to be made to the ECU. The ECU
/// will retain the values even after a power reset.
pub fn long_term_adjust(&self, args: &[u8]) -> DiagServerResult<()> {
let mut a = vec![self.identifier, 0x08];
a.extend_from_slice(args);
self.server
.send_command_with_response(KwpCommand::InputOutputControlByLocalIdentifier, &a)?;
Ok(())
}
}