iso14229_1/
request.rs

1#![allow(unused_imports)]
2
3/* - Diagnostic and communication management functional unit - */
4mod session_ctrl;           // 0x10
5pub use session_ctrl::*;
6mod ecu_reset;              // 0x11
7pub use ecu_reset::*;
8mod security_access;        // 0x27
9pub use security_access::*;
10mod communication_ctrl;     // 0x28
11pub use communication_ctrl::*;
12#[cfg(any(feature = "std2020"))]
13mod authentication;         // 0x29
14#[cfg(any(feature = "std2020"))]
15pub use authentication::*;
16mod tester_present;         // 0x3E
17pub use tester_present::*;
18#[cfg(any(feature = "std2006", feature = "std2013"))]
19mod access_timing_param;    // 0x83
20#[cfg(any(feature = "std2006", feature = "std2013"))]
21pub use access_timing_param::*;
22mod secured_data_trans;     // 0x84
23pub use secured_data_trans::*;
24mod ctrl_dtc_setting;       // 0x85
25pub use ctrl_dtc_setting::*;
26mod response_on_event;      // 0x86
27pub use response_on_event::*;
28mod link_ctrl;              // 0x87
29pub use link_ctrl::*;
30
31/* - Data transmission functional unit - */
32mod read_did;               // 0x22
33pub use read_did::*;
34mod read_mem_by_addr;       // 0x23
35pub use read_mem_by_addr::*;
36mod read_scaling_did;       // 0x24
37pub use read_scaling_did::*;
38mod read_data_by_pid;       // 0x2A
39pub use read_data_by_pid::*;
40mod dynamically_define_did; // 0x2C
41pub use dynamically_define_did::*;
42mod write_did;              // 0x2E
43pub use write_did::*;
44mod write_mem_by_addr;      // 0x3D
45pub use write_mem_by_addr::*;
46
47/* - Stored data transmission functional unit - */
48mod clear_diagnostic_info;  // 0x14
49pub use clear_diagnostic_info::*;
50mod read_dtc_info;          // 0x19
51pub use read_dtc_info::*;
52
53/* - InputOutput control functional unit - */
54mod io_ctrl;                // 0x2F
55pub use io_ctrl::*;
56
57/* - Remote activation of routine functional unit - */
58mod routine_ctrl;           // 0x31
59pub use routine_ctrl::*;
60
61/* - Upload download functional unit - */
62mod request_load;           // 0x34 | 0x35
63pub use request_load::*;
64mod transfer_data;          // 0x36
65pub use transfer_data::*;
66mod request_transfer_exit;  // 0x37
67pub use request_transfer_exit::*;
68#[cfg(any(feature = "std2013", feature = "std2020"))]
69mod request_file_transfer;  // 0x38
70#[cfg(any(feature = "std2013", feature = "std2020"))]
71pub use request_file_transfer::*;
72
73use crate::{Configuration, error::Error, RequestData, Service, utils};
74
75#[derive(Debug, Copy, Clone)]
76pub struct SubFunction<F> {
77    function: F,
78    suppress_positive: Option<bool>,
79}
80
81impl<F: Copy> SubFunction<F> {
82    pub fn new(
83        function: F,
84        suppress_positive: Option<bool>,
85    ) -> Self {
86        Self {
87            function,
88            suppress_positive,
89        }
90    }
91
92    #[inline]
93    pub fn function(&self) -> F {
94        self.function
95    }
96
97    #[inline]
98    pub const fn is_suppress_positive(&self) -> Result<Option<bool>, Error> {
99        Ok(self.suppress_positive)
100    }
101}
102
103impl<F> Into<u8> for SubFunction<F>
104where
105    F: Into<u8> {
106    fn into(self) -> u8 {
107        if let Some(v) = self.suppress_positive {
108            if v {
109                return self.function.into() | 0x80
110            }
111        }
112
113        self.function.into()
114    }
115}
116
117#[derive(Debug, Clone)]
118pub struct Request<F> {
119    pub(crate) service: Service,
120    pub(crate) sub_func: Option<SubFunction<F>>,
121    pub(crate) data: Vec<u8>,
122}
123
124impl<F: Copy> Request<F> {
125    pub fn new(
126        service: Service,
127        sub_func: Option<SubFunction<F>>,
128        data: Vec<u8>,
129    ) -> Self {
130        Self {
131            service,
132            sub_func,
133            data,
134        }
135    }
136
137    #[inline]
138    pub fn service(&self) -> Service {
139        self.service
140    }
141
142    #[inline]
143    pub fn sub_function(&self) -> Option<SubFunction<F>> {
144        self.sub_func.clone()
145    }
146
147    #[inline]
148    pub fn raw_data(&self) -> &[u8] {
149        self.data.as_slice()
150    }
151
152    #[inline]
153    pub fn data<T: RequestData<SubFunc = F>>(&self, cfg: &Configuration) -> Result<T, Error> {
154        T::try_parse(self.data.as_slice(), match self.sub_func {
155            Some(v) => Some(v.function),
156            None => None,
157        }, cfg)
158    }
159}
160
161impl<F: Into<u8>> Into<Vec<u8>> for Request<F> {
162    fn into(mut self) -> Vec<u8> {
163        let mut result = vec![self.service.into(), ];
164        if let Some(sub_func) = self.sub_func {
165            result.push(sub_func.into());
166        }
167
168        result.append(&mut self.data);
169
170        result
171    }
172}
173
174impl<F: TryFrom<u8, Error = Error> + Copy> TryFrom<Vec<u8>> for Request<F> {
175    type Error = Error;
176    fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> {
177        let data_len = data.len();
178        utils::data_length_check(data_len, 1, false)?;
179
180        let mut offset = 0;
181        let service = Service::try_from(data[offset])?;
182        offset += 1;
183        match service {
184            Service::SessionCtrl |
185            Service::ECUReset |
186            Service::SecurityAccess |
187            Service::CommunicationCtrl |
188            Service::ReadDTCInfo |
189            Service::RoutineCtrl |
190            Service::CtrlDTCSetting |
191            Service::TesterPresent |
192            Service::LinkCtrl |
193            Service::DynamicalDefineDID => {
194                utils::data_length_check(data_len, offset + 1, false)?;
195                let (suppress_positive, sub_func) = utils::peel_suppress_positive(data[offset]);
196                let sub_func = SubFunction::new(F::try_from(sub_func)?, Some(suppress_positive));
197
198                offset += 1;
199                let data = data[offset..].to_vec();
200
201                Ok(Request::new(service, Some(sub_func), data))
202            },
203            Service::ClearDiagnosticInfo |
204            Service::ReadDID |
205            Service::ReadMemByAddr |
206            Service::ReadScalingDID |
207            Service::ReadDataByPeriodId |
208            Service::WriteDID |
209            Service::IOCtrl |
210            Service::RequestDownload |
211            Service::RequestUpload |
212            Service::TransferData |
213            Service::RequestTransferExit |
214            Service::WriteMemByAddr |
215            Service::SecuredDataTrans |
216            Service::ResponseOnEvent => {
217                Ok(Self::new(service, None, data[offset..].to_vec()))
218            },
219            #[cfg(any(feature = "std2020"))]
220            Service::Authentication => {
221                utils::data_length_check(data_len, offset + 1, false)?;
222                let (suppress_positive, sub_func) = utils::peel_suppress_positive(data[offset]);
223                let sub_func = SubFunction::new(F::try_from(sub_func)?, Some(suppress_positive));
224
225                offset += 1;
226                let data = data[offset..].to_vec();
227
228                Ok(Request::new(service, Some(sub_func), data))
229            },
230            #[cfg(any(feature = "std2013", feature = "std2020"))]
231            Service::RequestFileTransfer => {
232                utils::data_length_check(data_len, offset + 1, false)?;
233                let (suppress_positive, sub_func) = utils::peel_suppress_positive(data[offset]);
234                let sub_func = SubFunction::new(F::try_from(sub_func)?, Some(suppress_positive));
235
236                offset += 1;
237                let data = data[offset..].to_vec();
238
239                Ok(Request::new(service, Some(sub_func), data))
240            },
241            #[cfg(any(feature = "std2006", feature = "std2013"))]
242            Service::AccessTimingParam => {
243                utils::data_length_check(data_len, offset + 1, false)?;
244                let (suppress_positive, sub_func) = utils::peel_suppress_positive(data[offset]);
245                let sub_func = SubFunction::new(F::try_from(sub_func)?, Some(suppress_positive));
246
247                offset += 1;
248                let data = data[offset..].to_vec();
249
250                Ok(Request::new(service, Some(sub_func), data))
251            },
252            Service::NRC => Err(Error::OtherError("got an NRC code from request data".into())),
253        }
254    }
255}