-
-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathkwp.rs
117 lines (107 loc) · 4.41 KB
/
kwp.rs
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use automotive_diag::kwp2000::{KwpSessionType, KwpSessionTypeByte};
use std::{time::Duration, sync::{Arc, RwLock}};
use ecu_diagnostics::{
channel::{self, IsoTPSettings},
dynamic_diag::{
DiagProtocol, DiagServerAdvancedOptions, DiagServerBasicOptions, DiagSessionMode,
DynamicDiagSession, TimeoutConfig, DiagServerEmptyLogger,
},
hardware::{self, HardwareScanner, Hardware},
kwp2000::Kwp2000Protocol,
};
extern crate ecu_diagnostics;
fn ecu_waiting_hook() {
println!("Called hook! ECU is processing our request");
}
fn tx_ok_hook(data: &[u8]) {
println!(
"This {} long array was sent to the ECU OK!: {:02X?}",
data.len(),
data
);
}
fn print_diag_mode(server: &DynamicDiagSession) {
if let Some(mode) = server.get_current_diag_mode() {
println!(
"ECU is currently in '{}' diagnostic mode (0x{:02X?}). Tester present being sent?: {}",
mode.name, mode.id, mode.tp_require
);
}
}
fn main() {
env_logger::init();
let dev = ecu_diagnostics::hardware::socketcan::SocketCanScanner::new();
let mut d = dev.open_device_by_name("can0").unwrap();
let isotp = d.create_iso_tp_channel().unwrap();
let mut protocol = Kwp2000Protocol::default();
println!("Diagnostic server is {}!", protocol.get_protocol_name());
// Register a custom diagnostic session with the protocol (Usually OEM specific)
protocol.register_session_type(DiagSessionMode {
id: 0x93,
tp_require: true,
name: "SuperSecretDiagMode".into(),
});
let mut diag_server = ecu_diagnostics::dynamic_diag::DynamicDiagSession::new_over_iso_tp(
protocol,
isotp,
IsoTPSettings {
// ISO-TP layer settings
block_size: 8,
st_min: 20,
extended_addresses: None,
pad_frame: true,
can_speed: 500_000,
can_use_ext_addr: false,
},
DiagServerBasicOptions {
// Basic server options
send_id: 0x07E1,
recv_id: 0x07E9,
timeout_cfg: TimeoutConfig {
read_timeout_ms: 2500,
write_timeout_ms: 2500,
},
},
Some(DiagServerAdvancedOptions {
// Advanced server options
global_tp_id: 0,
tester_present_interval_ms: 2000,
tester_present_require_response: true,
global_session_control: false,
tp_ext_id: None,
command_cooldown_ms: 100,
}),
DiagServerEmptyLogger{}
)
.unwrap();
// This call would work for KWP or UDS, not OBD2 as OBD2 has no form of 'session control'
if let Some(mode) = diag_server.get_current_diag_mode() {
println!(
"ECU is currently in '{}' diagnostic mode (0x{:02X?}). Tester present being sent?: {}",
mode.name, mode.id, mode.tp_require
);
}
// Register hook for when ECU responsds with RequestCorrectlyReceivedResponsePending
diag_server.register_waiting_hook(|| ecu_waiting_hook());
// Register hook for when our requests are sent to the ECU, but we have not got a response. Usually
// this can be used to just let the program know Tx was OK!
diag_server.register_send_complete_hook(|bytes| tx_ok_hook(bytes));
// Set diag session mode
let res = diag_server.kwp_set_session(KwpSessionType::ExtendedDiagnostics.into());
println!("Into extended diag mode result: {:?}", res);
// Now check diag session mode, should be extended
print_diag_mode(&diag_server);
let res = diag_server.kwp_set_session(KwpSessionTypeByte::from(0x93)); // Same ID as what we registered at the start
println!("Into special diag mode result: {:?}", res);
print_diag_mode(&diag_server);
println!("Reset result: {:?}", diag_server.kwp_reset_ecu(automotive_diag::kwp2000::ResetType::PowerOnReset));
print_diag_mode(&diag_server); // ECU should be in standard mode now as the ECU was rebooted
std::thread::sleep(Duration::from_millis(500));
println!("Read op: {:?}", diag_server.kwp_enable_normal_message_transmission());
print_diag_mode(&diag_server); // ECU will automatically be put into 0x93 mode
// (Last requested mode as enable_normal_message_transmission cannot be ran in standard mode)
loop {
// TP will be sent in this mode forever
std::thread::sleep(Duration::from_millis(1000));
}
}