1use crate::{Configuration, DTCReportType, Error, Placeholder, RequestData, Service, utils};
5
6#[derive(Debug, Clone)]
7pub struct DTCExtDataRecord {
8 pub number: u8,
9 pub data: Vec<u8>,
10}
11
12#[derive(Debug, Clone)]
13pub enum DTCInfo {
14 ReportNumberOfDTCByStatusMask(u8), ReportDTCByStatusMask(u8), #[cfg(any(feature = "std2006", feature = "std2013"))]
17 ReportMirrorMemoryDTCByStatusMask(u8), #[cfg(any(feature = "std2006", feature = "std2013"))]
19 ReportNumberOfMirrorMemoryDTCByStatusMask(u8), #[cfg(any(feature = "std2006", feature = "std2013"))]
21 ReportNumberOfEmissionsOBDDTCByStatusMask(u8), #[cfg(any(feature = "std2006", feature = "std2013"))]
23 ReportEmissionsOBDDTCByStatusMask(u8), ReportDTCSnapshotIdentification, ReportDTCSnapshotRecordByDTCNumber { mask_record: utils::U24,
27 record_num: u8,
28 },
29 ReportDTCStoredDataByRecordNumber { stored_num: u8,
31 },
32 #[cfg(any(feature = "std2006", feature = "std2020"))]
33 ReportDTCExtDataRecordByDTCNumber { mask_record: utils::U24,
35 extra_num: u8,
36 },
37 #[cfg(any(feature = "std2006", feature = "std2013"))]
38 ReportMirrorMemoryDTCExtDataRecordByDTCNumber { mask_record: utils::U24,
40 extra_num: u8,
41 },
42 ReportNumberOfDTCBySeverityMaskRecord { severity_mask: u8,
44 status_mask: u8,
45 },
46 ReportDTCBySeverityMaskRecord { severity_mask: u8,
48 status_mask: u8,
49 },
50 ReportSeverityInformationOfDTC { mask_record: utils::U24,
52 },
53 ReportSupportedDTC, ReportFirstTestFailedDTC, ReportFirstConfirmedDTC, ReportMostRecentTestFailedDTC, ReportMostRecentConfirmedDTC, ReportDTCFaultDetectionCounter, ReportDTCWithPermanentStatus, #[cfg(any(feature = "std2013", feature = "std2020"))]
61 ReportDTCExtDataRecordByRecordNumber { extra_num: u8, },
64 #[cfg(any(feature = "std2013", feature = "std2020"))]
65 ReportUserDefMemoryDTCByStatusMask { status_mask: u8,
67 mem_selection: u8,
68 },
69 #[cfg(any(feature = "std2013", feature = "std2020"))]
70 ReportUserDefMemoryDTCSnapshotRecordByDTCNumber { mask_record: utils::U24,
72 record_num: u8,
73 mem_selection: u8,
74 },
75 #[cfg(any(feature = "std2013", feature = "std2020"))]
76 ReportUserDefMemoryDTCExtDataRecordByDTCNumber { mask_record: utils::U24,
78 extra_num: u8,
79 mem_selection: u8,
80 },
81 #[cfg(any(feature = "std2020"))]
82 ReportSupportedDTCExtDataRecord { extra_num: u8, },
85 #[cfg(any(feature = "std2013", feature = "std2020"))]
86 ReportWWHOBDDTCByMaskRecord { func_gid: u8, status_mask: u8,
89 severity_mask: u8,
90 },
91 #[cfg(any(feature = "std2013", feature = "std2020"))]
92 ReportWWHOBDDTCWithPermanentStatus { func_gid: u8, },
95 #[cfg(any(feature = "std2020"))]
96 ReportDTCInformationByDTCReadinessGroupIdentifier { func_gid: u8, readiness_gid: u8, },
100}
101
102impl RequestData for DTCInfo {
103 type SubFunc = DTCReportType;
104 fn try_parse(data: &[u8], sub_func: Option<Self::SubFunc>, _: &Configuration) -> Result<Self, Error> {
105 match sub_func {
106 Some(v) => {
107 let data_len = data.len();
108 let mut offset = 0;
109
110 match v {
111 DTCReportType::ReportNumberOfDTCByStatusMask => {
112 utils::data_length_check(data_len, offset + 1, true)?;
113
114 Ok(Self::ReportNumberOfDTCByStatusMask(data[offset]))
115 },
116 DTCReportType::ReportDTCByStatusMask => {
117 utils::data_length_check(data_len, offset + 1, true)?;
118
119 Ok(Self::ReportDTCByStatusMask(data[offset]))
120 },
121 #[cfg(any(feature = "std2006", feature = "std2013"))]
122 DTCReportType::ReportMirrorMemoryDTCByStatusMask => {
123 utils::data_length_check(data_len, offset + 1, true)?;
124
125 Ok(Self::ReportMirrorMemoryDTCByStatusMask(data[offset]))
126 },
127 #[cfg(any(feature = "std2006", feature = "std2013"))]
128 DTCReportType::ReportNumberOfMirrorMemoryDTCByStatusMask => {
129 utils::data_length_check(data_len, offset + 1, true)?;
130
131 Ok(Self::ReportNumberOfMirrorMemoryDTCByStatusMask(data[offset]))
132 },
133 #[cfg(any(feature = "std2006", feature = "std2013"))]
134 DTCReportType::ReportNumberOfEmissionsOBDDTCByStatusMask => {
135 utils::data_length_check(data_len, offset + 1, true)?;
136
137 Ok(Self::ReportNumberOfEmissionsOBDDTCByStatusMask(data[offset]))
138 },
139 #[cfg(any(feature = "std2006", feature = "std2013"))]
140 DTCReportType::ReportEmissionsOBDDTCByStatusMask => {
141 utils::data_length_check(data_len, offset + 1, true)?;
142
143 Ok(Self::ReportEmissionsOBDDTCByStatusMask(data[offset]))
144 },
145 DTCReportType::ReportDTCSnapshotIdentification =>
146 Ok(Self::ReportDTCSnapshotIdentification),
147 DTCReportType::ReportDTCSnapshotRecordByDTCNumber => {
148 utils::data_length_check(data_len, offset + 4, true)?;
149
150 let mask_record = utils::U24::from_be_bytes([0, data[offset], data[offset + 1], data[offset + 2]]);
151 offset += 3;
152 let record_num = data[offset];
153
154 Ok(Self::ReportDTCSnapshotRecordByDTCNumber {
155 mask_record,
156 record_num,
157 })
158 }
159 DTCReportType::ReportDTCStoredDataByRecordNumber => {
160 utils::data_length_check(data_len, offset + 1, true)?;
161
162 Ok(Self::ReportDTCStoredDataByRecordNumber {
163 stored_num: data[offset],
164 })
165 },
166 #[cfg(any(feature = "std2006", feature = "std2020"))]
167 DTCReportType::ReportDTCExtDataRecordByDTCNumber => {
168 utils::data_length_check(data_len, offset + 4, true)?;
169
170 let mask_record = utils::U24::from_be_bytes([0, data[offset], data[offset + 1], data[offset + 2]]);
171 offset += 3;
172 let extra_num = data[offset];
173
174 Ok(Self::ReportDTCExtDataRecordByDTCNumber {
175 mask_record,
176 extra_num,
177 })
178 },
179 #[cfg(any(feature = "std2006", feature = "std2013"))]
180 DTCReportType::ReportMirrorMemoryDTCExtDataRecordByDTCNumber => {
181 utils::data_length_check(data_len, offset + 4, true)?;
182
183 let mask_record = utils::U24::from_be_bytes([0, data[offset], data[offset + 1], data[offset + 2]]);
184 offset += 3;
185 let extra_num = data[offset];
186
187 Ok(Self::ReportMirrorMemoryDTCExtDataRecordByDTCNumber {
188 mask_record,
189 extra_num,
190 })
191 },
192 DTCReportType::ReportNumberOfDTCBySeverityMaskRecord => {
193 utils::data_length_check(data_len, offset + 2, true)?;
194
195 let severity_mask = data[offset];
196 offset += 1;
197 let status_mask = data[offset];
198
199 Ok(Self::ReportNumberOfDTCBySeverityMaskRecord {
200 severity_mask,
201 status_mask,
202 })
203 },
204 DTCReportType::ReportDTCBySeverityMaskRecord => {
205 utils::data_length_check(data_len, offset + 2, true)?;
206
207 let severity_mask = data[offset];
208 offset += 1;
209 let status_mask = data[offset];
210
211 Ok(Self::ReportDTCBySeverityMaskRecord {
212 severity_mask,
213 status_mask,
214 })
215 },
216 DTCReportType::ReportSeverityInformationOfDTC => {
217 utils::data_length_check(data_len, offset + 3, true)?;
218
219 let mask_record = utils::U24::from_be_bytes([0, data[offset], data[offset + 1], data[offset + 2]]);
220
221 Ok(Self::ReportSeverityInformationOfDTC {
222 mask_record,
223 })
224 },
225 DTCReportType::ReportSupportedDTC =>
226 Ok(Self::ReportSupportedDTC),
227 DTCReportType::ReportFirstTestFailedDTC =>
228 Ok(Self::ReportFirstTestFailedDTC),
229 DTCReportType::ReportFirstConfirmedDTC =>
230 Ok(Self::ReportFirstConfirmedDTC),
231 DTCReportType::ReportMostRecentTestFailedDTC =>
232 Ok(Self::ReportMostRecentTestFailedDTC),
233 DTCReportType::ReportMostRecentConfirmedDTC =>
234 Ok(Self::ReportMostRecentConfirmedDTC),
235 DTCReportType::ReportDTCFaultDetectionCounter =>
236 Ok(Self::ReportDTCFaultDetectionCounter),
237 DTCReportType::ReportDTCWithPermanentStatus =>
238 Ok(Self::ReportDTCWithPermanentStatus),
239 #[cfg(any(feature = "std2013", feature = "std2020"))]
240 DTCReportType::ReportDTCExtDataRecordByRecordNumber => {
241 utils::data_length_check(data_len, offset + 1, true)?;
242
243 let extra_num = data[offset];
244 if extra_num > 0xEF {
245 return Err(Error::InvalidData(hex::encode(data)));
246 }
247
248 Ok(Self::ReportDTCExtDataRecordByRecordNumber {
249 extra_num,
250 })
251 },
252 #[cfg(any(feature = "std2013", feature = "std2020"))]
253 DTCReportType::ReportUserDefMemoryDTCByStatusMask => {
254 utils::data_length_check(data_len, offset + 2, true)?;
255
256 Ok(Self::ReportUserDefMemoryDTCByStatusMask {
257 status_mask: data[offset],
258 mem_selection: data[offset + 1],
259 })
260 },
261 #[cfg(any(feature = "std2013", feature = "std2020"))]
262 DTCReportType::ReportUserDefMemoryDTCSnapshotRecordByDTCNumber => {
263 utils::data_length_check(data_len, offset + 5, true)?;
264
265 let mask_record = utils::U24::from_be_bytes([0, data[offset], data[offset + 1], data[offset + 2]]);
266 offset += 3;
267
268 Ok(Self::ReportUserDefMemoryDTCSnapshotRecordByDTCNumber {
269 mask_record,
270 record_num: data[offset],
271 mem_selection: data[offset + 1],
272 })
273 },
274 #[cfg(any(feature = "std2013", feature = "std2020"))]
275 DTCReportType::ReportUserDefMemoryDTCExtDataRecordByDTCNumber => {
276 utils::data_length_check(data_len, offset + 5, true)?;
277
278 let mask_record = utils::U24::from_be_bytes([0, data[offset], data[offset + 1], data[offset + 2]]);
279 offset += 3;
280
281 Ok(Self::ReportUserDefMemoryDTCExtDataRecordByDTCNumber {
282 mask_record,
283 extra_num: data[offset],
284 mem_selection: data[offset + 1],
285 })
286 },
287 #[cfg(any(feature = "std2020"))]
288 DTCReportType::ReportSupportedDTCExtDataRecord => {
289 utils::data_length_check(data_len, offset + 1, true)?;
290
291 let extra_num = data[offset];
292 if extra_num < 1 || extra_num > 0xFD {
293 return Err(Error::InvalidData(hex::encode(data)));
294 }
295
296 Ok(Self::ReportSupportedDTCExtDataRecord {
297 extra_num,
298 })
299 },
300 #[cfg(any(feature = "std2013", feature = "std2020"))]
301 DTCReportType::ReportWWHOBDDTCByMaskRecord => {
302 utils::data_length_check(data_len, offset + 3, true)?;
303
304 let func_gid = data[offset];
305 offset += 1;
306 if func_gid > 0xFE {
307 return Err(Error::InvalidData(hex::encode(data)));
308 }
309
310 Ok(Self::ReportWWHOBDDTCByMaskRecord {
311 func_gid,
312 status_mask: data[offset],
313 severity_mask: data[offset + 1],
314 })
315 },
316 #[cfg(any(feature = "std2013", feature = "std2020"))]
317 DTCReportType::ReportWWHOBDDTCWithPermanentStatus => {
318 utils::data_length_check(data_len, offset + 1, true)?;
319
320 let func_gid = data[offset];
321 if func_gid > 0xFE {
322 return Err(Error::InvalidData(hex::encode(data)));
323 }
324
325 Ok(Self::ReportWWHOBDDTCWithPermanentStatus {
326 func_gid,
327 })
328 },
329 #[cfg(any(feature = "std2020"))]
330 DTCReportType::ReportDTCInformationByDTCReadinessGroupIdentifier => {
331 utils::data_length_check(data_len, offset + 2, true)?;
332
333 let func_gid = data[offset];
334 offset += 1;
335 if func_gid > 0xFE {
336 return Err(Error::InvalidData(hex::encode(data)));
337 }
338
339 let readiness_gid = data[offset];
340 if readiness_gid > 0xFE {
341 return Err(Error::InvalidData(hex::encode(data)));
342 }
343
344 Ok(Self::ReportDTCInformationByDTCReadinessGroupIdentifier {
345 func_gid,
346 readiness_gid,
347 })
348 },
349 }
350 },
351 None => panic!("Sub-function required"),
352 }
353 }
354 #[inline]
355 fn to_vec(self, _: &Configuration) -> Vec<u8> {
356 self.into()
357 }
358}
359
360impl Into<Vec<u8>> for DTCInfo {
361 fn into(self) -> Vec<u8> {
362 let mut result = Vec::new();
363
364 match self {
365 Self::ReportNumberOfDTCByStatusMask(v) => result.push(v),
366 Self::ReportDTCByStatusMask(v) => result.push(v),
367 #[cfg(any(feature = "std2006", feature = "std2013"))]
368 Self::ReportMirrorMemoryDTCByStatusMask(v) => result.push(v),
369 #[cfg(any(feature = "std2006", feature = "std2013"))]
370 Self::ReportNumberOfMirrorMemoryDTCByStatusMask(v) => result.push(v),
371 #[cfg(any(feature = "std2006", feature = "std2013"))]
372 Self::ReportNumberOfEmissionsOBDDTCByStatusMask(v) => result.push(v),
373 #[cfg(any(feature = "std2006", feature = "std2013"))]
374 Self::ReportEmissionsOBDDTCByStatusMask(v) => result.push(v),
375 Self::ReportDTCSnapshotIdentification => {},
376 Self::ReportDTCSnapshotRecordByDTCNumber {
377 mask_record,
378 record_num,
379 } => {
380 result.append(&mut mask_record.into());
381 result.push(record_num);
382 },
383 Self::ReportDTCStoredDataByRecordNumber { stored_num } => result.push(stored_num),
384 Self::ReportDTCExtDataRecordByDTCNumber {
385 mask_record,
386 extra_num,
387 } => {
388 result.append(&mut mask_record.into());
389 result.push(extra_num);
390 },
391 #[cfg(any(feature = "std2006", feature = "std2013"))]
392 Self::ReportMirrorMemoryDTCExtDataRecordByDTCNumber {
393 mask_record,
394 extra_num,
395 } => {
396 result.append(&mut mask_record.into());
397 result.push(extra_num);
398 },
399 Self::ReportNumberOfDTCBySeverityMaskRecord {
400 severity_mask,
401 status_mask,
402 } => {
403 result.push(severity_mask);
404 result.push(status_mask);
405 },
406 Self::ReportDTCBySeverityMaskRecord {
407 severity_mask,
408 status_mask,
409 } => {
410 result.push(severity_mask);
411 result.push(status_mask);
412 },
413 Self::ReportSeverityInformationOfDTC { mask_record } => result.append(&mut mask_record.into()),
414 Self::ReportSupportedDTC => {},
415 Self::ReportFirstTestFailedDTC => {},
416 Self::ReportFirstConfirmedDTC => {},
417 Self::ReportMostRecentTestFailedDTC => {},
418 Self::ReportMostRecentConfirmedDTC => {},
419 Self::ReportDTCFaultDetectionCounter => {},
420 Self::ReportDTCWithPermanentStatus => {},
421 #[cfg(any(feature = "std2013", feature = "std2020"))]
422 Self::ReportDTCExtDataRecordByRecordNumber { extra_num } => result.push(extra_num),
423 #[cfg(any(feature = "std2013", feature = "std2020"))]
424 Self::ReportUserDefMemoryDTCByStatusMask {
425 status_mask,
426 mem_selection } => {
427 result.push(status_mask);
428 result.push(mem_selection);
429 },
430 #[cfg(any(feature = "std2013", feature = "std2020"))]
431 Self::ReportUserDefMemoryDTCSnapshotRecordByDTCNumber {
432 mask_record,
433 record_num,
434 mem_selection
435 } => {
436 result.append(&mut mask_record.into());
437 result.push(record_num);
438 result.push(mem_selection);
439 },
440 #[cfg(any(feature = "std2013", feature = "std2020"))]
441 Self::ReportUserDefMemoryDTCExtDataRecordByDTCNumber {
442 mask_record,
443 extra_num,
444 mem_selection
445 } => {
446 result.append(&mut mask_record.into());
447 result.push(extra_num);
448 result.push(mem_selection);
449 },
450 #[cfg(any(feature = "std2020"))]
451 Self::ReportSupportedDTCExtDataRecord { extra_num } => result.push(extra_num),
452 #[cfg(any(feature = "std2013", feature = "std2020"))]
453 Self::ReportWWHOBDDTCByMaskRecord { func_gid, status_mask, severity_mask } => {
454 result.push(func_gid);
455 result.push(status_mask);
456 result.push(severity_mask);
457 },
458 #[cfg(any(feature = "std2013", feature = "std2020"))]
459 Self::ReportWWHOBDDTCWithPermanentStatus { func_gid } => result.push(func_gid),
460 #[cfg(any(feature = "std2020"))]
461 Self::ReportDTCInformationByDTCReadinessGroupIdentifier { func_gid, readiness_gid } => {
462 result.push(func_gid);
463 result.push(readiness_gid);
464 },
465 }
466
467 result
468 }
469}
470