/******************************************************************************
 �� �� ��;UDS_ISO14229_Services.c
 ��������;ISO 14229 �淶�涨����Ϸ���������˷���ʵ�ֺ������ļ�
 ��    ��;����
 ��    ��;V1.0
 ��    ��;2016.11.1
 ******************************************************************************/
#include <string.h>
#include "UDS_ISO14229_Services.h"
#include "UDS_ISO14229_Server.h"
#include "flash.h"
#include "CAN_Signal\CAN_Lib.h"
#include  "CAN_CH0_CAN_Communication_Matrix.h"
typedef struct
{
    uint8_t u8_ProgramName[32];
    uint8_t u8_PartNumber[32];
    uint8_t u8_Platform[32];
    uint8_t u8_Communication_Type[32];
    uint32_t u8_Diagnostic_ID[4];
} project_info_t;

/* 豪进750TFT仪表 */
extern const project_info_t project_info __attribute__((section(".ARM.__at_0x0000C200"))) =
{
    "HJ_750_TFT",
    "HJYB-7500TFT",
    "BAT32A279KM64FB",
    "CAN_STD_CH0_500Kbps",
    {DIAG_ID_Tx, DIAG_ID_Rx_PHY, DIAG_ID_Rx_FUN, 0U}
};

DiagSendDataNeg NegRes;
uint8_t UDS_ISO14229_Transfer[250];

DiagFlag DiagDataForFlag;
/****************S3Timer********************/
uint8_t S3_ServerEN       = 0;
uint8_t S3_ServerCnt      = 0;
uint8_t S3_Server_refresh = 0;
/****************DiagnosticSession*****************/
uint8_t SessionType = 0x01;
/******************************************************************************
 The service access point of the diagnostics application layer provides a number
 of services that all have the same general structure. For each service, three
 service primitives are specified:

 - a service indication primitive, used by the diagnostics application layer, to
 pass data to the server function of the ECU diagnostic application;

 - a service response primitive, used by the server function in the ECU
 diagnostic application, to pass response data provided by the requested
 diagnostic service to the diagnostics application layer;

 - a service response-confirmation primitive, used by the server function in the
 ECU diagnostic application, to indicate that the data passed in the service
 response primitive is successfully sent on the vehicle communication bus the
 ECU received the diagnostic request on;
 ******************************************************************************/

//软件版本号 F195
uint8_t MCU_SWversion[6] = {'S', 'V', (uint8_t)((SWV >> 8u) & 0x0Fu) + 0x30u, '.', (uint8_t)((SWV >> 4u) & 0x0Fu) + 0x30u, (uint8_t)(SWV & 0x0Fu) + 0x30u};

//硬件版本号 F193
uint8_t MCU_HWversion[6] = {'H', 'V', (uint8_t)((HWV >> 8u) & 0x0Fu) + 0x30u, '.', (uint8_t)((HWV >> 4u) & 0x0Fu) + 0x30u, (uint8_t)(HWV & 0x0Fu) + 0x30u};

//引导程序版本信息 F180
uint8_t MCU_FBLversion[6] = {'B', 'V', (uint8_t)((BTV >> 8u) & 0x0Fu) + 0x30u, '.', (uint8_t)((BTV >> 4u) & 0x0Fu) + 0x30u, (uint8_t)(BTV & 0x0Fu) + 0x30u};

//零件号信息 F187
uint8_t MCU_PartNumber[16] = {'K', 'E', 'E', 'W', 'A', 'Y', '_', 'T', '0', '6', '_', 'M', 'E', 'T', 'E', 'R'};

/* internal program info */
const uint8_t DID_1024[13] =
{
    ((internal_version / 100UL) + 0x30UL),
    '.',
    (((internal_version / 10UL) % 10UL) + 0x30UL),
    ((internal_version % 10UL) + 0x30UL),
    '_',
    ((internal_date / 10000000UL) + 0x30),
    (((internal_date / 1000000UL) % 10UL) + 0x30),
    (((internal_date / 100000UL) % 10UL) + 0x30),
    (((internal_date / 10000UL) % 10UL) + 0x30),
    (((internal_date / 1000UL) % 10UL) + 0x30),
    (((internal_date / 100UL) % 10UL) + 0x30),
    (((internal_date / 10UL) % 10UL) + 0x30),
    ((internal_date % 10UL) + 0x30)
};

