#include "common.h"
#include "TP_Layer.h"
#include "app_Service.h"
#include "Link_Layer.h"
#include "UDS_def.h"

#include "UDS_CFG.h"
#include "app_ServiceProc.h"
#include <string.h>
#include "CAN_User.h"
#include "Analog_Signals.h"
#include "flash.h"


#define GLOBALS_UDS_CFG
#define GLOBALS_USER_DEF

volatile _DiagnoCtl DiagnoCtl;  //诊断当前状态
volatile _N_USData Exct_USData; //报文接收的ID数据
volatile _DiagClock DiagClock;
volatile _ErrorFrame Error; //错误信息
_DiagReciveDTC DiagReciveDTC;
_DiagReciveGaugePara DiagReciveGaugePara;
volatile uint32_t CrcCheckSum;

uint8_t NormalCanSt = 0;
uint8_t NMCanSt = 0;
const uint8_t XorArray[4] = {0x31, 0x23, 0x56, 0x71};
uint32_t CalculateKey ( uint8_t *Seed );
uint32_t CalculateKeyLv11 ( uint8_t *Seed );
#define KeyK  0x0000000F
#define Flag_App_Answer     0xA77A3AA3     //0xA77A3AA3
#define Flag_App_NoAnswer   0xA77A8AA8

//软件版本号 F195
//uint8_t  MCU_SWversion[6]   =  {
//	'1',//‘1’表示工装样阶段，'2'表示量产阶段；
//	'0',//版本
//	23,//年
//	8,//月
//	17, //日 
//  6};//次

//硬件版本号 F193
uint8_t  MCU_HWversion[5]    ={
	102,	//2.0.0
	23,	  //年
	11,   //月
	24,    //日
	0};   //无扩展信息

//软件编码 F194  20230113
uint8_t  MCU_SoftCode[6]   =  {
		0x36,//表示软件供应商
		0x06,//ECU 仪表 
		'X', //车型
		'X',//代码
		'X',//代码
		0x00};//无扩展信息

//引导版本信息 F180
uint8_t  MCU_FBLversion[9]    ={
	23,  	//年
	52,	//周
	1,	//次	
	10,   	//版本
	0x64,	//MCU
	0xFB,	//MCU
	23,		//年
	9,		//月
	26}; 	//日
		
			
