iso14229_1/request/
read_dtc_info.rs

1//! request of Service 19
2
3
4use 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),      // 0x01
15    ReportDTCByStatusMask(u8),              // 0x02
16    #[cfg(any(feature = "std2006", feature = "std2013"))]
17    ReportMirrorMemoryDTCByStatusMask(u8),          // 0x0F
18    #[cfg(any(feature = "std2006", feature = "std2013"))]
19    ReportNumberOfMirrorMemoryDTCByStatusMask(u8),  // 0x11
20    #[cfg(any(feature = "std2006", feature = "std2013"))]
21    ReportNumberOfEmissionsOBDDTCByStatusMask(u8),  // 0x12
22    #[cfg(any(feature = "std2006", feature = "std2013"))]
23    ReportEmissionsOBDDTCByStatusMask(u8),          // 0x13
24    ReportDTCSnapshotIdentification,       // 0x03
25    ReportDTCSnapshotRecordByDTCNumber {    // 0x04
26        mask_record: utils::U24,
27        record_num: u8,
28    },
29    ReportDTCStoredDataByRecordNumber {     // 0x05
30        stored_num: u8,
31    },
32    #[cfg(any(feature = "std2006", feature = "std2020"))]
33    ReportDTCExtDataRecordByDTCNumber {     // 0x06
34        mask_record: utils::U24,
35        extra_num: u8,
36    },
37    #[cfg(any(feature = "std2006", feature = "std2013"))]
38    ReportMirrorMemoryDTCExtDataRecordByDTCNumber { // 0x10
39        mask_record: utils::U24,
40        extra_num: u8,
41    },
42    ReportNumberOfDTCBySeverityMaskRecord { // 0x07
43        severity_mask: u8,
44        status_mask: u8,
45    },
46    ReportDTCBySeverityMaskRecord {         // 0x08
47        severity_mask: u8,
48        status_mask: u8,
49    },
50    ReportSeverityInformationOfDTC {        // 0x09
51        mask_record: utils::U24,
52    },
53    ReportSupportedDTC,                     // 0x0A
54    ReportFirstTestFailedDTC,               // 0x0B
55    ReportFirstConfirmedDTC,                // 0x0C
56    ReportMostRecentTestFailedDTC,          // 0x0D
57    ReportMostRecentConfirmedDTC,           // 0x0E
58    ReportDTCFaultDetectionCounter,         // 0x14
59    ReportDTCWithPermanentStatus,           // 0x15
60    #[cfg(any(feature = "std2013", feature = "std2020"))]
61    ReportDTCExtDataRecordByRecordNumber {  // 0x16
62        extra_num: u8,  // 0x00~0xEF
63    },
64    #[cfg(any(feature = "std2013", feature = "std2020"))]
65    ReportUserDefMemoryDTCByStatusMask {    // 0x17
66        status_mask: u8,
67        mem_selection: u8,
68    },
69    #[cfg(any(feature = "std2013", feature = "std2020"))]
70    ReportUserDefMemoryDTCSnapshotRecordByDTCNumber {   // 0x18
71        mask_record: utils::U24,
72        record_num: u8,
73        mem_selection: u8,
74    },
75    #[cfg(any(feature = "std2013", feature = "std2020"))]
76    ReportUserDefMemoryDTCExtDataRecordByDTCNumber {    // 0x19
77        mask_record: utils::U24,
78        extra_num: u8,
79        mem_selection: u8,
80    },
81    #[cfg(any(feature = "std2020"))]
82    ReportSupportedDTCExtDataRecord {       // 0x1A
83        extra_num: u8,  // 0x01~0xFD
84    },
85    #[cfg(any(feature = "std2013", feature = "std2020"))]
86    ReportWWHOBDDTCByMaskRecord {           // 0x42
87        func_gid: u8, // 0x00~0xFE
88        status_mask: u8,
89        severity_mask: u8,
90    },
91    #[cfg(any(feature = "std2013", feature = "std2020"))]
92    ReportWWHOBDDTCWithPermanentStatus {    // 0x55
93        func_gid: u8, // 0x00~0xFE
94    },
95    #[cfg(any(feature = "std2020"))]
96    ReportDTCInformationByDTCReadinessGroupIdentifier { // 0x56
97        func_gid: u8, // 0x00~0xFE
98        readiness_gid: u8, // 0x00~0xFE
99    },
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