/*写App有效性标志*/
void Write_App_InValid(uint32_t m32)
{
	//设置App状态值
    DiagDataForFlag.Flag = 0xA77A5AA5u;
    DiagDataForFlag.APP_STATUS = m32;
	EraseSector (FLASH_APP_STATUS_INFO);
    ProgramPage (FLASH_APP_STATUS_INFO, 8U, (uint8_t *)(&DiagDataForFlag));
}

void S3_ServerCNTT(void)
{
    if ( S3_ServerEN == 1 )
    {
        if ( S3_Server_refresh == 1 )
        {
            S3_Server_refresh = 0;
            S3_ServerCnt      = 0;
        }

        if ( S3_ServerCnt >= S3_SERVER )
        {
            DIAG_InitParameter( );
        }
        else
        {
            ++S3_ServerCnt;
        }
    }
}

uint8_t SerXXNRC12Filter(uint8_t insub, const uint8_t *supportsub, uint8_t size, uint8_t *index)
{
    uint8_t sub     = insub;
    uint8_t i       = 0;
    uint8_t nrccode = 0;

    if ( size > 0 )
    {
        nrccode = subFunctionNotSupported;
        while ( i < size )
        {
            if ( supportsub [ i ] == sub )
            {
                nrccode = 0;
                *index  = i;
                break;
            }
            i++;
        }
    }
    else
    {
        *index = 0;
    }

    return nrccode;
}

uint8_t SerXXNRC13Filter(uint8_t type, uint8_t serlength, const uint8_t *length, uint8_t index)
{
    uint8_t nrccode;
    nrccode = incorrectMessageLength;

    if ( 0 == type )
    {
        if ( length != 0 )
        {
            if ( length [ 0 ] <= serlength )
            {
                nrccode = 0;
            }
        }
        else
        {
            nrccode = incorrectMessageLength;
        }
    }
    else
    {
        if ( length != 0 )
        {
            if ( length [ index ] == serlength )
            {
                nrccode = 0;
            }
        }
        else
        {
            nrccode = incorrectMessageLength;
        }
    }
    return nrccode;
}

uint8_t SerXXNRC22Filter(void)
{
    uint8_t nrccode = 0;
    nrccode         = 0;

    return nrccode;
}

uint8_t SerXXNRC31DIDFilter(uint16_t inDID, const uint16_t *DIDList, uint8_t size, uint8_t *index)
{
    uint8_t nrccode = 0;
    uint8_t i       = 0;

    if ( size > 0 )
    {
        nrccode = requestOutOfRange;
        while ( i < size )
        {
            if ( inDID == DIDList [ i ] )
            {
                nrccode = 0;
                *index  = i;
                break;
            }
            else
            {
                ++i;
            }
        }
    }
    return nrccode;
}

uint8_t SerXXNRC7EFilter(const uint8_t *SubSupportSession, uint8_t index)
{
    uint8_t nrccode;
    nrccode = 0;

    if ( 0 == (GetCurrentSession( ) & SubSupportSession [ index ]) )
    {
        nrccode = subfunctionNotSupportinActiveSession;
    }
    return nrccode;
}

uint8_t SerXXNRC7FFilter(uint8_t SupportSession)
{
    uint8_t nrccode;
    nrccode = 0;

    if ( 0 == (GetCurrentSession( ) & SupportSession) )
    {
        nrccode = serviceNotSupportedInActiveSession;
    }
    return nrccode;
}

uint8_t GetCurrentSession(void)
{
    uint8_t SessionMode;
    if ( DefaultSession == SessionType )
    {
        SessionMode = DefaultMode;
    }
    else if ( ProgrammingSession == SessionType )
    {
        SessionMode = ProgrammingMode;
    }
    else if ( ExtendedDiagnosticSession == SessionType )
    {
        SessionMode = ExtendedDiagnosticMode;
    }
    else
    {
        SessionType = DefaultSession;
        SessionMode = DefaultMode;
    }
    return SessionMode;
}

/******************************************************************************
 10# - DiagnosticSessionControl
 ******************************************************************************/
static const uint8_t Ser10BanResponse          = AbleResponseType;
static const uint8_t Ser10Sub []               = {DefaultSession, ProgrammingSession, ExtendedDiagnosticSession};
static const uint8_t Ser10MinLen []            = {1};
static const uint8_t Ser10SubLen []            = {1, 1, 1};
static const uint8_t Ser10SupportSession       = DefaultMode | ProgrammingMode | ExtendedDiagnosticMode;
static const uint8_t Ser10SubSupportSession [] = {DefaultMode | ProgrammingMode | ExtendedDiagnosticMode, ProgrammingMode | ExtendedDiagnosticMode,
                                                  DefaultMode | ExtendedDiagnosticMode};
