#ifndef _UDS_COMMON_H_
#define _UDS_COMMON_H_

#include "stdint.h"
           
//typedef unsigned char uint8_t;
//typedef unsigned short uint16_t;
//typedef unsigned int uint32_t;  
//typedef long int32_t;

// NRC
//     10_GENERAL_REJECT                                 
//     11_SERVICE_NOT_SUPPORTED                          
//     12_SUBFUNCTION_NOT_SUPPORTED                      
//     13_INCORRECT_MESSAGE_LENGTH_OR_INVALID_FORMAT     
//     14_RESPONSE_TOO_LONG                              
//     21_BUSY_REPEAT_REQUEST                            
//     22_CONDITIONS_NOT_CORRECT                         
//     24_REQUEST_SEQUENCE_ERROR                         
//     31_REQUEST_OUT_OF_RANGE                           
//     33_SECUTITY_ACCESS_DENIED                         
//     35_INVALID_KEY                                    
//     36_EXCEED_NUMBER_OF_ATTEMPTS                      
//     37_REQUIRED_TIME_DELAY_NOT_EXPIRED                
//     70_UPLOAD_DOWNLOAD_NOT_ACCEPTED                   
//     71_TRANSFER_DATA_SUSPENDED                        
//     72_GENERAL_PROGRAMMING_FAILURE                    
//     73_WRONG_BLOCK_SEQUENCE_COUNTER                   
//     78_RESPONSE_PENDING                               
//     7E_SUBFUNCTION_NOT_SUPPORTED_INACTIVE_SESSION     
//     7F_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION        
//     81_RPM_TOO_HIGH                                   
//     82_RPM_TOO_LOW                                    
//     83_ENGINE_IS_RUNNING                              
//     84_ENGINE_IS_NOT_RUNNING                          
//     85_ENGINE_RUN_TIME_TOO_LOW                        
//     86_TEMPERATURE_TOO_HIGH                           
//     87_TEMPERATURE_TOO_LOW                            
//     88_VEHICLE_SPEED_TOO_HIGH                         
//     89_VEHICLE_SPEED_TOO_LOW                          
//     8A_THROTTLE_PEDAL_TOO_HIGH                        
//     8B_THROTTLE_PEDAL_TOO_LOW                         
//     8C_TRANSMISSION_RANGE_NOT_IN_NEUTRAL              
//     8D_TRANSMISSION_RANGE_NOT_IN_GEAR                 
//     8F_BRAKE_SWITCH_NOT_CLOSED                        
//     90_SHIFT_ERLEVER_NOT_IN_PARK                      
//     91_TORQUECONVERTER_CLUTCH_LOCKED                  
//     92_VOLTAGE_TOO_HIGH                               
//     93_VOLTAGE_TOO_LOW                                

#define DIAG_PHY 0
#define DIAG_FUNC 1
#define TP_NAVI 2
#define TP_AV 3

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif


#define UdsAllSession           0xFFFFU
#define UdsDefaultSession       0x0001U
#define UdsProgramSession       0x0002U
#define UdsExtendedSession      0x0004U

// Security Level Mask List
#define UdsUnSecurityLevel        0x0000U
#define UdsSecurityLevel1         0x0001U
#define UdsSecurityLevel11        0x0011U

#define UdsFuncOrPhyValidPhy     0x1
#define UdsFuncOrPhyValidFunc    0x2

typedef uint8_t UDS_SessionType;
typedef uint8_t UDS_SecurityLevelType;
typedef uint8_t UDS_ServiceIdType;
typedef uint8_t UDS_NrcType;
// Each bit is a session
typedef uint16_t UDS_SessionMaskType;
// Each bit is a level
typedef uint8_t UDS_SecurityLevelMaskType;
typedef uint8_t UDS_FuncOrPhyValid;
typedef struct {
    UDS_ServiceIdType ServiceId;
    UDS_SessionMaskType sessionMask;
    UDS_SecurityLevelMaskType securityLevelMask;
    UDS_FuncOrPhyValid funcOrPhyMask;
    void (*callout)(void);
    uint16_t (*SetResp)(uint8_t *ReqData, uint16_t ReqLen, uint8_t *RespData, uint16_t RespLen);
} UDS_ServiceType;

