1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\r
6 * This source code is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the GNU General Public License version 2 as published by the
\r
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
\r
10 * This program is distributed in the hope that it will be useful, but
\r
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
\r
14 * -------------------------------- Arctic Core ------------------------------*/
\r
19 #include "Dcm_Cfg.h"
\r
21 #include "Dcm_Internal.h"
\r
27 #define ZERO_SUB_FUNCTION 0x00
\r
32 #define BYTES_TO_DTC(hb, mb, lb) (((hb) << 16) | ((mb) << 8) | (lb))
\r
33 #define DTC_HIGH_BYTE(dtc) (((dtc)>> 16) & 0xFF)
\r
34 #define DTC_MID_BYTE(dtc) (((dtc)>> 8) & 0xFF)
\r
35 #define DTC_LOW_BYTE(dtc) ((dtc) & 0xFF)
\r
39 boolean resetPending;
\r
40 PduIdType resetPduId;
\r
41 } DspUdsEcuResetDataType;
\r
43 static DspUdsEcuResetDataType dspUdsEcuResetData;
\r
47 boolean reqInProgress;
\r
48 Dcm_SecLevelType reqSecLevel;
\r
49 const Dcm_DspSecurityRowType *reqSecLevelRef;
\r
50 } DspUdsSecurityAccessDataType;
\r
52 static DspUdsSecurityAccessDataType dspUdsSecurityAccesData;
\r
57 dspUdsSecurityAccesData.reqInProgress = FALSE;
\r
58 dspUdsEcuResetData.resetPending = FALSE;
\r
68 boolean DspCheckSessionLevel(const Dcm_DspSessionRowType **sessionLevelRefTable)
\r
70 boolean returnStatus = TRUE;
\r
71 Dcm_SesCtrlType currentSession;
\r
73 DslGetSesCtrlType(¤tSession);
\r
74 while (((*sessionLevelRefTable)->DspSessionLevel != currentSession) && !(*sessionLevelRefTable)->Arc_EOL) {
\r
75 sessionLevelRefTable++;
\r
78 if ((*sessionLevelRefTable)->Arc_EOL) {
\r
79 returnStatus = FALSE;
\r
82 return returnStatus;
\r
86 boolean DspCheckSecurityLevel(const Dcm_DspSecurityRowType **securityLevelRefTable)
\r
88 boolean returnStatus = TRUE;
\r
89 Dcm_SecLevelType currentSecurityLevel;
\r
91 DslGetSecurityLevel(¤tSecurityLevel);
\r
92 while (((*securityLevelRefTable)->DspSecurityLevel != currentSecurityLevel) && !(*securityLevelRefTable)->Arc_EOL) {
\r
93 securityLevelRefTable++;
\r
95 if ((*securityLevelRefTable)->Arc_EOL) {
\r
96 returnStatus = FALSE;
\r
99 return returnStatus;
\r
103 Std_ReturnType AskApplicationForSessionPermission(Dcm_SesCtrlType newSessionLevel)
\r
105 Std_ReturnType returnCode = E_OK;
\r
106 const Dcm_DslSessionControlType *sesControl = DCM_Config.Dsl->DslSessionControl;
\r
107 Dcm_SesCtrlType currentSessionLevel;
\r
108 Std_ReturnType result;
\r
110 while (!sesControl->Arc_EOL && (returnCode != E_SESSION_NOT_ALLOWED)) {
\r
111 if (sesControl->GetSesChgPermission != NULL) {
\r
112 Dcm_GetSesCtrlType(¤tSessionLevel);
\r
113 result = sesControl->GetSesChgPermission(currentSessionLevel ,newSessionLevel);
\r
114 if (result != E_OK) {
\r
115 returnCode = result;
\r
125 void DspUdsDiagnosticSessionControl(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
128 const Dcm_DspSessionRowType *sessionRow = DCM_Config.Dsp->DspSession->DspSessionRow;
\r
129 Dcm_SesCtrlType reqSessionType;
\r
130 Std_ReturnType result;
\r
132 if (pduRxData->SduLength == 2) {
\r
133 reqSessionType = pduRxData->SduDataPtr[1];
\r
134 // Check if type exist in session table
\r
135 while ((sessionRow->DspSessionLevel != reqSessionType) && !sessionRow->Arc_EOL) {
\r
139 if (!sessionRow->Arc_EOL) {
\r
140 result = AskApplicationForSessionPermission(reqSessionType);
\r
141 if (result == E_OK) {
\r
142 DslSetSesCtrlType(reqSessionType); /** @req DCM311 **/
\r
143 // Create positive response
\r
144 /** @req DCM039.2 **/
\r
145 pduTxData->SduDataPtr[1] = reqSessionType;
\r
146 pduTxData->SduLength = 2;
\r
147 DsdDspProcessingDone(DCM_E_POSITIVERESPONSE); /** @req DCM269.2 **/
\r
150 // TODO: Add handling of special case of E_FORCE_RCRRP (Dcm138)
\r
151 DsdDspProcessingDone(DCM_E_CONDITIONSNOTCORRECT); /** @req DCM308 **/
\r
155 DsdDspProcessingDone(DCM_E_SUBFUNCTIONNOTSUPPORTED); /** @req DCM307 **/
\r
160 DsdDspProcessingDone(DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT); /** @req DCM272.1 **/
\r
165 void DspUdsEcuReset(const PduInfoType *pduRxData, PduIdType txPduId, PduInfoType *pduTxData)
\r
168 uint8 reqResetType;
\r
170 if (pduRxData->SduLength == 2) {
\r
171 reqResetType = pduRxData->SduDataPtr[1];
\r
173 switch (reqResetType)
\r
175 case 0x01: // Hard reset
\r
176 // TODO: Ask application for permission (Dcm373) (Dcm375) (Dcm377)
\r
178 // Schedule the reset
\r
179 dspUdsEcuResetData.resetPending = TRUE;
\r
180 dspUdsEcuResetData.resetPduId = txPduId;
\r
182 // Create positive response
\r
183 /** @req DCM039.1 **/
\r
184 pduTxData->SduDataPtr[1] = reqResetType;
\r
185 pduTxData->SduLength = 2;
\r
186 DsdDspProcessingDone(DCM_E_POSITIVERESPONSE); /** @req DCM269.3 **/
\r
190 DsdDspProcessingDone(DCM_E_SUBFUNCTIONNOTSUPPORTED); /** @req DCM273.3 **/
\r
196 DsdDspProcessingDone(DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT); /** @req DCM272.3 **/
\r
201 void DspUdsClearDiagnosticInformation(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
204 Dem_ReturnClearDTCType result;
\r
206 if (pduRxData->SduLength == 4) {
\r
207 dtc = BYTES_TO_DTC(pduRxData->SduDataPtr[1], pduRxData->SduDataPtr[2], pduRxData->SduDataPtr[3]);
\r
209 result = Dem_ClearDTC(dtc, DEM_DTC_KIND_ALL_DTCS, DEM_DTC_ORIGIN_PRIMARY_MEMORY);
\r
214 // Create positive response
\r
215 /** @req DCM039.1 **/
\r
216 pduTxData->SduLength = 1;
\r
217 DsdDspProcessingDone(DCM_E_POSITIVERESPONSE); /** @req DCM269.4 **/
\r
221 DsdDspProcessingDone(DCM_E_REQUESTOUTOFRANGE);
\r
227 DsdDspProcessingDone(DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT); /** @req DCM272.1 **/
\r
232 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x01_0x07_0x11_0x12(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
237 uint8 dtcStatusAvailabilityMask;
\r
238 uint8 dtcFormatIdentifier;
\r
239 uint8 dtcCountHighByte;
\r
240 uint8 dtcCountLowByte;
\r
243 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
244 Dem_ReturnSetDTCFilterType setDtcFilterResult;
\r
246 // Setup the DTC filter
\r
247 switch (pduRxData->SduDataPtr[1]) /** @reg DCM293 **/
\r
249 case 0x01: // reportNumberOfDTCByStatusMask
\r
250 setDtcFilterResult = Dem_SetDTCFilter(pduRxData->SduDataPtr[2], DEM_DTC_KIND_ALL_DTCS, DEM_DTC_ORIGIN_PRIMARY_MEMORY, DEM_FILTER_WITH_SEVERITY_NO, VALUE_IS_NOT_USED, DEM_FILTER_FOR_FDC_NO);
\r
253 case 0x07: // reportNumberOfDTCBySeverityMaskRecord
\r
254 setDtcFilterResult = Dem_SetDTCFilter(pduRxData->SduDataPtr[3], DEM_DTC_KIND_ALL_DTCS, DEM_DTC_ORIGIN_PRIMARY_MEMORY, DEM_FILTER_WITH_SEVERITY_YES, pduRxData->SduDataPtr[2], DEM_FILTER_FOR_FDC_NO);
\r
257 case 0x11: // reportNumberOfMirrorMemoryDTCByStatusMask
\r
258 setDtcFilterResult = Dem_SetDTCFilter(pduRxData->SduDataPtr[2], DEM_DTC_KIND_ALL_DTCS, DEM_DTC_ORIGIN_MIRROR_MEMORY, DEM_FILTER_WITH_SEVERITY_NO, VALUE_IS_NOT_USED, DEM_FILTER_FOR_FDC_NO);
\r
261 case 0x12: // reportNumberOfEmissionRelatedOBDDTCByStatusMask
\r
262 setDtcFilterResult = Dem_SetDTCFilter(pduRxData->SduDataPtr[2], DEM_DTC_KIND_EMISSON_REL_DTCS, DEM_DTC_ORIGIN_PRIMARY_MEMORY, DEM_FILTER_WITH_SEVERITY_NO, VALUE_IS_NOT_USED, DEM_FILTER_FOR_FDC_NO);
\r
266 setDtcFilterResult = DEM_WRONG_FILTER;
\r
267 #if (DCM_DEV_ERROR_DETECT == STD_ON)
\r
268 Det_ReportError(MODULE_ID_DCM, 0, DCM_UDS_READ_DTC_INFO, DCM_E_UNEXPECTED_PARAM);
\r
273 if (setDtcFilterResult == DEM_FILTER_ACCEPTED) {
\r
274 uint16 numberOfFilteredDtc;
\r
275 uint8 dtcStatusMask;
\r
276 TxDataType *txData = (TxDataType*)pduTxData->SduDataPtr;
\r
278 /** @reg DCM376 **/
\r
279 Dem_GetNumberOfFilteredDtc(&numberOfFilteredDtc);
\r
280 Dem_GetDTCStatusAvailabilityMask(&dtcStatusMask);
\r
282 // Create positive response (ISO 14229-1 table 251)
\r
283 /** @req DCM039.0x19 **/
\r
284 txData->reportType = pduRxData->SduDataPtr[1]; // reportType
\r
285 txData->dtcStatusAvailabilityMask = dtcStatusMask; // DTCStatusAvailabilityMask
\r
286 txData->dtcFormatIdentifier = Dem_GetTranslationType(); // DTCFormatIdentifier
\r
287 txData->dtcCountHighByte = (numberOfFilteredDtc >> 8); // DTCCount high byte
\r
288 txData->dtcCountLowByte = (numberOfFilteredDtc & 0xFF); // DTCCount low byte
\r
289 pduTxData->SduLength = 6;
\r
292 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
295 return responseCode;
\r
299 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x02_0x0A_0x0F_0x13_0x15(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
301 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
302 Dem_ReturnSetDTCFilterType setDtcFilterResult;
\r
306 uint8 dtcMiddleByte;
\r
309 } dtcAndStatusRecordType;
\r
314 uint8 dtcStatusAvailabilityMask;
\r
315 dtcAndStatusRecordType dtcAndStatusRecord[];
\r
318 // Setup the DTC filter
\r
319 switch (pduRxData->SduDataPtr[1]) /** @reg DCM378 **/
\r
321 case 0x02: // reportDTCByStatusMask
\r
322 setDtcFilterResult = Dem_SetDTCFilter(pduRxData->SduDataPtr[2], DEM_DTC_KIND_ALL_DTCS, DEM_DTC_ORIGIN_PRIMARY_MEMORY, DEM_FILTER_WITH_SEVERITY_NO, VALUE_IS_NOT_USED, DEM_FILTER_FOR_FDC_NO);
\r
325 case 0x0A: // reportSupportedDTC
\r
326 setDtcFilterResult = Dem_SetDTCFilter(DEM_DTC_STATUS_MASK_ALL, DEM_DTC_KIND_ALL_DTCS, DEM_DTC_ORIGIN_PRIMARY_MEMORY, DEM_FILTER_WITH_SEVERITY_NO, VALUE_IS_NOT_USED, DEM_FILTER_FOR_FDC_NO);
\r
329 case 0x0F: // reportMirrorMemoryDTCByStatusMask
\r
330 setDtcFilterResult = Dem_SetDTCFilter(pduRxData->SduDataPtr[2], DEM_DTC_KIND_ALL_DTCS, DEM_DTC_ORIGIN_MIRROR_MEMORY, DEM_FILTER_WITH_SEVERITY_NO, VALUE_IS_NOT_USED, DEM_FILTER_FOR_FDC_NO);
\r
333 case 0x13: // reportEmissionRelatedOBDDTCByStatusMask
\r
334 setDtcFilterResult = Dem_SetDTCFilter(pduRxData->SduDataPtr[2], DEM_DTC_KIND_EMISSON_REL_DTCS, DEM_DTC_ORIGIN_PRIMARY_MEMORY, DEM_FILTER_WITH_SEVERITY_NO, VALUE_IS_NOT_USED, DEM_FILTER_FOR_FDC_NO);
\r
337 case 0x15: // reportDTCWithPermanentStatus
\r
338 setDtcFilterResult = Dem_SetDTCFilter(DEM_DTC_STATUS_MASK_ALL, DEM_DTC_KIND_ALL_DTCS, DEM_DTC_ORIGIN_PERMANENT_MEMORY, DEM_FILTER_WITH_SEVERITY_NO, VALUE_IS_NOT_USED, DEM_FILTER_FOR_FDC_NO);
\r
342 setDtcFilterResult = DEM_WRONG_FILTER;
\r
343 #if (DCM_DEV_ERROR_DETECT == STD_ON)
\r
344 Det_ReportError(MODULE_ID_DCM, 0, DCM_UDS_READ_DTC_INFO, DCM_E_UNEXPECTED_PARAM);
\r
349 if (setDtcFilterResult == DEM_FILTER_ACCEPTED) {
\r
350 uint8 dtcStatusMask;
\r
351 TxDataType *txData = (TxDataType*)pduTxData->SduDataPtr;
\r
352 Dem_ReturnGetNextFilteredDTCType getNextFilteredDtcResult;
\r
354 Dem_EventStatusExtendedType dtcStatus;
\r
355 uint16 nrOfDtcs = 0;
\r
357 /** @reg DCM377 **/
\r
358 Dem_GetDTCStatusAvailabilityMask(&dtcStatusMask);
\r
360 // Create positive response (ISO 14229-1 table 252)
\r
361 /** @req DCM039.0x19 **/
\r
362 txData->reportType = pduRxData->SduDataPtr[1];
\r
363 txData->dtcStatusAvailabilityMask = dtcStatusMask;
\r
365 if (dtcStatusMask != 0x00) { /** @req DCM008 **/
\r
366 getNextFilteredDtcResult = Dem_GetNextFilteredDTC(&dtc, &dtcStatus);
\r
367 while (getNextFilteredDtcResult == DEM_FILTERED_OK) {
\r
368 txData->dtcAndStatusRecord[nrOfDtcs].dtcHighByte = DTC_HIGH_BYTE(dtc);
\r
369 txData->dtcAndStatusRecord[nrOfDtcs].dtcMiddleByte = DTC_MID_BYTE(dtc);
\r
370 txData->dtcAndStatusRecord[nrOfDtcs].dtcLowByte = DTC_LOW_BYTE(dtc);
\r
371 txData->dtcAndStatusRecord[nrOfDtcs].statusOfDtc = dtcStatus;
\r
373 getNextFilteredDtcResult = Dem_GetNextFilteredDTC(&dtc, &dtcStatus);
\r
376 if (getNextFilteredDtcResult != DEM_FILTERED_NO_MATCHING_DTC) {
\r
377 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
380 pduTxData->SduLength = 3 + nrOfDtcs * sizeof(dtcAndStatusRecordType);
\r
383 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
386 return responseCode;
\r
390 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x08(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
392 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
394 // TODO: Not supported yet, (DEM module does not currently support severity).
\r
395 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
397 return responseCode;
\r
401 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x09(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
403 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
405 // TODO: Not supported yet, (DEM module does not currently support severity).
\r
406 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
408 return responseCode;
\r
412 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x06_0x10(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
414 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
415 Dem_DTCOriginType dtcOrigin = NULL;
\r
419 // Switch on sub function
\r
420 switch (pduRxData->SduDataPtr[1]) /** @reg DCM378 **/
\r
422 case 0x06: // reportDTCExtendedDataRecordByDTCNumber
\r
423 dtcOrigin = DEM_DTC_ORIGIN_PRIMARY_MEMORY;
\r
426 case 0x10: // reportMirrorMemoryDTCExtendedDataRecordByDTCNumber
\r
427 dtcOrigin = DEM_DTC_ORIGIN_MIRROR_MEMORY;
\r
431 responseCode = DCM_E_SUBFUNCTIONNOTSUPPORTED;
\r
432 #if (DCM_DEV_ERROR_DETECT == STD_ON)
\r
433 Det_ReportError(MODULE_ID_DCM, 0, DCM_UDS_READ_DTC_INFO, DCM_E_UNEXPECTED_PARAM);
\r
438 // Switch on record number
\r
439 switch (pduRxData->SduDataPtr[5])
\r
441 case 0xFF: // Report all Extended Data Records for a particular DTC
\r
442 startRecNum = 0x00;
\r
446 case 0xFE: // Report all OBD Extended Data Records for a particular DTC
\r
447 startRecNum = 0x90;
\r
451 default: // Report one specific Extended Data Records for a particular DTC
\r
452 startRecNum = pduRxData->SduDataPtr[5];
\r
453 endRecNum = startRecNum;
\r
457 if (responseCode == DCM_E_POSITIVERESPONSE) {
\r
458 Dem_ReturnGetStatusOfDTCType getStatusOfDtcResult;
\r
460 Dem_EventStatusExtendedType statusOfDtc;
\r
462 dtc = BYTES_TO_DTC(pduRxData->SduDataPtr[2], pduRxData->SduDataPtr[3], pduRxData->SduDataPtr[4]);
\r
463 getStatusOfDtcResult = Dem_GetStatusOfDTC(dtc, DEM_DTC_KIND_ALL_DTCS, dtcOrigin, &statusOfDtc); /** @req DCM295 **/ /** @req DCM475 **/
\r
464 if (getStatusOfDtcResult == DEM_STATUS_OK) {
\r
465 Dem_ReturnGetExtendedDataRecordByDTCType getExtendedDataRecordByDtcResult;
\r
468 uint16 txIndex = 6;
\r
470 /** @req DCM297 **/ /** @req DCM474 **/ /** @req DCM386 **/
\r
471 pduTxData->SduDataPtr[1] = pduRxData->SduDataPtr[1]; // Sub function
\r
472 pduTxData->SduDataPtr[2] = DTC_HIGH_BYTE(dtc); // DTC high byte
\r
473 pduTxData->SduDataPtr[3] = DTC_MID_BYTE(dtc); // DTC mid byte
\r
474 pduTxData->SduDataPtr[4] = DTC_LOW_BYTE(dtc); // DTC low byte
\r
475 pduTxData->SduDataPtr[5] = statusOfDtc; // DTC status
\r
476 for (recNum = startRecNum; recNum <= endRecNum; recNum++) {
\r
477 recLength = DCM_PHYS_BUFFER_SIZE - txIndex -1; // Calculate what's left in buffer
\r
478 /** @req DCM296 **/ /** @req DCM476 **/ /** @req DCM382 **/
\r
479 getExtendedDataRecordByDtcResult = Dem_GetExtendedDataRecordByDTC(dtc, DEM_DTC_KIND_ALL_DTCS, dtcOrigin, recNum, &pduTxData->SduDataPtr[txIndex+1], &recLength);
\r
480 if (getExtendedDataRecordByDtcResult == DEM_RECORD_OK) {
\r
481 pduTxData->SduDataPtr[txIndex++] = recNum;
\r
482 /* Instead of calling Dem_GetSizeOfExtendedDataRecordByDTC() the result from Dem_GetExtendedDataRecordByDTC() is used */
\r
483 /** @req DCM478 **/ /** @req DCM479 **/ /** @req DCM480 **/
\r
484 txIndex += recLength;
\r
487 // TODO: What to do here?
\r
490 pduTxData->SduLength = txIndex;
\r
493 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
497 return responseCode;
\r
501 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x03(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
503 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
505 // TODO: Not supported yet
\r
506 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
508 return responseCode;
\r
512 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x04(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
514 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
516 // TODO: Not supported yet
\r
517 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
519 return responseCode;
\r
523 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x05(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
525 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
527 // TODO: Not supported yet
\r
528 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
530 return responseCode;
\r
534 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x0B_0x0C_0x0D_0x0E(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
536 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
538 // TODO: Not supported yet
\r
539 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
541 return responseCode;
\r
545 Dcm_NegativeResponseCodeType DspUdsReadDtcInfoSub_0x14(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
547 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
549 // TODO: Not supported yet
\r
550 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
552 return responseCode;
\r
556 void DspUdsReadDtcInformation(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
558 /** @reg DCM248 **/
\r
559 // Sub function number 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15
\r
560 const uint8 sduLength[0x16] = {0, 3, 3, 6, 6, 3, 6, 4, 4, 5, 2, 2, 2, 2, 2, 3, 6, 3, 3, 3, 2, 2};
\r
562 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
564 uint8 subFunctionNumber = pduRxData->SduDataPtr[1];
\r
567 if (subFunctionNumber <= 0x15) {
\r
568 if (pduRxData->SduLength == sduLength[subFunctionNumber]) {
\r
569 switch (subFunctionNumber)
\r
571 case 0x01: // reportNumberOfDTCByStatusMask
\r
572 case 0x07: // reportNumberOfDTCBySeverityMaskRecord
\r
573 case 0x11: // reportNumberOfMirrorMemoryDTCByStatusMask
\r
574 case 0x12: // reportNumberOfEmissionRelatedOBDDTCByStatusMask
\r
575 responseCode = DspUdsReadDtcInfoSub_0x01_0x07_0x11_0x12(pduRxData, pduTxData);
\r
578 case 0x02: // reportDTCByStatusMask
\r
579 case 0x0A: // reportSupportedDTC
\r
580 case 0x0F: // reportMirrorMemoryDTCByStatusMask
\r
581 case 0x13: // reportEmissionRelatedOBDDTCByStatusMask
\r
582 case 0x15: // reportDTCWithPermanentStatus
\r
583 responseCode = DspUdsReadDtcInfoSub_0x02_0x0A_0x0F_0x13_0x15(pduRxData, pduTxData);
\r
586 case 0x08: // reportDTCBySeverityMaskRecord
\r
587 responseCode = DspUdsReadDtcInfoSub_0x08(pduRxData, pduTxData);
\r
590 case 0x09: // reportSeverityInformationOfDTC
\r
591 responseCode = DspUdsReadDtcInfoSub_0x09(pduRxData, pduTxData);
\r
594 case 0x06: // reportDTCExtendedDataRecordByDTCNumber
\r
595 case 0x10: // reportMirrorMemoryDTCExtendedDataRecordByDTCNumber
\r
596 responseCode = DspUdsReadDtcInfoSub_0x06_0x10(pduRxData, pduTxData);
\r
599 case 0x03: // reportDTCSnapshotIdentidication
\r
600 responseCode = DspUdsReadDtcInfoSub_0x03(pduRxData, pduTxData);
\r
603 case 0x04: // reportDTCSnapshotByDtcNumber
\r
604 responseCode = DspUdsReadDtcInfoSub_0x04(pduRxData, pduTxData);
\r
607 case 0x05: // reportDTCSnapshotRecordNumber
\r
608 responseCode = DspUdsReadDtcInfoSub_0x05(pduRxData, pduTxData);
\r
611 case 0x0B: // reportFirstTestFailedDTC
\r
612 case 0x0C: // reportFirstConfirmedDTC
\r
613 case 0x0D: // reportMostRecentTestFailedDTC
\r
614 case 0x0E: // reportMostRecentConfirmedDTC
\r
615 responseCode = DspUdsReadDtcInfoSub_0x0B_0x0C_0x0D_0x0E(pduRxData, pduTxData);
\r
618 case 0x14: // reportDTCFaultDetectionCounter
\r
619 responseCode = DspUdsReadDtcInfoSub_0x14(pduRxData, pduTxData);
\r
623 // Unknown sub function
\r
624 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
630 responseCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT; /** @req DCM272.0x19 **/
\r
634 // Sub function out of range
\r
635 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
638 DsdDspProcessingDone(responseCode);
\r
642 boolean DspLookupDid(uint16 didNr, const Dcm_DspDidType **didPtr)
\r
644 const Dcm_DspDidType *dspDid = DCM_Config.Dsp->DspDid;
\r
645 boolean didFound = FALSE;
\r
647 while ((dspDid->DspDidIdentifier != didNr) && !dspDid->Arc_EOL) {
\r
651 if (!dspDid->Arc_EOL) {
\r
660 Dcm_NegativeResponseCodeType DspReadDidData(const Dcm_DspDidType *didPtr, PduInfoType *pduTxData, uint16 *txPos)
\r
662 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
664 if ((didPtr->DspDidInfoRef->DspDidAccess.DspDidRead != NULL) && (didPtr->DspDidConditionCheckReadFnc != NULL) && (didPtr->DspDidReadDataFnc != NULL)) { /** @req DCM433 **/
\r
665 if (DspCheckSessionLevel(didPtr->DspDidInfoRef->DspDidAccess.DspDidRead->DspDidReadSessionRef)) { /** @req DCM434 **/
\r
666 if (DspCheckSecurityLevel(didPtr->DspDidInfoRef->DspDidAccess.DspDidRead->DspDidReadSecurityLevelRef)) { /** @req DCM435 **/
\r
667 Std_ReturnType result;
\r
668 Dcm_NegativeResponseCodeType errorCode;
\r
669 result = didPtr->DspDidConditionCheckReadFnc(&errorCode);
\r
670 if ((result == E_OK) && (errorCode == DCM_E_POSITIVERESPONSE)) { /** @req DCM439 **/
\r
673 if (didPtr->DspDidInfoRef->DspDidFixedLength) { /** @req DCM436 **/
\r
674 didLen = didPtr->DspDidSize;
\r
678 if (didPtr->DspDidReadDataLengthFnc != NULL) {
\r
679 result = didPtr->DspDidReadDataLengthFnc(&didLen);
\r
683 if (result == E_OK) {
\r
684 // Now ready for reading the data!
\r
685 if ((*txPos + didLen + 2) <= pduTxData->SduLength) {
\r
686 pduTxData->SduDataPtr[*txPos] = (didPtr->DspDidIdentifier >> 8) & 0xFF;
\r
688 pduTxData->SduDataPtr[*txPos] = (didPtr->DspDidIdentifier >> 0) & 0xFF;
\r
690 result = didPtr->DspDidReadDataFnc(&pduTxData->SduDataPtr[*txPos]); /** @req DCM437 **/
\r
693 if (result != E_OK) {
\r
694 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
697 else { // tx buffer full
\r
698 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
701 else { // Not possible to obtain did length
\r
702 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
705 else { // CheckRead failed
\r
706 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
709 else { // Not allowed in current security level
\r
710 responseCode = DCM_E_SECUTITYACCESSDENIED;
\r
713 else { // Not allowed in current session
\r
714 responseCode = DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION;
\r
717 else { // Read access not configured
\r
718 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
721 if (responseCode == DCM_E_POSITIVERESPONSE) {
\r
722 // Recurse trough the rest of the dids. /** @req DCM440 **/
\r
724 for (i=0; (!didPtr->DspDidRef[i]->Arc_EOL) && (responseCode == DCM_E_POSITIVERESPONSE); i++) {
\r
725 responseCode = DspReadDidData(didPtr->DspDidRef[i], pduTxData, txPos);
\r
729 return responseCode;
\r
732 void DspUdsReadDataByIdentifier(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
734 /** @req DCM253 **/
\r
735 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
738 const Dcm_DspDidType *didPtr = NULL;
\r
743 if ((pduRxData->SduLength - 1) % 2 == 0 ) {
\r
744 nrOfDids = (pduRxData->SduLength - 1) / 2;
\r
746 for (i = 0; (i < nrOfDids) && (responseCode == DCM_E_POSITIVERESPONSE); i++) {
\r
747 didNr = (pduRxData->SduDataPtr[1+i*2] << 8) + pduRxData->SduDataPtr[2+i*2];
\r
748 if (DspLookupDid(didNr, &didPtr)) { /** @req DCM438 **/
\r
749 responseCode = DspReadDidData(didPtr, pduTxData, &txPos);
\r
751 else { // DID not found
\r
752 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
757 responseCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
\r
760 if (responseCode == DCM_E_POSITIVERESPONSE) {
\r
761 pduTxData->SduLength = txPos;
\r
764 DsdDspProcessingDone(responseCode);
\r
768 Dcm_NegativeResponseCodeType DspReadDidScalingData(const Dcm_DspDidType *didPtr, PduInfoType *pduTxData, uint16 *txPos)
\r
770 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
772 if (didPtr->DspDidGetScalingInfoFnc != NULL) {
\r
773 uint16 scalingInfoLen;
\r
775 scalingInfoLen = didPtr->DspDidInfoRef->DspDidScalingInfoSize;
\r
776 if ((*txPos + scalingInfoLen + 2) <= pduTxData->SduLength) {
\r
777 Std_ReturnType result;
\r
778 Dcm_NegativeResponseCodeType errorCode;
\r
780 pduTxData->SduDataPtr[*txPos] = (didPtr->DspDidIdentifier >> 8) & 0xFF;
\r
782 pduTxData->SduDataPtr[*txPos] = (didPtr->DspDidIdentifier >> 0) & 0xFF;
\r
784 result = didPtr->DspDidGetScalingInfoFnc(&pduTxData->SduDataPtr[*txPos], &errorCode); /** @req DCM394 **/
\r
785 *txPos += scalingInfoLen;
\r
787 if ((result != E_OK) || (errorCode != DCM_E_POSITIVERESPONSE)) {
\r
788 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
791 else { // tx buffer full
\r
792 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
795 else { // DspDidGetScalingInfoFnc null pointer
\r
796 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
799 return responseCode;
\r
802 void DspUdsReadScalingDataByIdentifier(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
804 /** @req DCM258 **/
\r
805 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
807 const Dcm_DspDidType *didPtr = NULL;
\r
811 if (pduRxData->SduLength == 3) {
\r
812 didNr = (pduRxData->SduDataPtr[1] << 8) + pduRxData->SduDataPtr[2];
\r
813 if (DspLookupDid(didNr, &didPtr)) {
\r
814 responseCode = DspReadDidScalingData(didPtr, pduTxData, &txPos);
\r
816 else { // DID not found
\r
817 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
820 if (responseCode == DCM_E_POSITIVERESPONSE) {
\r
821 pduTxData->SduLength = txPos;
\r
826 responseCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
\r
829 DsdDspProcessingDone(responseCode);
\r
833 Dcm_NegativeResponseCodeType DspWriteDidData(const Dcm_DspDidType *didPtr, const PduInfoType *pduRxData, uint16 writeDidLen)
\r
835 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
837 if ((didPtr->DspDidInfoRef->DspDidAccess.DspDidWrite != NULL) && (didPtr->DspDidConditionCheckWriteFnc != NULL) && (didPtr->DspDidWriteDataFnc != NULL)) { /** @req DCM468 **/
\r
838 if (DspCheckSessionLevel(didPtr->DspDidInfoRef->DspDidAccess.DspDidWrite->DspDidWriteSessionRef)) { /** @req DCM469 **/
\r
839 if (DspCheckSecurityLevel(didPtr->DspDidInfoRef->DspDidAccess.DspDidWrite->DspDidWriteSecurityLevelRef)) { /** @req DCM470 **/
\r
840 Std_ReturnType result;
\r
841 Dcm_NegativeResponseCodeType errorCode;
\r
842 result = didPtr->DspDidConditionCheckWriteFnc(&errorCode); /** @req DCM471 **/
\r
843 if ((result == E_OK) && (errorCode == DCM_E_POSITIVERESPONSE)) {
\r
846 if (didPtr->DspDidInfoRef->DspDidFixedLength) { /** @req DCM472 **/
\r
847 didLen = didPtr->DspDidSize;
\r
851 if (didPtr->DspDidReadDataLengthFnc != NULL) {
\r
852 result = didPtr->DspDidReadDataLengthFnc(&didLen);
\r
856 if (result == E_OK) {
\r
857 if (didLen == writeDidLen) { /** @req DCM473 **/
\r
858 result = didPtr->DspDidWriteDataFnc(&pduRxData->SduDataPtr[3], didLen, &errorCode); /** @req DCM395 **/
\r
859 if ((result != E_OK) || (errorCode != DCM_E_POSITIVERESPONSE)) {
\r
860 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
864 responseCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
\r
867 else { // Not possible to obtain did length
\r
868 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
871 else { // CheckRead failed
\r
872 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
875 else { // Not allowed in current security level
\r
876 responseCode = DCM_E_SECUTITYACCESSDENIED;
\r
879 else { // Not allowed in current session
\r
880 responseCode = DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION;
\r
883 else { // Read access not configured
\r
884 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
887 return responseCode;
\r
890 void DspUdsWriteDataByIdentifier(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
892 /** @req DCM255 **/
\r
893 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
895 const Dcm_DspDidType *didPtr = NULL;
\r
897 uint16 didDataLength;
\r
899 didDataLength = pduRxData->SduLength - 3;
\r
900 didNr = (pduRxData->SduDataPtr[1] << 8) + pduRxData->SduDataPtr[2];
\r
901 if (DspLookupDid(didNr, &didPtr)) { /** @req DCM467 **/
\r
902 responseCode = DspWriteDidData(didPtr, pduRxData, didDataLength);
\r
904 else { // DID not found
\r
905 responseCode = DCM_E_REQUESTOUTOFRANGE;
\r
908 if (responseCode == DCM_E_POSITIVERESPONSE) {
\r
909 pduTxData->SduLength = 3;
\r
910 pduTxData->SduDataPtr[1] = (didNr >> 8) & 0xFF;
\r
911 pduTxData->SduDataPtr[2] = (didNr >> 0) & 0xFF;
\r
914 DsdDspProcessingDone(responseCode);
\r
918 void DspUdsSecurityAccess(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
920 /** @req DCM252 **/
\r
921 Dcm_NegativeResponseCodeType responseCode = DCM_E_POSITIVERESPONSE;
\r
923 // Check sub function range (0x01 to 0x42)
\r
924 if ((pduRxData->SduDataPtr[1] >= 0x01) && (pduRxData->SduDataPtr[1] <= 0x42)) {
\r
925 boolean isRequestSeed = pduRxData->SduDataPtr[1] & 0x01;
\r
926 Dcm_SecLevelType requestedSecurityLevel = (pduRxData->SduDataPtr[1]-1)/2;
\r
927 Std_ReturnType getSeedResult;
\r
928 Dcm_NegativeResponseCodeType getSeedErrorCode;
\r
931 if (isRequestSeed) {
\r
932 // requestSeed message
\r
933 // Check if type exist in security table
\r
934 for (i = 0; (DCM_Config.Dsp->DspSecurity->DspSecurityRow[i].DspSecurityLevel != requestedSecurityLevel) && !DCM_Config.Dsp->DspSecurity->DspSecurityRow[i].Arc_EOL; i++);
\r
936 if (!DCM_Config.Dsp->DspSecurity->DspSecurityRow[i].Arc_EOL) {
\r
937 const Dcm_DspSecurityRowType *requestedSecurity = &DCM_Config.Dsp->DspSecurity->DspSecurityRow[i];
\r
939 if (pduRxData->SduLength == (2 + requestedSecurity->DspSecurityADRSize)) { /** @req DCM321.1 **/
\r
940 Dcm_SecLevelType activeSecLevel;
\r
941 Dcm_GetSecurityLevel(&activeSecLevel);
\r
942 if (requestedSecurityLevel == activeSecLevel) { /** @req DCM323 **/
\r
943 pduTxData->SduDataPtr[1] = pduRxData->SduDataPtr[1];
\r
944 // If same level set the seed to zeroes
\r
945 for (i = 0; i < requestedSecurity->DspSecuritySeedSize; i++) {
\r
946 pduTxData->SduDataPtr[2+i] = 0;
\r
947 pduTxData->SduLength = 2 + requestedSecurity->DspSecuritySeedSize;
\r
951 // New security level ask for seed
\r
952 getSeedResult = requestedSecurity->GetSeed(&pduRxData->SduDataPtr[2], &pduTxData->SduDataPtr[2], &getSeedErrorCode);
\r
953 if ((getSeedResult == E_OK) && (getSeedErrorCode == E_OK)) {
\r
954 // Everything ok add sub function to tx message and send it.
\r
955 pduTxData->SduDataPtr[1] = pduRxData->SduDataPtr[1];
\r
956 pduTxData->SduLength = 2 + requestedSecurity->DspSecuritySeedSize;
\r
958 dspUdsSecurityAccesData.reqSecLevel = requestedSecurityLevel;
\r
959 dspUdsSecurityAccesData.reqSecLevelRef = &DCM_Config.Dsp->DspSecurity->DspSecurityRow[i];
\r
960 dspUdsSecurityAccesData.reqInProgress = TRUE;
\r
961 // TODO: Start security timeout
\r
964 // GetSeed returned not ok
\r
965 responseCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
\r
971 responseCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
\r
975 // Requested security level not configured
\r
976 responseCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
\r
981 if (dspUdsSecurityAccesData.reqInProgress) {
\r
982 if (pduRxData->SduLength == (2 + dspUdsSecurityAccesData.reqSecLevelRef->DspSecurityKeySize)) { /** @req DCM321 **/
\r
983 if (requestedSecurityLevel == dspUdsSecurityAccesData.reqSecLevel) {
\r
984 Std_ReturnType compareKeyResult;
\r
985 compareKeyResult = dspUdsSecurityAccesData.reqSecLevelRef->CompareKey(&pduRxData->SduDataPtr[2]);
\r
986 if (compareKeyResult == E_OK) {
\r
987 // Request accepted
\r
989 DslSetSecurityLevel(dspUdsSecurityAccesData.reqSecLevelRef->DspSecurityLevel);
\r
990 dspUdsSecurityAccesData.reqInProgress = FALSE;
\r
991 pduTxData->SduDataPtr[1] = pduRxData->SduDataPtr[1];
\r
992 pduTxData->SduLength = 2;
\r
995 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
999 responseCode = DCM_E_CONDITIONSNOTCORRECT;
\r
1004 responseCode = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
\r
1008 // sendKey request without a preceding requestSeed
\r
1009 responseCode = DCM_E_REQUESTSEQUENCEERROR;
\r
1014 responseCode = DCM_E_SUBFUNCTIONNOTSUPPORTED;
\r
1017 DsdDspProcessingDone(responseCode);
\r
1021 void DspUdsTesterPresent(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
1023 if (pduRxData->SduLength == 2) {
\r
1024 switch (pduRxData->SduDataPtr[1])
\r
1026 case ZERO_SUB_FUNCTION:
\r
1027 DslResetSessionTimeoutTimer();
\r
1028 // Create positive response
\r
1029 /** @req DCM039.1 **/
\r
1030 pduTxData->SduDataPtr[1] = ZERO_SUB_FUNCTION;
\r
1031 pduTxData->SduLength = 2;
\r
1032 DsdDspProcessingDone(DCM_E_POSITIVERESPONSE); /** @req DCM269.1 **/
\r
1036 DsdDspProcessingDone(DCM_E_SUBFUNCTIONNOTSUPPORTED); /** @req DCM273.1 **/
\r
1042 DsdDspProcessingDone(DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT); /** @req DCM272.1 **/
\r
1047 void DspUdsControlDtcSetting(const PduInfoType *pduRxData, PduInfoType *pduTxData)
\r
1049 Dem_ReturnControlDTCStorageType resultCode;
\r
1051 if (pduRxData->SduLength == 2) {
\r
1052 switch (pduRxData->SduDataPtr[1])
\r
1054 case 0x01: // ON /** @req DCM249.1 **/
\r
1055 resultCode = Dem_EnableDTCStorage(DEM_DTC_GROUP_ALL_DTCS, DEM_DTC_KIND_ALL_DTCS); /** @req DCM304 **/
\r
1056 if (resultCode == DEM_CONTROL_DTC_STORAGE_OK) {
\r
1057 pduTxData->SduDataPtr[1] = 0x01;
\r
1058 pduTxData->SduLength = 2;
\r
1059 DsdDspProcessingDone(DCM_E_POSITIVERESPONSE);
\r
1062 DsdDspProcessingDone(DCM_E_REQUESTOUTOFRANGE);
\r
1066 case 0x02: // OFF /** @req DCM249.2 **/
\r
1067 resultCode = Dem_DisableDTCStorage(DEM_DTC_GROUP_ALL_DTCS, DEM_DTC_KIND_ALL_DTCS); /** @req DCM406 **/
\r
1068 if (resultCode == DEM_CONTROL_DTC_STORAGE_OK) {
\r
1069 pduTxData->SduDataPtr[1] = 0x02;
\r
1070 pduTxData->SduLength = 2;
\r
1071 DsdDspProcessingDone(DCM_E_POSITIVERESPONSE);
\r
1074 DsdDspProcessingDone(DCM_E_REQUESTOUTOFRANGE);
\r
1079 DsdDspProcessingDone(DCM_E_SUBFUNCTIONNOTSUPPORTED);
\r
1085 DsdDspProcessingDone(DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
\r
1090 void DspDcmConfirmation(PduIdType confirmPduId)
\r
1092 if (dspUdsEcuResetData.resetPending) {
\r
1093 if (confirmPduId == dspUdsEcuResetData.resetPduId) {
\r
1094 dspUdsEcuResetData.resetPending = FALSE;
\r
1095 Mcu_PerformReset();
\r