void UDS_Service_10_Indication(uint16_t A_TA_type, uint16_t A_Length, uint8_t *A_Data)
{
    uint8_t i;
    uint8_t si = DiagnosticSessionControl;
    uint8_t NrcCode = 0;
    uint8_t Index = 0;
    uint8_t SubFunction = 0;
    uint16_t Service10DiagDataLength = A_Length;
    uint16_t FunorPhy = A_TA_type;

    for (i = 0; i < Service10DiagDataLength; ++i)
    {
        UDS_ISO14229_Transfer[i] = *(A_Data + i);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC7FFilter(Ser10SupportSession);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC13Filter(MinLengthType, Service10DiagDataLength, Ser10MinLen, Index);
    }

    if (0 == NrcCode)
    {
        if (Ser10BanResponse == AbleResponseType)
        {
            SubFunction = UDS_ISO14229_Transfer[0] & 0x7F;
        }
        else
        {
            SubFunction = UDS_ISO14229_Transfer[0];
        }
        NrcCode = SerXXNRC12Filter(SubFunction, Ser10Sub, sizeof(Ser10Sub), &Index);
    }

    if ((0 == NrcCode) && (DIAG_ID_Rx_FUN == FunorPhy) && (ProgrammingSession == Ser10Sub[Index]))
    {
        NrcCode = subFunctionNotSupported;
    }

    if (0 == NrcCode && (Index < sizeof(Ser10SubSupportSession)))
    {
        NrcCode = SerXXNRC7EFilter(Ser10SubSupportSession, Index);
    }

    if (0 == NrcCode && (Index < sizeof(Ser10SubLen)))
    {
        NrcCode = SerXXNRC13Filter(SubLengthType, Service10DiagDataLength, Ser10SubLen, Index);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC22Filter();
    }

    if (0 == NrcCode)
    {
        UDS_ISO14229_Transfer[1] = 0;
        UDS_ISO14229_Transfer[2] = 50;
        UDS_ISO14229_Transfer[3] = 0;
        UDS_ISO14229_Transfer[4] = 200;
        if (DefaultSession == SubFunction)
        {
            S3_ServerEN = 0;
            SessionType = DefaultSession;
            DIAG_InitParameter();
            CAN_RX_SetEnable(&CAN_CH0_CanMsgOp, CAN_N_RX_Enable);
            CAN_TX_SetEnable(&CAN_CH0_CanMsgTxOp, CAN_N_TX_Enable);//切会话解除


            if (AbleResponseType == Ser10BanResponse)
            {
                if (bit_is_clear(UDS_ISO14229_Transfer[0], 7))
                {
                    UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 5, UDS_ISO14229_Transfer);
                }
            }
            else
            {
                UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 5, UDS_ISO14229_Transfer);
            }
        }
        else if (ProgrammingSession == SubFunction)
        {
            S3_ServerEN = 1;
            S3_Server_refresh = 1;
            SessionType = ProgrammingSession;

            if (AbleResponseType == Ser10BanResponse)
            {
                if (bit_is_clear(UDS_ISO14229_Transfer[0], 7))
                {
                    NegRes.code = requestCorrectlyReceivedResponsePending;
                    UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));

                    Write_App_InValid(Jump_To_Boot_Need_Answer);

                    for (i = 0; i < 250; ++i)
                    {
                        __NOP();
                    }
                    __NVIC_SystemReset();
                }
                else
                {
                    Write_App_InValid(Jump_To_Boot_No_Answer);
                    for (i = 0; i < 250; ++i)
                    {
                        __NOP();
                    }
                    __NVIC_SystemReset();
                }
            }
            else
            {
                NegRes.code = requestCorrectlyReceivedResponsePending;
                UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
                Write_App_InValid(Jump_To_Boot_Need_Answer);
                for (i = 0; i < 250; ++i)
                {
                    __NOP();
                }
                __NVIC_SystemReset();
            }
        }
        else if (ExtendedDiagnosticSession == SubFunction)
        {
            S3_ServerEN = 1;
            S3_Server_refresh = 1;
            SessionType = ExtendedDiagnosticSession;

            if (AbleResponseType == Ser10BanResponse)
            {
                if (bit_is_clear(UDS_ISO14229_Transfer[0], 7))
                {
                    UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 5, UDS_ISO14229_Transfer);
                }
            }
            else
            {
                UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 5, UDS_ISO14229_Transfer);
            }
        }
    }
    else
    {
        if (DIAG_ID_Rx_FUN == FunorPhy)
        {
            if ((NrcCode != 0x11) && (NrcCode != 0x12) && (NrcCode != 0x13) && (NrcCode != 0x7E) && (NrcCode != 0x7F) && (NrcCode != 0x31))
            {
                NegRes.code = NrcCode;
                UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
                return;
            }
        }
        else
        {
            NegRes.code = NrcCode;
            UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
            return;
        }
    }
}