typedef struct {
    uint16_t did;
    UDS_SessionMaskType sessionMask;
    UDS_SecurityLevelMaskType securityLevelMask;
    uint16_t (*callout)(uint8_t *Data,uint16_t length);
} UDS_DIDType;

typedef struct {
    uint16_t did;
    UDS_SessionMaskType sessionMask;
    UDS_SecurityLevelMaskType securityLevelMask;
    uint16_t (*callout)(uint8_t *Data, uint16_t length, uint8_t *rData, uint16_t rlength);
} UDS_IOCTLType;

typedef struct {
    uint16_t id;
    UDS_SessionMaskType sessionMask;
    UDS_SecurityLevelMaskType securityLevelMask;
    uint16_t (*startRC)(uint8_t *param,uint16_t length,uint8_t *status);
    uint16_t (*stopRC)(uint8_t *param,uint16_t length,uint8_t *status);
    uint16_t (*requestResultRC)(uint8_t *param,uint16_t length,uint8_t *result);
} UDS_RCType;

typedef struct {
    const UDS_ServiceType *ServiceIdList;
    uint8_t                ServiceIdNum;
    const UDS_DIDType     *ReadDidList;
    uint8_t                ReadDidNum;
    const UDS_DIDType     *WriteDidList;
    uint8_t                WriteDidNum;
    const UDS_RCType      *RoutinueControlList;
    uint8_t                RoutinueControlNum;
    const UDS_IOCTLType     *IOControlList;
    uint8_t                IOControlNum;
} UDS_ConfigType;

typedef struct {
    uint32_t RespID;
    uint8_t FillByte;  
    uint8_t Tp_N_STmin;
    uint8_t Tp_N_BS;
    uint16_t Tp_N_Ar;  
    uint16_t Tp_N_Br;
    uint16_t Uds_cfgP2Server; 
    UDS_ConfigType Uds_Config;
}UDS_INIT_PARA;

typedef struct
{
    uint32_t    memoryAddress;
    uint32_t    memorySize;
    uint32_t    RecvDataLen;
    uint8_t     RecvBlockNum;
    uint8_t     memoryData[308];
} _DownInfo;

typedef enum
{
    SE_IDLE,
    SE_CURRENT_31,
    SE_CURRENT_34,
    SE_CURRENT_36,
    SE_CURRENT_37,
    SE_WAIT_31_ERASE,
    SE_WAIT_34,
    SE_WAIT_36_37,
} DOWN_SEQUENCE;



// Service ID table
#define SID_DIAGNOSTIC_SESSION_CONTROL          0x10
#define SID_ECU_RESET                           0x11
#define SID_CLEAR_DIAGNOSTIC_INFORMATION        0x14
#define SID_READ_STATUS_OF_DTC                  0x17    //kwp2000 on can
#define SID_READ_DTC_BY_STATUS                  0x18    //kwp2000 on can
#define SID_READ_DTC_INFORMATION                0x19
#define SID_READ_ECU_ID                         0x1a    //kwp2000 on can
#define SID_STOP_DIAGNOSITC_SESSION             0X20
#define SID_READ_DATA_BY_IDENTIFIER             0x22
#define SID_READ_MEMORY_BY_ADDRESS              0x23
#define SID_READ_SCALING_DATA_BY_IDENTIFIER     0x24
#define SID_SECURITY_ACCESS                     0x27
#define SID_COMMUNICATION_CONTROL               0x28
#define SID_ENABLE_NORMAL_MESSAGE_TRANSMISSION  0x29    //kwp2000 on can 
#define SID_INPUT_OUTPUT_CONTROL_BY_LOCAL_ID    0x30    //kwp2000 on can
#define SID_READ_DATA_BY_PERIODIC_IDENTIFIER    0x2A
#define SID_DYNAMICALLY_DEFINE_DATA_IDENTIFIER  0x2C
#define SID_WRITE_DATA_BY_IDENTIFIER            0x2E
#define SID_INPUT_OUTPUT_CONTROL_BY_IDENTIFIER  0x2F
#define SID_ROUTINE_CONTROL                     0x31
#define SID_WRITE_MEMORY_BY_ADDRESS             0x3D
#define SID_TESTER_PRESENT                      0x3E
#define SID_NEGATIVE_RESPONSE                   0x7F
#define SID_CONTROL_DTC_SETTING                 0x85
#define SID_REQUEST_DOWNLOAD                    0x34
#define SID_REQUEST_UPLOAD                      0x35
#define SID_TRANSFER_DATA                       0x36
#define SID_REQUEST_TRANSFER_EXIT               0x37

