1#![allow(unused_imports)]
2
3mod session_ctrl; pub use session_ctrl::*;
6mod ecu_reset; pub use ecu_reset::*;
8mod security_access; pub use security_access::*;
10mod communication_ctrl; pub use communication_ctrl::*;
12#[cfg(any(feature = "std2020"))]
13mod authentication; #[cfg(any(feature = "std2020"))]
15pub use authentication::*;
16mod tester_present; pub use tester_present::*;
18#[cfg(any(feature = "std2006", feature = "std2013"))]
19mod access_timing_param; #[cfg(any(feature = "std2006", feature = "std2013"))]
21pub use access_timing_param::*;
22mod secured_data_trans; pub use secured_data_trans::*;
24mod ctrl_dtc_setting; pub use ctrl_dtc_setting::*;
26mod response_on_event; pub use response_on_event::*;
28mod link_ctrl; pub use link_ctrl::*;
30
31mod read_did; pub use read_did::*;
34mod read_mem_by_addr; pub use read_mem_by_addr::*;
36mod read_scaling_did; pub use read_scaling_did::*;
38mod read_data_by_pid; pub use read_data_by_pid::*;
40mod dynamically_define_did; pub use dynamically_define_did::*;
42mod write_did; pub use write_did::*;
44mod write_mem_by_addr; pub use write_mem_by_addr::*;
46
47mod clear_diagnostic_info; pub use clear_diagnostic_info::*;
50mod read_dtc_info; pub use read_dtc_info::*;
52
53mod io_ctrl; pub use io_ctrl::*;
56
57mod routine_ctrl; pub use routine_ctrl::*;
60
61mod request_load; pub use request_load::*;
64mod transfer_data; pub use transfer_data::*;
66mod request_transfer_exit; pub use request_transfer_exit::*;
68#[cfg(any(feature = "std2013", feature = "std2020"))]
69mod request_file_transfer; #[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}