/******************************************************************************
 11# - ECUReset
 ******************************************************************************/
static const uint8_t Ser11BanResponse          = AbleResponseType;
static const uint8_t Ser11Sub []               = {HardReset};
static const uint8_t Ser11MinLen []            = {1};
static const uint8_t Ser11SubLen []            = {1};
static const uint8_t Ser11SupportSession       = ProgrammingMode | ExtendedDiagnosticMode;
static const uint8_t Ser11SubSupportSession [] = {ProgrammingMode | ExtendedDiagnosticMode};
void UDS_Service_11_Indication(uint16_t A_TA_type, uint16_t A_Length, uint8_t *A_Data)
{
    uint8_t si = ECUReset;
    uint8_t NrcCode = 0;
    uint8_t Index = 0;
    uint8_t SubFunction = 0;
    uint16_t i;
    uint16_t Service11DiagDataLength = A_Length;
    uint16_t FunorPhy = A_TA_type;

    for (i = 0; i < Service11DiagDataLength; ++i)
    {
        UDS_ISO14229_Transfer[i] = *(A_Data + i);
    }

    if ((0 == NrcCode) && (DIAG_ID_Rx_FUN == FunorPhy))
    {
        NrcCode = serviceNotSupported;
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC7FFilter(Ser11SupportSession);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC13Filter(MinLengthType, Service11DiagDataLength, Ser11MinLen, Index);
    }

    if (0 == NrcCode)
    {
        if (AbleResponseType == Ser11BanResponse)
        {
            SubFunction = UDS_ISO14229_Transfer[0] & 0x7F;
        }
        else
        {
            SubFunction = UDS_ISO14229_Transfer[0];
        }
        NrcCode = SerXXNRC12Filter(SubFunction, Ser11Sub, sizeof(Ser11Sub), &Index);
    }

    if (0 == NrcCode && (Index < sizeof(Ser11SubSupportSession)))
    {
        NrcCode = SerXXNRC7EFilter(Ser11SubSupportSession, Index);
    }

    if (0 == NrcCode && (Index < sizeof(Ser11SubLen)))
    {
        NrcCode = SerXXNRC13Filter(SubLengthType, Service11DiagDataLength, Ser11SubLen, Index);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC22Filter();
    }

    if (0 == NrcCode)
    {
        if (HardReset == SubFunction)
        {
            if (AbleResponseType == Ser11BanResponse)
            {
                if (bit_is_clear(UDS_ISO14229_Transfer[0], 7))
                {
                    UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 1, UDS_ISO14229_Transfer);
                }
            }
            else
            {
                UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 1, UDS_ISO14229_Transfer);
            }
            i = 900;
            while (--i)
            {
                __NOP();
            }
            __NVIC_SystemReset();
        }
    }
    else
    {
        if (DIAG_ID_Rx_FUN == FunorPhy)
        {
            if ((NrcCode != 0x11) && (NrcCode != 0x12) && (NrcCode != 0x13) && (NrcCode != 0x7E) && (NrcCode != 0x7F) && (NrcCode != 0x31))
            {
                NegRes.code = NrcCode;
                UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
                return;
            }
        }
        else
        {
            NegRes.code = NrcCode;
            UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
            return;
        }
    }
}

/******************************************************************************
 22# - ReadDataByIdentifier
 ******************************************************************************/