/*-------------------------------------------------------------------------
* Function Name  : DiagnosisInit_main
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void DiagnosisInit_main(void)
{

    N_US_R_MultiData.ind.N_Result = STATE0;
    N_US_S_MultiData.ind.N_Result = STATE0;
    N_USSFData[0].ind.N_Result = STATE0;
    N_USSFData[1].ind.N_Result = STATE0;
    Exct_USData.ind.N_Result = STATE0;
    N_RSPData.ind.N_Result = STATE0;
    LinkDataBuf[0].TransferStatus = empoty;
    LinkDataBuf[1].TransferStatus = empoty;

    DiagnoCtl.SubFunction = 0;
    DiagnoCtl.CommCtl = SubEnableRxAndTx;
    DiagnoCtl.SessionType = DefSession;
    DiagnoCtl.AccessLock = Lock;
    DiagnoCtl.N_REV_MAX_BS = MaxBuff / 8;
    DiagnoCtl.N_STmin = 20;
    DiagnoCtl.DTCSettingType = DtcSetOn;
    DiagnoCtl.tDiagStart = 0;
    DiagnoCtl.DTCByStatusMask = 0x09; //0x08已确认的诊断故障代码
                                      //0x01测试失败

    Error.FrameErr = 0;

    TP_SetSTminTimer(DiagnoCtl.N_STmin, (_DiagClock *)&DiagClock);
}
/*-------------------------------------------------------------------------
* Function Name  : App_Load_DTCNum
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_Load_DTCNum(uint32_t *DtcNum, uint8_t *data)
{
    *(DtcNum) = data[0];
    *(DtcNum) = *(DtcNum) << 8;
    *(DtcNum) |= data[1];
    *(DtcNum) = *(DtcNum) << 8;
    *(DtcNum) |= data[2];
    //*(DtcNum) = *(DtcNum);
}

/*-------------------------------------------------------------------------
* Function Name  : Diagnosis_main
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void Diagnosis_main(void)
{
    TP_Buffer_handle();
    if (LinkData.TransferStatus == full)
    {
        TP_ReciveSF_handle();
        TP_ReciveMultiF_handle();

        TP_NormalRecFC_handle();
        LinkData.TransferStatus = empoty;
    }

    TP_NormalSendFC_Fun();

    if (N_USSFData[0].ind.N_Result == N_OK)
    {
        App_CopyRam((uint8_t *)&Exct_USData, (uint8_t *)&N_USSFData[0], sizeof(_N_USSFData));
        Exct_USData.ind.N_Result = N_OK;
        N_USSFData[0].ind.N_Result = STATE0;
    }
    else if ((N_USSFData[1].ind.N_Result == N_OK) && (Exct_USData.ind.N_Result == STATE0))
    {
        App_CopyRam((uint8_t *)&Exct_USData, (uint8_t *)&N_USSFData[1], sizeof(_N_USSFData));
        Exct_USData.ind.N_Result = N_OK;
        N_USSFData[1].ind.N_Result = STATE0;
    }
    else if ((N_US_R_MultiData.ind.N_Result == N_OK) && (Exct_USData.ind.N_Result == STATE0) &&
             (N_US_S_MultiData.ind.N_Result == STATE0))
    {
        App_CopyRam((uint8_t *)&Exct_USData, (uint8_t *)&N_US_R_MultiData, sizeof(_N_USData));
        N_US_R_MultiData.ind.N_Result = STATE0;
    }

    if (N_US_S_Data_FF.ind.N_PCI == FC_WAIT)
    {
        if (TP_BsTimerOver((_DiagClock *)&DiagClock))
        {
            N_US_S_MultiData.ind.N_Result = N_TIMEOUT_Bs;
        }
    }

    if (N_US_S_MultiData.ind.N_Result == STATE0)
    {
        DiagClock.TT_BsEnable = 0;
        N_US_S_Data_FF.ind.N_FC_Num = 0;
    }

    if (N_US_R_MultiData.ind.N_Result == N_OK)
    {
        N_US_R_Data_FF.ind.pos = 0;
        N_US_R_Data_FF.ind.N_PCI = 0;
    }
    if ((N_US_R_MultiData.ind.N_Result == N_TIMEOUT_Bs) || (N_US_R_MultiData.ind.N_Result == N_WRONG_SN))
    {
        N_US_R_MultiData.ind.N_Result = STATE0;
        N_US_R_Data_FF.ind.pos = 0;
        N_US_R_Data_FF.ind.N_PCI = 0;
        N_US_R_Data_FF.ind.N_RecSN_L = 0;
    }

    if ((N_US_S_MultiData.ind.N_Result == N_TIMEOUT_Bs) ||
        (N_US_S_MultiData.ind.N_Result == OVFLW) ||
        (N_US_S_MultiData.ind.N_Result == N_INVALID_FS))
    {
        N_US_S_MultiData.ind.N_Result = STATE0;
        N_US_S_Data_FF.ind.N_PCI = 0;
        N_US_S_Data_FF.ind.N_SID = 0;
        N_US_S_Data_FF.ind.N_BS_CNT = 0;
    }

    if (App_SessionTimerOver((_DiagClock *)&DiagClock))
    {
        DiagnoCtl.SessionType = DefSession;
        DiagnoCtl.A5_Sequence = 0;
        //	DiagnoCtl.SubFunction = SubHardReset;  
    }
    if (App_ReUnlockTimerOver((_DiagClock *)&DiagClock))
    {
        DiagnoCtl.AccessCount = 0;
    }
    if (DiagnoCtl.SessionType == DefSession)
    {
        DiagnoCtl.AccessLock = Lock;
        // DiagnoCtl.CommCtl = SubEnableRxAndTx;
        DiagnoCtl.CommType = NOR_NM_Message;

        DiagnoCtl.DTCSettingType = DtcSetOn;
    }

    if (Exct_USData.ind.N_Result == N_OK)
    {
        switch (Exct_USData.ind.N_TAtype)
        {

        case ID_FunAddr:
            switch (Exct_USData.ind.MsgData[0])
            {
                case ReqSessionCtlId:
                    App_10_service((_N_USData*)&Exct_USData);
                    break;
                case ReqECUResetId:
                    App_11_service((_N_USData*)&Exct_USData);
                    break;
                case ReqReadDataId:
                    App_22_service((_N_USData*)&Exct_USData);
                    break;
                case ReqTesterId:
                    App_3E_service((_N_USData*)&Exct_USData);
                     break;
                case ReqCtlDTCSetId:
                    App_85_service((_N_USData*)&Exct_USData);
                     break;   
                case ReqCommCtlId:
                    App_28_service((_N_USData*)&Exct_USData);
                     break;  
                default:
                    break;
            }
        case ID_PhyAddr:
            switch (Exct_USData.ind.MsgData[0])
            {
                case ReqSessionCtlId:
                    App_10_service((_N_USData*)&Exct_USData);
                    break;
                case ReqECUResetId:
                    App_11_service((_N_USData*)&Exct_USData);
                    break;
                case ReqReadDataId:
                    App_22_service((_N_USData*)&Exct_USData);
                    break;
                case ReqAccessId:
                    App_27_service((_N_USData*)&Exct_USData);
                    break;
                case ReqWriteDataId:
                    App_2E_service((_N_USData*)&Exct_USData);
                    break;
                case ReqTesterId:
                    App_3E_service((_N_USData*)&Exct_USData);
                     break;
                case ReqCtlDTCSetId:
                    App_85_service((_N_USData*)&Exct_USData);
                     break;   
                case ReqCommCtlId:
                    App_28_service((_N_USData*)&Exct_USData);
                     break;  
                default:
                    Error.N_TAtype = ID_PhyAddr;
                    Error.FrameErr = ServiceNotSupported; //服务不支持
                    Error.RespSerId = Exct_USData.ind.MsgData[0];
                    break;
            }
            break;
        default:;
        }
        Exct_USData.ind.N_Result = STATE0;
    }

    TP_TransmitPDU(); //仪表诊断回复
    App_11_Reset_handle();
}

/*-------------------------------------------------------------------------
* Function Name  : App_10_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_10_service(_N_USData *AppUSData)
{
    _SubFun SubFun;
    uint8_t buf[4];
    App_ErrorInfoInit((_N_USData *)AppUSData);

    SubFun.SubData = AppUSData->ind.MsgData[1];

    if (AppUSData->ind.Length == 0x02) //请求命令的字节长度 2个  10 01
    {
        if (DiagnoCtl.SessionType == SubDefSession) //当前为默认会话模式
        {
            if ((SubFun.SubBits.SubFunBit0_6 & 0xf) == SubDefSession) //请求命令子功能 01
            {
                DiagnoCtl.AccessLock = Lock;        //上锁
                DiagnoCtl.SessionType = DefSession; //默认模式
                if (DiagnoCtl.SessionType != SubFun.SubBits.SubFunBit0_6)
                {
                    DiagnoCtl.SessionType = SubFun.SubBits.SubFunBit0_6;
                    DiagnoCtl.A5_Sequence = 0;
                }
            }
            else if ((SubFun.SubBits.SubFunBit0_6 & 0xf) == SubExtSession) //请求命令子功能 03
            {
                DiagnoCtl.AccessLock = Lock;
                if (DiagnoCtl.SessionType != SubFun.SubBits.SubFunBit0_6)
                {
                    DiagnoCtl.SessionType = SubFun.SubBits.SubFunBit0_6;
                    DiagnoCtl.A5_Sequence = 0;
                }

                App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
            }
            else
            {
                Error.FrameErr = SubFunctionNotSupported; //子功能不支持 10 04
            }
        }
        else if (DiagnoCtl.SessionType == SubExtSession) //当前编程模式
        {
            if ((SubFun.SubBits.SubFunBit0_6 & 0xf) == SubDefSession)
            {
                DiagnoCtl.AccessLock = Lock;
                DiagnoCtl.SessionType = DefSession;
                if (DiagnoCtl.SessionType != SubFun.SubBits.SubFunBit0_6)
                {
                    DiagnoCtl.SessionType = SubFun.SubBits.SubFunBit0_6;
                    DiagnoCtl.A5_Sequence = 0;
                }
            }
            else if ((SubFun.SubBits.SubFunBit0_6 & 0xf) == SubExtSession)
            {
                DiagnoCtl.AccessLock = Lock;
                if (DiagnoCtl.SessionType != SubFun.SubBits.SubFunBit0_6)
                {
                    DiagnoCtl.SessionType = SubFun.SubBits.SubFunBit0_6;
                    DiagnoCtl.A5_Sequence = 0;
                }

                App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
            }
            else if ((SubFun.SubBits.SubFunBit0_6 & 0xf) == SubProgSession)
            {
                DiagnoCtl.AccessLock = Lock;
                if (DiagnoCtl.SessionType != SubFun.SubBits.SubFunBit0_6)
                {
                    DiagnoCtl.SessionType = SubFun.SubBits.SubFunBit0_6;
                    DiagnoCtl.A5_Sequence = 0;

                    DiagnoCtl.SubFunction = SubHardReset;
                    EraseSector (0x500400);
                    buf[0]=(uint8_t)(Flag_App_Answer>>24);
                    buf[1]=(uint8_t)(Flag_App_Answer>>16);
                    buf[2]=(uint8_t)(Flag_App_Answer>>8);
                    buf[3]=(uint8_t)(Flag_App_Answer);

                    EraseSector (0x500400);
                    ProgramPage (0x500400,4,(uint8_t *)buf);
                    Error.FrameErr=0x78;
                }

                App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
            }
            else
            {
                Error.FrameErr = SubFunctionNotSupported; //子功能不支持
            }
        }
        else if (DiagnoCtl.SessionType == SubProgSession) //当前为扩展模式
        {
            if ((SubFun.SubBits.SubFunBit0_6 & 0xf) == SubDefSession)
            {
                DiagnoCtl.AccessLock = Lock;
                DiagnoCtl.SessionType = DefSession;
                if (DiagnoCtl.SessionType != SubFun.SubBits.SubFunBit0_6)
                {
                    DiagnoCtl.SessionType = SubFun.SubBits.SubFunBit0_6;
                    DiagnoCtl.A5_Sequence = 0;
                }
                DiagnoCtl.SubFunction = SubHardReset;
            }
            else if ((SubFun.SubBits.SubFunBit0_6 & 0xf) == SubProgSession)
            {
                DiagnoCtl.AccessLock = Lock;
                if (DiagnoCtl.SessionType != SubFun.SubBits.SubFunBit0_6)
                {
                    DiagnoCtl.SessionType = SubFun.SubBits.SubFunBit0_6;
                    DiagnoCtl.A5_Sequence = 0;
                }

                App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
            }
            else
            {
                Error.FrameErr = SubFunctionNotSupported; //子功能不支持
            }
        }
    }
    else
    {
        Error.FrameErr = ErrFormatLength; //长度不对
    }

    //格式正确，返回正确      头 + 50 01 00 32 01 F4
    if (Error.FrameErr == 0)
    {
        if (!SubFun.SubBits.SubFunBit7_7) //请求命令子功能 第7位为0
        {
            N_RSPData.ind.len = 7;                                       //7个字节
            N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;            //头
            N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40; //50
            N_RSPData.ind.MsgData[2] = SubFun.SubBits.SubFunBit0_6;      //01
            N_RSPData.ind.MsgData[3] = 0x00;
            N_RSPData.ind.MsgData[4] = 0x32;
            N_RSPData.ind.MsgData[5] = 0x01;
            N_RSPData.ind.MsgData[6] = 0xF4;

            N_RSPData.ind.N_Result = N_OK; //正确
        }
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_11_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_11_service(_N_USData *AppUSData)
{
    _SubFun SubFun;

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if ((DiagnoCtl.SessionType == ExtSession) ||
        (DiagnoCtl.SessionType == ProgSession))
    {
        if (AppUSData->ind.Length > 1)
        {
            SubFun.SubData = AppUSData->ind.MsgData[1];
            switch (SubFun.SubBits.SubFunBit0_6)
            {
            case SubHardReset: //11 01
                if (AppUSData->ind.Length == 0x02)
                {
                    DiagnoCtl.SubFunction = SubHardReset;
                }
                else
                {
                    Error.FrameErr = ErrFormatLength; //长度不对
                }
                break;
            case SubKeyOffOnReset: //11 02
                if (AppUSData->ind.Length == 0x02)
                {
                    DiagnoCtl.SubFunction = SubKeyOffOnReset;
                }
                else
                {
                    Error.FrameErr = ErrFormatLength; //长度不对
                }
                break;
            case SubSoftReset: //11 03
                if (AppUSData->ind.Length == 0x02)
                {
                    DiagnoCtl.SubFunction = SubSoftReset;
                }
                else
                {
                    Error.FrameErr = ErrFormatLength; //长度不对
                }
                break;
            default:
                Error.FrameErr = SubFunctionNotSupported; //子功能不支持
            }
        }
        else
        {
            Error.FrameErr = ErrFormatLength; //长度不对
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }
    if (Error.FrameErr == 0)
    {
        if (!SubFun.SubBits.SubFunBit7_7)
        {
            N_RSPData.ind.len = 3;
            N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
            N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
            N_RSPData.ind.MsgData[2] = SubFun.SubBits.SubFunBit0_6;
            N_RSPData.ind.N_Result = N_OK;
        }
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_85_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_85_service(_N_USData *AppUSData)
{
    _SubFun SubFun;

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if (DiagnoCtl.SessionType == ExtSession)
    {
        if (AppUSData->ind.Length > 1)
        {
            SubFun.SubData = AppUSData->ind.MsgData[1];

            switch (SubFun.SubBits.SubFunBit0_6)
            {
            case DtcSetOn:
                if (AppUSData->ind.Length == 0x02)
                {
                    DiagnoCtl.DTCSettingType = SubFun.SubBits.SubFunBit0_6;
                }
                else
                {
                    Error.FrameErr = ErrFormatLength; //长度不对
                }
                break;
            case DtcSetOff:
                if (AppUSData->ind.Length == 0x02)
                {
                    DiagnoCtl.DTCSettingType = SubFun.SubBits.SubFunBit0_6;
                }
                else
                {
                    Error.FrameErr = ErrFormatLength; //长度不对
                }

                break;
            default:
                Error.FrameErr = SubFunctionNotSupported; //子功能不支持
            }
        }
        else
        {
            Error.FrameErr = ErrFormatLength; //长度不对
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }
    if (Error.FrameErr == 0)
    {
        if (!SubFun.SubBits.SubFunBit7_7)
        {
            N_RSPData.ind.len = 3;
            N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
            N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
            N_RSPData.ind.MsgData[2] = SubFun.SubBits.SubFunBit0_6;
            N_RSPData.ind.N_Result = N_OK;
        }
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_27_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_27_service(_N_USData *AppUSData)
{
    uint8_t Seed[4];
    uint32_t wTemp;
    _SubFun SubFun;
    uint8_t SeedHigh;
    uint8_t SeedLow;
    
    App_ErrorInfoInit((_N_USData *)AppUSData);

    if ((DiagnoCtl.SessionType == ProgSession) || (DiagnoCtl.SessionType == SubExtSession))
    {
        if (AppUSData->ind.Length > 0x01)
        {
            SubFun.SubData = AppUSData->ind.MsgData[1];
            switch (SubFun.SubBits.SubFunBit0_6)
            {
            case 0x01: //27 01
                if (AppUSData->ind.Length == 0x02)
                {

                    if (!SubFun.SubBits.SubFunBit7_7)
                    {
                        SeedHigh = (uint8_t)ADC_Read_Signal(ADC_CH_KL30_VOLTAGE);
                        SeedLow = (uint8_t)SysTick->VAL;
                        Seed[3] = 0x31 + ~SeedHigh; 
                        Seed[2] = 0x23 + ~SeedLow;	
                        Seed[1] = 0x56 + SeedHigh;  
                        Seed[0] = 0x71 + SeedLow;  
                        
//                        Seed[0] = 0x31; 
//                        Seed[1] = 0x23;	
//                        Seed[2] = 0x56;  
//                        Seed[3] = 0x71;  
                        N_RSPData.ind.len = 7;
                        N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;            //06
                        N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40; //67
                        N_RSPData.ind.MsgData[2] = SubFun.SubBits.SubFunBit0_6;      //01
                        if ((DiagnoCtl.AccessLock == UnLockLv1) || (DiagnoCtl.AccessLock == UnLockLv2))
                        {
                            N_RSPData.ind.MsgData[3] = 0; //如果已经解锁，则回复0
                            N_RSPData.ind.MsgData[4] = 0;
                            N_RSPData.ind.MsgData[5] = 0;
                            N_RSPData.ind.MsgData[6] = 0;
                        }
                        else
                        {
                            N_RSPData.ind.MsgData[3] = Seed[0];
                            N_RSPData.ind.MsgData[4] = Seed[1];
                            N_RSPData.ind.MsgData[5] = Seed[2];
                            N_RSPData.ind.MsgData[6] = Seed[3];
                        }
                        N_RSPData.ind.N_Result = N_OK;
                    }

                            wTemp = CalculateKey(Seed);

                    DiagnoCtl.key[0] = (uint8_t)(wTemp);
                    DiagnoCtl.key[1] = (uint8_t)(wTemp >>8);
                    DiagnoCtl.key[2] = (uint8_t)(wTemp >>16);
                    DiagnoCtl.key[3] = (uint8_t)(wTemp >>24);
                    
                    DiagnoCtl.w27_Sequence = SubFun.SubBits.SubFunBit0_6;

                    if (DiagClock.TT_UnlockEnable)
                    {
                        N_RSPData.ind.len = 4;
                        N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
                        N_RSPData.ind.MsgData[1] = NegativeId;
                        N_RSPData.ind.MsgData[2] = AppUSData->ind.MsgData[0];
                        N_RSPData.ind.MsgData[3] = ReqTimeDelayNotExpired;
                        N_RSPData.ind.N_Result = N_OK;
                    }
                }
                else
                {
                    Error.FrameErr = ErrFormatLength; //长度不对
                }
                break;
            case 0x02: //27 02 解锁
            case 0x82: //27 82 解锁
            case 0x12: //27 12 解锁
            case 0x92: //27 92 解锁
                if (((DiagnoCtl.w27_Sequence == 0x01) && (SubFun.SubBits.SubFunBit0_6 == 0x02)) 
                    ||((DiagnoCtl.w27_Sequence == 0x11) && (SubFun.SubBits.SubFunBit0_6 == 0x12)))
                {
                    DiagnoCtl.w27_Sequence = SubFun.SubBits.SubFunBit0_6;
                    if (!DiagClock.TT_UnlockEnable)
                    {
                        if (AppUSData->ind.Length == 0x06)
                        {
                            if (DiagnoCtl.AccessCount < 5)
                            {
                                DiagnoCtl.AccessCount++;
                            }
                            if((AppUSData->ind.MsgData[2] == DiagnoCtl.key[3]) &&\
                               (AppUSData->ind.MsgData[3] == DiagnoCtl.key[2]) &&\
                               (AppUSData->ind.MsgData[4] == DiagnoCtl.key[1]) &&\
                               (AppUSData->ind.MsgData[5] == DiagnoCtl.key[0]) ||\
															 ((AppUSData->ind.MsgData[5] == DiagnoCtl.key[3]) &&\
                               (AppUSData->ind.MsgData[4] == DiagnoCtl.key[2]) &&\
                               (AppUSData->ind.MsgData[3] == DiagnoCtl.key[1]) &&\
                               (AppUSData->ind.MsgData[2] == DiagnoCtl.key[0])))
                            {
                                if (!SubFun.SubBits.SubFunBit7_7)
                                {
                                    N_RSPData.ind.len = 3;
                                    N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
                                    N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
                                    N_RSPData.ind.MsgData[2] = SubFun.SubBits.SubFunBit0_6;
                                    N_RSPData.ind.N_Result = N_OK;
                                }
                                if (DiagnoCtl.AccessCount <= 3)
                                {
                                    if (SubFun.SubBits.SubFunBit0_6 == 0x02) //27 _02
                                    {
                                        DiagnoCtl.AccessLock = UnLockLv1; //解锁
                                    }

                                    else if (SubFun.SubBits.SubFunBit0_6 == 0x12) //27 _12
                                    {
                                        DiagnoCtl.AccessLock = UnLockLv2; //解锁
                                    }
                                    /* else if (SubFun.SubBits.SubFunBit0_6 == SubSendKey8)
                                        {
                                            DiagnoCtl.AccessLock = UnLockLv4;
                                        }*/

                                    DiagnoCtl.AccessCount = 0;
                                }
                            }
                        }
                        else
                        {
                            Error.FrameErr = ErrFormatLength;
                        }
                    }
                }
                else
                {
                    Error.FrameErr = ReqSequenceError;
                }
                break;
            default:
                Error.FrameErr = SubFunctionNotSupported; //子功能不支持
            }

            if (Error.FrameErr == 0)
            {
                if ((DiagnoCtl.w27_Sequence == 0x02) || (DiagnoCtl.w27_Sequence == 0x12))
                {
                    DiagnoCtl.w27_Sequence = 0;

                    if ((DiagnoCtl.AccessLock != UnLockLv1) && (DiagnoCtl.AccessLock != UnLockLv2))
                    {
                        if (DiagnoCtl.AccessCount <= 1)
                        {
                            N_RSPData.ind.len = 4;
                            N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
                            N_RSPData.ind.MsgData[1] = NegativeId;
                            N_RSPData.ind.MsgData[2] = AppUSData->ind.MsgData[0];
                            N_RSPData.ind.MsgData[3] = InvalidKey; //秘钥错误
                            N_RSPData.ind.N_Result = N_OK;
                        }
                        if (DiagnoCtl.AccessCount >= 2)
                        {
                            N_RSPData.ind.len = 4;
                            N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
                            N_RSPData.ind.MsgData[1] = NegativeId;
                            N_RSPData.ind.MsgData[2] = AppUSData->ind.MsgData[0];
                            N_RSPData.ind.MsgData[3] = ExceedNumberOfAttempts;
                            N_RSPData.ind.N_Result = N_OK;

                            if (!DiagClock.TT_UnlockEnable)
                            {
                                App_SetReUnlockTimer(N_Unlock, (_DiagClock *)&DiagClock);
                            }
                        }
                    }
                }
            }
        }
        else
        {
            Error.FrameErr = ErrFormatLength; //长度不对
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession; //此会话不支持功能
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_31_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_31_service(_N_USData *AppUSData)
{

    uint8_t data = 1;
    uint16_t DID;

    _SubFun SubFun;

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if ((DiagnoCtl.SessionType == ProgSession) || (DiagnoCtl.SessionType == SubExtSession))
    {
        if (AppUSData->ind.Length > 0x01)
        {
            SubFun.SubData = AppUSData->ind.MsgData[1];
            switch (SubFun.SubBits.SubFunBit0_6)
            {
            case 1: //startRoutine
                if (AppUSData->ind.Length >= 4)
                {
                    App_Load_DID((uint16_t *)&DID, (uint8_t *)&AppUSData->ind.MsgData[2]);
                    if ((DiagnoCtl.AccessLock == UnLockLv1) || (DiagnoCtl.AccessLock == UnLockLv2))
                    {

                        if (DID == 0xFF00) //eraseMemory
                        {
                            if (AppUSData->ind.Length == 13)
                            {
                                if (AppUSData->ind.MsgData[4] == 0x44)
                                {
                                }
                                else
                                {
                                    Error.FrameErr = RequestOutOfRange;
                                }
                            }
                            else
                            {
                                Error.FrameErr = ErrFormatLength; //长度不对
                            }
                        }

                        else if (DID == 0xFF01) //checkProgrammingDependencies
                        {
                            if (AppUSData->ind.Length == 4)
                            {
                            }
                            else
                            {
                                Error.FrameErr = ErrFormatLength; //长度不对
                            }
                        }
                        else
                        {
                            Error.FrameErr = RequestOutOfRange;
                        }
                    }
                    else
                    {
                        Error.FrameErr = SecurityAccessDenied;
                    }
                }
                else
                {
                    Error.FrameErr = ErrFormatLength; //长度不对
                }
                break;
            case 2: //stopRoutine
                if (AppUSData->ind.Length == 4)
                {
                    App_Load_DID((uint16_t *)&DID, (uint8_t *)&AppUSData->ind.MsgData[2]);
                    if ((DiagnoCtl.AccessLock == UnLockLv1) || (DiagnoCtl.AccessLock == UnLockLv2))
                    {

                        if (DID == 0xFF00)
                        {
                        }

                        else
                        {
                            Error.FrameErr = RequestOutOfRange;
                        }
                    }
                    else
                    {
                        Error.FrameErr = SecurityAccessDenied;
                    }
                }
                else
                {
                    Error.FrameErr = ErrFormatLength; //长度不对
                }
                break;
            case 3: //requestRoutineResults
                if ((DiagnoCtl.AccessLock == UnLockLv1) || (DiagnoCtl.AccessLock == UnLockLv2))
                {

                    //  data = 1;
                }
                break;
            default:;
            }
        }
        else
        {
            Error.FrameErr = ErrFormatLength; //长度不对
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }

    if (Error.FrameErr == 0)
    {
        if (!SubFun.SubBits.SubFunBit7_7)
        {
            N_RSPData.ind.len = 5;
            if (DID == 0x0203)
                N_RSPData.ind.len = 8;
            N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
            N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
            N_RSPData.ind.MsgData[2] = SubFun.SubBits.SubFunBit0_6;
            N_RSPData.ind.MsgData[3] = (uint8_t)(DID >> 8);
            N_RSPData.ind.MsgData[4] = (uint8_t)DID;
            N_RSPData.ind.MsgData[5] = data;
            N_RSPData.ind.MsgData[6] = 0;
            N_RSPData.ind.MsgData[7] = 0;

            //N_RSPData.ind.N_Result = N_OK;

            (void)memcpy((uint8_t *)N_US_S_MultiData.ind.MsgData, (uint8_t *)(N_RSPData.ind.MsgData + 1), N_RSPData.ind.len);
            if (N_RSPData.ind.len >= 8)
            {
                N_US_S_Data_FF.ind.Length = N_RSPData.ind.len;
                N_US_S_Data_FF.ind.N_PCI = FirstFrame;
            }
            else
            {
                N_US_S_MultiData.ind.Length = N_RSPData.ind.len;
                N_US_S_Data_FF.ind.N_PCI = 0;
            }
            N_US_S_MultiData.ind.N_Result = N_OK;
        }
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_34_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_34_service(_N_USData *AppUSData)
{

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if (DiagnoCtl.SessionType == ProgSession)
    {
        if (DiagnoCtl.AccessLock == UnLockLv2)
        {
            if (AppUSData->ind.Length == 11)
            {
            }
            else
            {
                Error.FrameErr = ErrFormatLength; //长度不对
            }
        }
        else
        {
            Error.FrameErr = SecurityAccessDenied;
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }
    if (DiagnoCtl.AccessLock == UnLockLv2)
    {
        if (Error.FrameErr == 0)
        {
            N_RSPData.ind.len = 5;
            N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
            N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
            N_RSPData.ind.MsgData[2] = 0x20;
            N_RSPData.ind.MsgData[3] = 0x00;
            N_RSPData.ind.MsgData[4] = 128;

            N_RSPData.ind.N_Result = N_OK;
        }
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_36_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_36_service(_N_USData *AppUSData)
{

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if (DiagnoCtl.SessionType == ProgSession)
    {
        if (DiagnoCtl.AccessLock == UnLockLv2)
        {
            if ((AppUSData->ind.Length > 2) && (AppUSData->ind.Length <= 1024))
            {
            }
            else
            {
                Error.FrameErr = ErrFormatLength; //长度不对
            }
        }
        else
        {
            Error.FrameErr = SecurityAccessDenied;
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }

    if (Error.FrameErr == 0)
    {
        N_RSPData.ind.len = 3;
        N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
        N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
        N_RSPData.ind.MsgData[2] = AppUSData->ind.MsgData[1];

        N_RSPData.ind.N_Result = N_OK;
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_37_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_37_service(_N_USData *AppUSData)
{
    App_ErrorInfoInit((_N_USData *)AppUSData);
    if (DiagnoCtl.SessionType == ProgSession)
    {
        if (DiagnoCtl.AccessLock == UnLockLv2)
        {
            if (AppUSData->ind.Length == 1)
            {
            }
            else
            {
                Error.FrameErr = ErrFormatLength; //长度不对
            }
        }
        else
        {
            Error.FrameErr = SecurityAccessDenied;
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }

    if (Error.FrameErr == 0)
    {
        N_RSPData.ind.len = 2;
        N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
        N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;

        N_RSPData.ind.N_Result = N_OK;
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_28_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_28_service(_N_USData *AppUSData)
{
    _SubFun SubFun;

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if (1) //(DiagnoCtl.SessionType == ExtSession)
    {
        if (AppUSData->ind.Length > 1)
        {
            SubFun.SubData = AppUSData->ind.MsgData[1];
            switch (SubFun.SubData) //(SubFun.SubBits.SubFunBit0_6) //子功能判断
            {

            case SubEnableRxAndTx0:                // 28 80
            case SubEnableRxAndTx:                 // 28 00
                if (AppUSData->ind.Length == 0x03) //长度为3
                {
                    if (AppUSData->ind.MsgData[2] == NOR_Message) //28 00 01 应用报文
                    {
                        DiagnoCtl.CommCtl = SubEnableRxAndTx; //使能接收发送
                        DiagnoCtl.CommType = NOR_Message;
                    }
                    /*else if (AppUSData->ind.MsgData[2] == NM_Message) //28 00 02 网络管理报文
                    {
                        DiagnoCtl.CommCtl = SubEnableRxAndTx; //使能接收发送
                        DiagnoCtl.CommType = NM_Message;
                    }
                    else if (AppUSData->ind.MsgData[2] == NOR_NM_Message) //28 00 03 应用和网络管理报文
                    {
                        DiagnoCtl.CommCtl = SubEnableRxAndTx; //使能接收发送
                        DiagnoCtl.CommType = NOR_NM_Message;
                    }*/
                    else
                    {
                        Error.FrameErr = RequestOutOfRange; //超出范围
                    }
                }
                else
                {
                    Error.FrameErr = RequestOutOfRange; //超出范围
                }
                break;
            case SubEnableRxAndDisTx:  // 28 01
            case SubEnableRxAndDisTx1: // 28 81
                if (AppUSData->ind.Length == 0x03)
                {
                    if (AppUSData->ind.MsgData[2] == NOR_Message) // 28 01/81 01  应用报文
                    {
                        DiagnoCtl.CommCtl = SubEnableRxAndDisTx; //禁止
                        DiagnoCtl.CommType = NOR_Message;
                    }
                    /*else if (AppUSData->ind.MsgData[2] == NM_Message) //28 03 02 网络管理报文
                    {
                        DiagnoCtl.CommCtl = SubDisableRxAndTx; //关闭
                        DiagnoCtl.CommType = NM_Message;
                    }
                    else if (AppUSData->ind.MsgData[2] == NOR_NM_Message) //28 03 03 应用和网络管理报文
                    {
                        DiagnoCtl.CommCtl = SubDisableRxAndTx; //关闭
                        DiagnoCtl.CommType = NOR_NM_Message;
                    }*/
                    else
                    {
                        Error.FrameErr = RequestOutOfRange;
                    }
                }
                else
                {
                    Error.FrameErr = RequestOutOfRange;
                }
                break;
            default:
                Error.FrameErr = SubFunctionNotSupported; //子功能不支持
            }
        }
        else
        {
            Error.FrameErr = ErrFormatLength; //长度不对
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }
    if (Error.FrameErr == 0)
    {
        N_RSPData.ind.len = 3;
        N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
        N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
        N_RSPData.ind.MsgData[2] = SubFun.SubBits.SubFunBit0_6;

        N_RSPData.ind.N_Result = N_OK;
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_22_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_22_service(_N_USData *AppUSData)
{
    uint8_t   DID_Num;
    uint16_t  MsgLen = 0;
    uint16_t  DID[20];
    uint32_t  i;
    uint8_t   *pTemp8;
    uint8_t temp8;
    uint8_t  MCU_SWversion[6] ;
    
    App_ErrorInfoInit((_N_USData *)AppUSData);
    
    if((DiagnoCtl.SessionType == DefSession)||(DiagnoCtl.SessionType == ExtSession))
    {
        if(((AppUSData->ind.Length - 1) % 2 == 0) && (AppUSData->ind.Length > 2))
        {
            DID_Num = (AppUSData->ind.Length - 1) / 2;
            if(DID_Num < 20)
            {
                N_US_S_MultiData.ind.MsgData[MsgLen] = AppUSData->ind.MsgData[0] + 0x40;
                MsgLen = 1;
                for(i = 0;i < DID_Num;i++)
                {
                    App_Load_DID((uint16_t *)&DID[i],(uint8_t *)&AppUSData->ind.MsgData[i*2+1]);
                    N_US_S_MultiData.ind.MsgData[MsgLen] = DID[i] >>8;
                    N_US_S_MultiData.ind.MsgData[MsgLen+1] = (uint8_t)DID[i];
                    MsgLen += 2;
                    
                    switch(DID[i])
                    {
                            //                        case DID0FA0: //读-当前会话模式
                        case 0xF195: //读软件版本号
              
                            MCU_SWversion[0] = pTemp8[0];
                            MCU_SWversion[1] = pTemp8[2];
                            MCU_SWversion[5] = (pTemp8[4]&0x0f)*100 + (pTemp8[5]&0x0f)*10 + (pTemp8[6]&0x0f);
           
                            MCU_SWversion[2] = (pTemp8[0]&0x0f)*10 + (pTemp8[1]&0x0f);
                            MCU_SWversion[3] = (pTemp8[2]&0x0f)*10 + (pTemp8[3]&0x0f);
                            MCU_SWversion[4] = (pTemp8[4]&0x0f)*10 + (pTemp8[5]&0x0f);
                            for(i=0;i<6;i++)
							{
                                N_US_S_MultiData.ind.MsgData[ 3+i ] = MCU_SWversion[ i ];
                                MsgLen += 1;
                            }
                            break;
                       case 0xF194: //读软件编码
              
					        MCU_SoftCode[2] = pTemp8[5];
						    MCU_SoftCode[3] = pTemp8[6];
						    MCU_SoftCode[4] = pTemp8[7];
                            for(i=0;i<6;i++)
							{
                                N_US_S_MultiData.ind.MsgData[ 3+i ] = MCU_SoftCode[ i ];
                                MsgLen += 1;
                            }
                            break;
                        case 0xF193: //读硬件版本号
                            for(i=0;i<5;i++)
							{
                                N_US_S_MultiData.ind.MsgData[ 3+i ] = MCU_HWversion[ i ];
                                MsgLen += 1;
                            }
                            break;
						case 0xF180: //读硬件版本号
                            for(i=0;i<9;i++)
                            {
                                N_US_S_MultiData.ind.MsgData[ 3+i ] = MCU_FBLversion[ i ];
                                MsgLen += 1;
                            }
                            break;
						case  0xF187:	// 读零件号
		

                            for(i=0;i<MaxBuff;i++){
                                temp8 = *(pTemp8++);
                                if(temp8){
                                    N_US_S_MultiData.ind.MsgData[ 3+i ] = temp8;
                                    MsgLen += 1;
                                }
                                else{
                                    break;
                                }
                            }
                            break;

                        default:
                            Error.FrameErr  = RequestOutOfRange;
                            break;
                    }
                }
            }
            else
            {
                    Error.FrameErr  = RequestOutOfRange;
            }
        }
        else
        {
            Error.FrameErr = ErrFormatLength;
        }
        
        if(MsgLen == 1)
        {
                Error.FrameErr = RequestOutOfRange;
	    }
        
        if(Error.FrameErr == 0)
        {
            N_US_S_MultiData.ind.Length = MsgLen;
            N_US_S_MultiData.ind.N_Result = N_OK;
            if(MsgLen >= 8)
            {
                N_US_S_Data_FF.ind.N_PCI = FirstFrame;
            }
            else
            {
                N_US_S_Data_FF.ind.N_PCI = 0;
            }
        }
    }
    else
    {
            Error.FrameErr = NotSuppInActiveSession;
    }
}


/*-------------------------------------------------------------------------
* Function Name  : App_2E_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/

void App_2E_service(_N_USData *AppUSData)
{
    uint16_t DID;

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if ((DiagnoCtl.SessionType == ExtSession) || ((DiagnoCtl.SessionType == ProgSession)))
    {
        if ((DiagnoCtl.AccessLock == UnLockLv1) || (DiagnoCtl.AccessLock == UnLockLv2))
        {
            if (AppUSData->ind.Length > 1)
            {
                App_Load_DID((uint16_t *)&DID, (uint8_t *)&AppUSData->ind.MsgData[1]);
                switch(DID)
                {
//                    case DID0FA0:
//                        if(AppUSData->ind.Length == 35)
//                        {
//                            eeprom_WriteUUID((uint8_t *)&AppUSData->ind.MsgData[3]);
//                        }
//                        else
//                        {
//                            Error.FrameErr = ErrFormatLength;
//                        }
//                        break;
                    default:
                        Error.FrameErr = RequestOutOfRange;
                        break;
                }
            }
            else
            {
                Error.FrameErr = ErrFormatLength;
            }
        }
        else
        {
            Error.FrameErr = SecurityAccessDenied;
        }

        if ((DiagnoCtl.AccessLock == UnLockLv1) || ((DiagnoCtl.AccessLock == UnLockLv2)))
        {
            if (Error.FrameErr == 0)
            {
                N_RSPData.ind.len = 4;
                N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
                N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
                N_RSPData.ind.MsgData[2] = (uint8_t)(DID >> 8);
                N_RSPData.ind.MsgData[3] = (uint8_t)(DID);
                N_RSPData.ind.N_Result = N_OK;
            }
        }
        else
        {
            Error.FrameErr = SecurityAccessDenied;
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_14_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_14_service(_N_USData *AppUSData)
{

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if (Error.FrameErr == 0)
    {
        N_RSPData.ind.len = 2;
        N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
        N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
        N_RSPData.ind.N_Result = N_OK;
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_19_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_59_service(_N_USData *AppUSData)
{
    uint16_t DID;
    App_ErrorInfoInit((_N_USData *)AppUSData);
    //获取DID
    App_Load_DID((uint16_t *)&DID, (uint8_t *)&AppUSData->ind.MsgData[1]);
     (void)memset((uint8_t *)&DiagReciveDTC.UnionDTC, 0,sizeof(_DiagReciveDTC));
    if (AppUSData->ind.Length > 1)
    {

        if (AppUSData->ind.MsgData[1] == 0x02)
        {
            App_CopyRam((uint8_t *)&DiagReciveDTC.UnionDTC, (uint8_t *)&AppUSData->ind.MsgData[3], (AppUSData->ind.Length - 3));
        }
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_2F_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_2F_service(_N_USData *AppUSData)
{
    uint8_t InOutCtrlParameter;
    uint16_t DID;
    uint16_t MsgLen = 4;
    App_ErrorInfoInit((_N_USData *)AppUSData);

    if (DiagnoCtl.SessionType == ExtSession) //2F + DID + 控制参数 + INfo
    {
        if ((DiagnoCtl.AccessLock == UnLockLv1) || (DiagnoCtl.AccessLock == UnLockLv2)) //解锁
        {
            if (AppUSData->ind.Length > 1)
            {
                App_Load_DID((uint16_t *)&DID, (uint8_t *)&AppUSData->ind.MsgData[1]);

                InOutCtrlParameter = AppUSData->ind.MsgData[3]; //2F 10 01 _03..+ 1byte

                if (Error.FrameErr == 0)
                {
                }
            }
            else
            {
                Error.FrameErr = ErrFormatLength; //长度不对
            }
            if (Error.FrameErr == 0)
            {
                N_US_S_MultiData.ind.MsgData[0] = AppUSData->ind.MsgData[0] + 0x40;
                N_US_S_MultiData.ind.MsgData[1] = (uint8_t)(DID >> 8);
                N_US_S_MultiData.ind.MsgData[2] = (uint8_t)DID;
                N_US_S_MultiData.ind.MsgData[3] = InOutCtrlParameter;

                if (MsgLen >= 8)
                {
                    N_US_S_Data_FF.ind.Length = MsgLen;
                    N_US_S_Data_FF.ind.N_PCI = FirstFrame;
                }
                else
                {
                    N_US_S_MultiData.ind.Length = MsgLen;
                    N_US_S_Data_FF.ind.N_PCI = 0;
                }
                N_US_S_MultiData.ind.N_Result = N_OK;
            }
        }
        else
        {
            Error.FrameErr = SecurityAccessDenied;
        }
    }
    else
    {
        Error.FrameErr = NotSuppInActiveSession;
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_3E_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_3E_service(_N_USData *AppUSData)
{
    _SubFun SubFun;

    App_ErrorInfoInit((_N_USData *)AppUSData);

    if (AppUSData->ind.Length > 1)
    {
        SubFun.SubData = AppUSData->ind.MsgData[1];

        switch (SubFun.SubBits.SubFunBit0_6)
        {
        case SubZeroFun0:
            if (AppUSData->ind.Length == 0x02)
            {
                if (!SubFun.SubBits.SubFunBit7_7)
                {
                    N_RSPData.ind.len = 3;
                    N_RSPData.ind.MsgData[0] = N_RSPData.ind.len - 1;
                    N_RSPData.ind.MsgData[1] = AppUSData->ind.MsgData[0] + 0x40;
                    N_RSPData.ind.MsgData[2] = SubFun.SubBits.SubFunBit0_6;
                    N_RSPData.ind.N_Result = N_OK;
                }
                App_SetSessionTimer(N_Session, (_DiagClock *)&DiagClock);
            }
            else
            {
                Error.FrameErr = ErrFormatLength; //长度不对
            }
            break;
        default:
            Error.FrameErr = SubFunctionNotSupported; //子功能不支持
        }
    }
    else
    {
        Error.FrameErr = ErrFormatLength; //长度不对
    }
}
/*-------------------------------------------------------------------------
* Function Name  : App_19_service
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_01_service(_N_USData *AppUSData)
{

    if (AppUSData->ind.Length == 0x06)
    {
        if (AppUSData->ind.MsgData[1] == 1)
        {
            DiagReciveGaugePara.MilLamp = 1;
            
        }
        else
        {
            DiagReciveGaugePara.MilLamp = 0;
        }
        Reset_Mil_Signal_Time();
        DelfuModuleIn();
    }
    else
    {
        ;
    }
}

uint32_t CalculateKey ( uint8_t *Seed )  
{
   
    uint8_t i;
    union
    {
        uint8_t key_byte[4];  
        uint32_t key_word;
    }key;
    uint32_t seed_temp;

    seed_temp = (uint32_t)(Seed[0])<<24 | (uint32_t)(Seed[1])<<16 | (uint32_t)(Seed[2])<<8 | (uint32_t)(Seed[3]);
    if(seed_temp != 0)
    {
        for(i=0;i<35;i++)
        {
            if(seed_temp & 0x80000000)
            {
                if(seed_temp & 0x00000002)
                {
                    seed_temp = ((seed_temp << 1)&0xFFFFFFFF);
                    seed_temp = (seed_temp^0x0A827D34)&0xFFFFFFFF;
                }
                else
                {
                    seed_temp = (seed_temp << 1)&0xFFFFFFFF;
                    seed_temp = seed_temp^0x91CD92D7;
                }
            }
            else
            {
                seed_temp = (seed_temp << 1)&0xFFFFFFFF;
            }
            
        }
        key.key_byte[0] = (seed_temp & 0xFF000000)>>24;
        key.key_byte[1] = (seed_temp & 0x00FF0000)>>16;
        key.key_byte[2] = (seed_temp & 0x0000FF00)>>8;
        key.key_byte[3] = (seed_temp & 0x000000FF);
    }
    return key.key_word;

}

uint32_t CalculateKeyLv11 ( uint8_t *Seed )  
{
    uint8_t i;
    uint8_t Cal[4];
    uint8_t *p;
    uint32_t KeyResult;

    for ( i = 0; i < 4; i++ )
    {
        Cal[i] = Seed[i] ^ XorArray[i];
    }

    p = ( uint8_t * ) &KeyResult;
    p[3] = ( ( ( Cal[2] & 0x03 ) << 6 ) | ( Cal[3] & 0xFC ) >> 2 );
    p[2] = ( ( Cal[3] & 0x03 ) << 6 ) | ( ( Cal[0] & 0x3F ) );
    p[1] = ( Cal[0] & 0xFC ) | ( ( Cal[1] & 0xC0 ) >> 6 );
    p[0] = ( ( Cal[1] & 0xFC ) ) | ( Cal[2] & 0x03 );

    return KeyResult;
}
/*-------------------------------------------------------------------------
* Function Name  : App_SetSequenceTimer
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_SetSequenceTimer(uint32_t Second, _DiagClock *T)
{
    T->TT_SequenceEnable = 1;
    T->OverSequenceTime = Second;
    T->SequenceTime = 0;
}
/*-------------------------------------------------------------------------
* Function Name  : App_SequenceTimerOver
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
uint8_t App_SequenceTimerOver(_DiagClock *T)
{
    if ((T->SequenceTime >= T->OverSequenceTime) && (T->TT_SequenceEnable))
    {
        T->TT_SequenceEnable = 0;
        T->SequenceTime = 0;
        return 1;
    }
    else
    {
        return 0;
    }
}

/*-------------------------------------------------------------------------
* Function Name  : App_SetSessionTimer
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_SetSessionTimer(uint32_t Second, _DiagClock *T)
{
    T->TT_SessionEnable = 1;
    T->OverSessionTime = Second;
    T->SessionTime = 0;
}
/*-------------------------------------------------------------------------
* Function Name  : Api_TTimerOver3
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
uint8_t App_SessionTimerOver(_DiagClock *T)
{
    if ((T->SessionTime >= T->OverSessionTime) && (T->TT_SessionEnable))
    {
        T->TT_SessionEnable = 0;
        T->SessionTime = 0;
        return 1;
    }
    else
    {
        return 0;
    }
}

/*-------------------------------------------------------------------------
* Function Name  : App_SetReUnlockTimer
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
void App_SetReUnlockTimer(uint32_t Second, _DiagClock *T)
{
    T->TT_UnlockEnable = 1;
    T->OverUnlockTime = Second;
    T->UnlockTime = 0;
}
/*-------------------------------------------------------------------------
* Function Name  : App_ReUnlockTimerOver
* Description    :
* Input          :
* Output         : None
* Return         : None
* onther         :
--------------------------------------------------------------------------*/
uint8_t App_ReUnlockTimerOver(_DiagClock *T)
{
    if ((T->UnlockTime >= T->OverUnlockTime) && (T->TT_UnlockEnable))
    {
        T->TT_UnlockEnable = 0;
        T->UnlockTime = 0;
        return 1;
    }
    else
    {
        return 0;
    }
}
uint16_t Get_DiagnoCtl_CommCtl(void )
{
    return DiagnoCtl.CommCtl ; //使能接收发送
}