extern uint8_t *GetDiagnosticVersion(void);
extern uint8_t CheckVoltage(void);  
extern uint8_t Api_CreateCRCCheckSum(uint8_t *p ,uint8_t Nub);
extern void McuReset(uint8_t GotoBoot);
extern void SendMessageToCan(uint8_t CanCh, uint16_t ID_H, uint16_t ID_L, uint8_t *data, uint8_t len);
extern void CheckDiagBuff(void);
extern void TP_RxToBuffer(uint8_t PhyOrFunc, uint32_t id, uint8_t *data, uint8_t len);
extern void UDS_PeriodTask(uint16_t TimerDelta);
extern void UDS_InitDiagnostic(void *init);

extern void UDS_SessionControlFunc(void);
extern void UDS_StopDiagnositcSessionFunc(void);
extern void UDS_EnableNormalMessageTransmissionFunc(void);
extern void UDS_EcuResetFunc(void);
extern void UDS_ControlDtcSettingFunc(void);
extern void UDS_ClearDiagnosticInformation(void);
extern void UDS_ReadDtcInformation(void);
extern void UDS_RequestDownload(void);
extern void UDS_TransferData(void);
extern void UDS_RequestTransferExit(void);
extern void UDS_SecurityAccessFunc(void);
extern void UDS_CommunicationControlFunc(void);
extern void UDS_TesterPresentFunc(void);
extern void UDS_ReadDIDFunc(void);              //support nrc,eg:0x8012,return nrc code 0x12
extern void UDS_WriteDIDFunc(void);              //support nrc,eg:0x8012,return nrc code 0x12
extern void UDS_InputOutputControlByIdentifierFunc(void);   //support nrc,eg:0x8012,return nrc code 0x12
extern void UDS_RoutineControlFunc(void);
extern void UDS_ResetCommParameter(void);
extern uint8_t UDS_isEnableNormalMsgValid(uint8_t data);

extern uint8_t UDS_CheckRequestLength(uint8_t SID, uint16_t len);
extern uint8_t UDS_IsNewSessionValid(UDS_SessionType Session);
extern UDS_SessionType UDS_SessionMap(UDS_SessionType Session);
extern void UDS_ChangeDefaultSession(void);
extern uint32_t UDS_CalcKey(uint8_t *seed);
extern uint8_t UDS_PrepareSeed(uint8_t *seed, uint8_t GetSeedType);
extern uint8_t UDS_CompareKey(uint8_t *key, uint8_t length);
extern uint8_t UDS_CheckRequestSeedValid(uint8_t SubFun);
extern uint8_t UDS_CheckRequestSeedLength(uint8_t len);
extern uint8_t UDS_CheckSendKeyValid(uint8_t SubFun);
extern void UDS_SetUdsSecurityLevel(uint8_t lv);
extern uint32_t TcflashRead(uint32_t addr);
extern void TcflashWrite(uint32_t addr, uint8_t *data, uint16_t len);
extern uint8_t UDS_CheckSessionLevel(UDS_SessionMaskType sessionMask);
extern uint8_t UDS_CheckSecurityLevel(UDS_SecurityLevelMaskType securityLevelMask);
extern uint8_t UDS_IsDefaultSession(UDS_SessionMaskType sessionMask);
extern uint8_t UDS_IsProgramSession(UDS_SessionMaskType sessionMask);
extern uint8_t UDS_IsExtendSession(UDS_SessionMaskType sessionMask);
extern uint8_t UDS_isResetValid(uint8_t data);

extern void UDS_SetNormalEnTxEnRx(void);
extern void UDS_SetNMEnTxEnRx(void);
extern void UDS_SetNMAndNormalEnTxEnRx(void);
extern void UDS_SetNormalDisTxDisRx(void);
extern void UDS_SetNMDisTxDisRx(void);
extern void UDS_SetNMAndNormalDisTxDisRx(void);
extern void UDS_SetDtcOn(void);
extern void UDS_SetDtcOff(void);
                                            
#define UDS_RESPONSE_PENDING 0xff 


extern uint8_t GetCurSession(void);
extern uint8_t GetCurSecyritySt(void);
#endif