static const uint8_t Ser22BanResponse = DisableResponseType;
static const uint8_t Ser22Sub []      = {0xFF};
static const uint8_t Ser22MinLen []   = {2};
static const uint8_t Ser22SubLen []   = {2};
static const uint16_t Ser22DIDList [] = {0xF195, 0xF193, 0xF180, 0xF187, 0x1024, 0x1028, 0xF184,/*0x2024*/ };
static const uint8_t Ser22SupportSession       = DefaultMode | ProgrammingMode | ExtendedDiagnosticMode;
static const uint8_t Ser22SubSupportSession [] = {DefaultMode | ProgrammingMode | ExtendedDiagnosticMode};
void UDS_Service_22_Indication(uint16_t A_TA_type, uint16_t A_Length, uint8_t *A_Data)
{
    uint8_t i;
    uint8_t si = ReadDataByIdentifier;
    uint8_t NrcCode = 0;
    uint8_t Index = 0;
    uint8_t SubFunction = 0;
    uint16_t DID;
    uint16_t Service22DiagDataLength = A_Length;
    uint16_t FunorPhy = A_TA_type;

    for (i = 0; i < Service22DiagDataLength; ++i)
    {
        UDS_ISO14229_Transfer[i] = *(A_Data + i);
    }

    if ((0 == NrcCode) && (DIAG_ID_Rx_FUN == FunorPhy))
    {
        NrcCode = serviceNotSupported;
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC7FFilter(Ser22SupportSession);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC13Filter(MinLengthType, Service22DiagDataLength, Ser22MinLen, Index);
    }

    if (0 == NrcCode)
    {
        if (AbleResponseType == Ser22BanResponse)
        {
            SubFunction = UDS_ISO14229_Transfer[0] & 0x7F;
        }
        else
        {
            SubFunction = UDS_ISO14229_Transfer[0];
        }
        NrcCode = SerXXNRC12Filter(SubFunction, Ser22Sub, 0, &Index);
    }

    if (0 == NrcCode && (Index < sizeof(Ser22SubSupportSession)))
    {
        NrcCode = SerXXNRC7EFilter(Ser22SubSupportSession, Index);
    }

    if (0 == NrcCode && (Index < sizeof(Ser22SubLen)))
    {
        NrcCode = SerXXNRC13Filter(SubLengthType, Service22DiagDataLength, Ser22SubLen, Index);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC22Filter();
    }

    if (0 == NrcCode)
    {
        DID = ((uint16_t)UDS_ISO14229_Transfer[0] << 8) | UDS_ISO14229_Transfer[1];
        NrcCode = SerXXNRC31DIDFilter(DID, Ser22DIDList, (sizeof(Ser22DIDList) / 2), &Index);
    }

    if (0 == NrcCode)
    {
        switch (DID)
        {
        case 0xF195: // 读软件版本号
            for (i = 0; i < 6; i++)
            {
                UDS_ISO14229_Transfer[i + 2] = MCU_SWversion[i];
            }
            UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 2 + 6, UDS_ISO14229_Transfer);
            break;

        case 0xF193: // 读硬件版本号
            for (i = 0; i < 6; i++)
            {
                UDS_ISO14229_Transfer[i + 2] = MCU_HWversion[i];
            }
            UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 2 + 6, UDS_ISO14229_Transfer);
            break;
        case 0xF180: // 读硬件版本号
            for (i = 0; i < 6; i++)
            {
                UDS_ISO14229_Transfer[i + 2] = MCU_FBLversion[i];
            }
            UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 2 + 6, UDS_ISO14229_Transfer);
            break;

        case 0xF187: // 读零件号
            for (i = 0; i < 16; i++)
            {
                UDS_ISO14229_Transfer[i + 2] = MCU_PartNumber[i];
            }
            UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 2 + 16, UDS_ISO14229_Transfer);
            break;

        case 0x1024: // 读内部版本号
            (void)memcpy(&UDS_ISO14229_Transfer[2], DID_1024, sizeof(DID_1024));
            UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 2 + sizeof(DID_1024), UDS_ISO14229_Transfer);
            break;

        // case 0x2024: // ESP32内部版本号
        //     UDS_ISO14229_Transfer[3] = BlueTooth.ESP32_SWV;
        //     UDS_Service_Response(0x22, POSITIVE_RSP, DIAG_ID_Tx, 2 + 1, UDS_ISO14229_Transfer);
        //     break;

        default:
            if (FunorPhy == DIAG_ID_Rx_FUN)
            {
                return;
            }
            NegRes.code = requestOutOfRange;
            UDS_Service_Response ( 0x22, NEGATIVE_RSP, DIAG_ID_Tx, 1, ( uint8_t * ) ( &NegRes.code ) );
            break;
        }
    }
    else
    {
        if (DIAG_ID_Rx_FUN == FunorPhy)
        {
            if ((NrcCode != 0x11) && (NrcCode != 0x12) && (NrcCode != 0x13) && (NrcCode != 0x7E) && (NrcCode != 0x7F) && (NrcCode != 0x31))
            {
                NegRes.code = NrcCode;
                UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
                return;
            }
        }
        else
        {
            NegRes.code = NrcCode;
            UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
            return;
        }
    }
}

