/* * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD * All rights reserved. * * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use * exclusively with CVA's microcontroller products. This file can be freely * distributed within development tools that are supporting such microcontroller * products. * * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. */ /******************************************************************************* * the includes ******************************************************************************/ #include "uds_service31.h" /******************************************************************************* * the defines ******************************************************************************/ /******************************************************************************* * the typedefs ******************************************************************************/ /*! \brief The Uds routine control type */ typedef enum _UdsRoutineCtrlType_ { UDS_ROUTINE_CTRL_NONE = 0, UDS_ROUTINE_CTRL_START = 0x01, UDS_ROUTINE_CTRL_STOP = 0x02, UDS_ROUTINE_CTRL_REQUEST_RESULT = 0x03 } UdsRoutineCtrlType; /*! \brief The Uds routine control status */ typedef enum _UdsRtnCtrlStatus_ { UDS_RTN_ST_IDLE = 0x00, UDS_RTN_ST_RUNNING = 0x01, } UdsRtnCtrlStatus; /*! \brief The Uds routine control struct */ typedef struct _Uds_RtnCtrl_ { uint16_t rtnCtrlId; uint8_t sessionLevel; uint8_t securityLevel; UdsRtnCtrlStatus rtnStatus; void (*Routine_Start)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); void (*Routine_Stop)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); void (*Routine_Result)(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); } Uds_RtnCtrl; /******************************************************************************* * the constants ******************************************************************************/ static void Routine_StartEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); static void Routine_StopEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); static void Routine_EreaseMemoryResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); static void Routine_StartCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); static void Routine_StopCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); static void Routine_CheckProgramDependenciesResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); static void Routine_StartEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); static void Routine_StopEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); static void Routine_EreaseMirrorMemDtcsResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen); /******************************************************************************* * the globals ******************************************************************************/ Uds_RtnCtrl udsRtnCtrlTable[] = { {0xFF00, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartEreaseMemory, &Routine_StopEreaseMemory, &Routine_EreaseMemoryResult }, {0xFF01, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartCheckProgramDependencies, &Routine_StopCheckProgramDependencies, &Routine_CheckProgramDependenciesResult}, {0xFF02, UDS_SESSION_EXTENDED, UDS_SA_LEVEL_1, UDS_RTN_ST_IDLE, &Routine_StartEreaseMirrorMemDtcs, &Routine_StopEreaseMirrorMemDtcs, &Routine_EreaseMirrorMemDtcsResult }, }; /******************************************************************************* * the functions ******************************************************************************/ void Routine_StatusInit(uint16_t routineId) { uint8_t rtnIndex = 0; uint8_t rntNum = sizeof(udsRtnCtrlTable) / sizeof(Uds_RtnCtrl); for(rtnIndex = 0; rtnIndex < rntNum; rtnIndex++) { if(udsRtnCtrlTable[rtnIndex].rtnCtrlId == routineId) { udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_IDLE; } } } static void Routine_StartEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add start erease memory code */ } static void Routine_StopEreaseMemory(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add stop erease memory code */ } static void Routine_EreaseMemoryResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add erease memory result code */ } static void Routine_StartCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add start check program dependencies code */ } static void Routine_StopCheckProgramDependencies(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add stop check program dependencies code */ } static void Routine_CheckProgramDependenciesResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add check program dependencies result code */ } static void Routine_StartEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add start erease mirror memory Dtcs code */ } static void Routine_StopEreaseMirrorMemDtcs(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add stop erease mirror memory Dtcs code */ } static void Routine_EreaseMirrorMemDtcsResult(const uint8_t *pdata, uint16_t len, uint8_t *pRspData, uint16_t rspSize, uint16_t *pRspLen) { if(pdata == NULL) { return; } /* user add erease mirror memory Dtcs resultl code */ } void UdsService31_RoutineControl(UdsType *obj, const uint8_t msgBuf[], uint16_t msgLen) { const uint8_t *pOptionParam = NULL; uint8_t subFunction = 0; uint16_t optionParamLen = 0; uint16_t routineId = 0; uint8_t rtnIndex = 0; uint8_t rntNum = sizeof(udsRtnCtrlTable) / sizeof(Uds_RtnCtrl); uint8_t rspBuffer[UDS_RSP_LEN_MAX] = {0}; uint16_t rspLen = 0; if(msgLen < obj->seviceTable[obj->curServiceIdx].minLen) { Uds_NegativeResponse(obj, 0x31, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT); return; } subFunction = UDS_GET_SUB_FUNCTION(msgBuf[1]); routineId = ((uint16_t)msgBuf[2] << 8) + msgBuf[3]; optionParamLen = msgLen - 4; if(optionParamLen > 0) { pOptionParam = &msgBuf[4]; } for(rtnIndex = 0; rtnIndex < rntNum; rtnIndex++) { if(udsRtnCtrlTable[rtnIndex].rtnCtrlId == routineId) { if(obj->session == udsRtnCtrlTable[rtnIndex].sessionLevel) { if((udsRtnCtrlTable[rtnIndex].securityLevel != UDS_SA_NONE) && (udsRtnCtrlTable[rtnIndex].securityLevel != obj->securityLevel)) { Uds_NegativeResponse(obj, 0x31, NRC_SECURITY_ACCESS_DENIED); return; } break; } else { Uds_NegativeResponse(obj, 0x31, NRC_CONDITIONS_NOT_CORRECT); return; } } } if(rtnIndex >= rntNum) { Uds_NegativeResponse(obj, 0x31, NRC_REQUEST_OUT_OF_RANGE); return; } memset(rspBuffer, 0, UDS_RSP_LEN_MAX); switch(subFunction) { case UDS_ROUTINE_CTRL_START: udsRtnCtrlTable[rtnIndex].Routine_Start(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen); udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_RUNNING; break; case UDS_ROUTINE_CTRL_STOP: if(udsRtnCtrlTable[rtnIndex].rtnStatus != UDS_RTN_ST_IDLE) { udsRtnCtrlTable[rtnIndex].Routine_Stop(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen); udsRtnCtrlTable[rtnIndex].rtnStatus = UDS_RTN_ST_IDLE; } break; case UDS_ROUTINE_CTRL_REQUEST_RESULT: if(udsRtnCtrlTable[rtnIndex].rtnStatus != UDS_RTN_ST_IDLE) { udsRtnCtrlTable[rtnIndex].Routine_Result(pOptionParam, optionParamLen, rspBuffer, UDS_RSP_LEN_MAX, &rspLen); } break; default: Uds_NegativeResponse(obj, 0x31, NRC_SUBFUNCTION_NOT_SUPPORTED); return; } /* polyspace-begin DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */ if((rspLen >= 4) && (rspBuffer[0] == UDS_GET_POSITIVE_RSP(0x31))) { Uds_PositiveResponse(obj, rspBuffer, rspLen); } else if((rspLen == 3) && (rspBuffer[0] == NEGATIVE_RSP)) { Uds_NegativeResponse(obj, 0x31, rspBuffer[2]); } else { Uds_NegativeResponse(obj, 0x31, NRC_REQUEST_SEQUENCE_ERROR); } /* polyspace-end DEFECT:DEAD_CODE [No action planned:Low] "Still reserve though it's maybe unreachable" */ }