/******************************************************************************
 3E# - TesterPresent
 ******************************************************************************/
static const uint8_t Ser3EBanResponse          = AbleResponseType;
static const uint8_t Ser3ESub []               = {0x00};
static const uint8_t Ser3EMinLen []            = {1};
static const uint8_t Ser3ESubLen []            = {1};
static const uint8_t Ser3ESupportSession       = DefaultMode | ProgrammingMode | ExtendedDiagnosticMode;
static const uint8_t Ser3ESubSupportSession [] = {DefaultMode | ProgrammingMode | ExtendedDiagnosticMode};
void UDS_Service_3E_Indication(uint16_t A_TA_type, uint16_t A_Length, uint8_t *A_Data)
{
    uint8_t i;
    uint8_t si = TesterPresent;
    uint8_t NrcCode = 0;
    uint8_t Index = 0;
    uint8_t SubFunction = 0;
    uint16_t Service3EDiagDataLength = A_Length;
    uint16_t FunorPhy = A_TA_type;

    for (i = 0; i < Service3EDiagDataLength; ++i)
    {
        UDS_ISO14229_Transfer[i] = *(A_Data + i);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC7FFilter(Ser3ESupportSession);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC13Filter(MinLengthType, Service3EDiagDataLength, Ser3EMinLen, Index);
    }

    if (0 == NrcCode)
    {
        if (AbleResponseType == Ser3EBanResponse)
        {
            SubFunction = UDS_ISO14229_Transfer[0] & 0x7F;
        }
        else
        {
            SubFunction = UDS_ISO14229_Transfer[0];
        }
        NrcCode = SerXXNRC12Filter(SubFunction, Ser3ESub, sizeof(Ser3ESub), &Index);
    }

    if (0 == NrcCode && (Index < sizeof(Ser3ESubSupportSession)))
    {
        NrcCode = SerXXNRC7EFilter(Ser3ESubSupportSession, Index);
    }

    if (0 == NrcCode && (Index < sizeof(Ser3ESubLen)))
    {
        NrcCode = SerXXNRC13Filter(SubLengthType, Service3EDiagDataLength, Ser3ESubLen, Index);
    }

    if (0 == NrcCode)
    {
        NrcCode = SerXXNRC22Filter();
    }

    if (0 == NrcCode)
    {
        if (0x00 == SubFunction)
        {
            S3_Server_refresh = 1;
            if (AbleResponseType == Ser3EBanResponse)
            {
                if (bit_is_clear(UDS_ISO14229_Transfer[0], 7))
                {
                    UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 1, UDS_ISO14229_Transfer);
                }
            }
            else
            {
                UDS_Service_Response(si, POSITIVE_RSP, DIAG_ID_Tx, 1, UDS_ISO14229_Transfer);
            }
        }
    }
    else
    {
        if (DIAG_ID_Rx_FUN == FunorPhy)
        {
            if ((NrcCode != 0x11) && (NrcCode != 0x12) && (NrcCode != 0x13) && (NrcCode != 0x7E) && (NrcCode != 0x7F) && (NrcCode != 0x31))
            {
                NegRes.code = NrcCode;
                UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
                return;
            }
        }
        else
        {
            NegRes.code = NrcCode;
            UDS_Service_Response(si, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
            return;
        }
    }
}

/*************IGN on,S3 Timeout****************/
void DIAG_InitParameter(void)
{
    S3_ServerCnt = 0;
    S3_ServerEN  = 0;
    SessionType  = DefaultSession;
}

void Get_Into_630H_Update_MCU_Mode(void)
{
    uint8_t i;
    Write_App_InValid(Flag_App_OTAStatus);
    for (i = 0; i < 250; ++i)
    {
        __NOP();
    }
    __NVIC_SystemReset();
}