/*******************************************************************************
********************************************************************************
**
**  Copyright(c) 2022, Alliance for Automotive Innovation
**  Used only under license from the Alliance for Automotive Innovation. All Rights Reserved.
**
**  Project:  J1699-3
**  FileName: j1699.h
**  Author:   EnGenius
**  Date:     2/25/2022
**  Email:    <support@autosinnovate.org>
**
**  Purpose:  SAE J1699-3 Vehicle OBD II Compliance Test Cases Source Code.
**            This source code is intended to run the tests described in
**            the SAE J1699-3 document in an automated manner, when compiled
**            and used with an SAE J2534-compatible pass-thru device.
**
**            File j1699.c contains information on building and running this test.
**
**  Description:
**
**  Modifications:  12/07/2022  Initial Version
**
********************************************************************************
*******************************************************************************/


/*******************************************************************************
**  Typedefs and function pointers for J2534 API
*******************************************************************************/
typedef long (CALLBACK* PTCONNECT)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long *);
typedef long (CALLBACK* PTDISCONNECT)(unsigned long);
typedef long (CALLBACK* PTREADMSGS)(unsigned long, void *, unsigned long *, unsigned long);
typedef long (CALLBACK* PTWRITEMSGS)(unsigned long, void *, unsigned long *, unsigned long);
typedef long (CALLBACK* PTSTARTPERIODICMSG)(unsigned long, void *, unsigned long *, unsigned long);
typedef long (CALLBACK* PTSTOPPERIODICMSG)(unsigned long, unsigned long);
typedef long (CALLBACK* PTSTARTMSGFILTER)(unsigned long, unsigned long, void *, void *, void *, unsigned long *);
typedef long (CALLBACK* PTSTOPMSGFILTER)(unsigned long, unsigned long);
typedef long (CALLBACK* PTSETPROGRAMMINGVOLTAGE)(unsigned long, unsigned long, unsigned long);
typedef long (CALLBACK* PTREADVERSION)(unsigned long, char *, char *, char *);
typedef long (CALLBACK* PTGETLASTERROR)(char *);
typedef long (CALLBACK* PTIOCTL)(unsigned long, unsigned long, void *, void *);

typedef long (CALLBACK* PTOPEN)(void *, unsigned long *);
typedef long (CALLBACK* PTCLOSE)(unsigned long);

extern PTCONNECT PassThruConnect;
extern PTDISCONNECT PassThruDisconnect;
extern PTREADMSGS PassThruReadMsgs;
extern PTWRITEMSGS PassThruWriteMsgs;
extern PTSTARTPERIODICMSG PassThruStartPeriodicMsg;
extern PTSTOPPERIODICMSG PassThruStopPeriodicMsg;
extern PTSTARTMSGFILTER PassThruStartMsgFilter;
extern PTSTOPMSGFILTER PassThruStopMsgFilter;
extern PTSETPROGRAMMINGVOLTAGE PassThruSetProgrammingVoltage;
extern PTREADVERSION PassThruReadVersion;
extern PTGETLASTERROR PassThruGetLastError;
extern PTIOCTL PassThruIoctl;
extern PTOPEN  PassThruOpen;
extern PTCLOSE PassThruClose;


// maximum number of J2534 devices allowed
#define MAX_J2534_DEVICES        50


/*******************************************************************************
**  OBD Message and protocol definitions
*******************************************************************************/
// Maximum number of OBD ECUs and protocols
#define OBD_LEGACY_MAX_ECUS      8
#define MAX_ECUS             239
#define MAX_ECUS_PER_PAGE        8
#define MAX_ECU_PAGE             30 // MAX_ECUS / MAX_ECUS_PER_PAGE rounded up
#define OBD_MAX_US_PROTOCOLS     7
#define OBD_MAX_EU250K_PROTOCOLS 7
#define OBD_MAX_EU_PROTOCOLS     9
#define OBD_MAX_PROTOCOLS        OBD_MAX_EU_PROTOCOLS  // the largest number of protocols possible

// OBD response indicator bit
#define OBD_RESPONSE_BIT         0x40

// Maximum number of bytes in ISO15765 frame
#define ISO15765_MAX_BYTES_PER_FRAME 7

// NAK Response ID and Codes
#define NAK                      0x7F
#define NAK_GENERAL_REJECT       0x10
#define NAK_NOT_SUPPORTED        0x11
#define NAK_INVALID_FORMAT       0x12
#define NAK_REPEAT_REQUEST       0x21
#define NAK_SEQUENCE_ERROR       0x22
#define NAK_RESPONSE_PENDING     0x78

// Tester node address
#define TESTER_NODE_ADDRESS      0xF1

// eProtocolTag list - the order of this list must match ProtocolInitData[] in InitOBDProtocolList.c
#define J1850PWM_I              0   // US OBD-II protocol
#define J1850VPW_I              1   // US OBD-II protocol
#define ISO9141_I               2   // US OBD-II protocol
#define ISO14230_FAST_INIT_I    3   // US OBD-II protocol
#define ISO14230_I              4   // US OBD-II protocol
#define ISO15765_I              5   // US OBD-II protocol
#define ISO15765_29_BIT_I       6   // US OBD-II protocol
#define ISO15765_250K_11_BIT_I  7   // EOBD protocol
#define ISO15765_250K_29_BIT_I  8   // EOBD protocol


#define MAX_PROTOCOL_NAME  25
// Protocol list structure
typedef struct
{
	unsigned long eProtocol;       // generic protocol (for J2534-1)
	unsigned long ChannelID;
	unsigned long eInitFlags;      // J2534-1 ConnectFlags
	unsigned long TesterPresentID;
	unsigned long FilterID;
	unsigned long FlowFilterID[MAX_ECUS];
	BYTE          HeaderSize;      // size of message header
	unsigned long BaudRate;        // link data rate
	unsigned long eProtocolTag;    // tag that uniquely identifies each protocol
	char Name[MAX_PROTOCOL_NAME];  // ASCII string for the protocol name
} PROTOCOL_LIST;


// RequestSid Flags
#define REQ_MSG_NORMAL                      0x00000000
#define REQ_MSG_RETURN_AFTER_ALL_RESPONSES  0x00000001
#define REQ_MSG_NO_PERIODIC_DISABLE         0x00000002
#define REQ_MSG_ALLOW_NO_RESPONSE           0x00000004
        // set = no response returns PASS from RequestSid
        // unset = no response returns FAIL from RequestSid
#define REQ_MSG_IGNORE_NO_RESPONSE          0x00000008
        // set = log WARNING on no response in RequestSid
        // unset = don't log WARNING on no response in RequestSid


/*******************************************************************************
**  User Input definitions
*******************************************************************************/
// User prompt type definitions
typedef enum
{
	NO_PROMPT=0,
	ENTER_PROMPT=1,
	YES_NO_PROMPT=2,
	YES_NO_ALL_PROMPT=3,
	QUIT_CONTINUE_PROMPT=4,
	CUSTOM_PROMPT=5,
	COMMENT_PROMPT=6
} PROMPTTYPE;

// User log entry type definitions
typedef enum
{
	USER_ERROR=1,
	FAILURE=2,
	WARNING=3,
	INFORMATION=4,
	PROMPT=5,
	SUBSECTION_BEGIN=6,
	SUBSECTION_PASSED_RESULT=7,
	SUBSECTION_FAILED_RESULT=8,
	SUBSECTION_INCOMPLETE_RESULT=9,
	SECTION_PASSED_RESULT=10,
	SECTION_FAILED_RESULT=11,
	SECTION_INCOMPLETE_RESULT=12,
	BLANK=13,
	NETWORK=14,
	ERROR_FAILURE=15,
	RESULTS=16,
	COMMENT=17,
	J2534_FAILURE=20
} LOGTYPE;

// Screen Output type definitions
typedef enum
{
	SCREENOUTPUTON=TRUE,
	SCREENOUTPUTOFF=FALSE
} SCREENOUTPUT;

// Logfile Output type definitions
typedef enum
{
	LOGOUTPUTON=TRUE,
	LOGOUTPUTOFF=FALSE
} LOGOUTPUT;

// engine type definitions
typedef enum
{
	ENGINE_UNKNOWN=0,
	GASOLINE=1,
	DIESEL=2
} ENGINETYPE;

// Powertrain type definitions
typedef enum
{
	PWRTRN_UNKNOWN=0,
	CONV=1,
	SS=2,
	HEV=3,
	PHEV=4
} PWRTRNTYPE;

// vehicle type definitions
typedef enum
{
	VEHICLE_UNKNOWN=0,
	LD=1,
	MD=2,
	HD=3
} VEHICLETYPE;

// Compliance test type definitions
typedef enum
{
	UNKNOWN=0,
	US_OBDII=1,
	EOBD_WITH_IUMPR=2,
	EOBD_NO_IUMPR=3,
	HD_OBD=4,
	HD_EOBD=5,
	IOBD_NO_IUMPR=6,
	HD_IOBD_NO_IUMPR=7,
	OBDBr_NO_IUMPR=8,
	CNOBD_NO_IUMPR=9
} COMPLIANCETYPE;

typedef enum
{
	USOBD=1,
	EOBD=2,
	EOBD_250K=3
} SCANTABLETYPE;

typedef enum
{
	eTestNone=0,
	eTestNoDTC=5,
	eTestPendingDTC=6,
	eTestConfirmedDTC=7,
	eTestFaultRepaired=8,
	eTestNoFault3DriveCycle=9,
	eTestInUseCounters=10,
	eTestPerformanceCounters=11
} TEST_PHASE;


// List of message defines - ORDER MUST MATCH gDisplayStrings in j1699.c
#define DSPSTR_PRMPT_MODEL_YEAR         0
#define DSPSTR_PRMPT_ENG_CERT_YEAR      1
#define DSPSTR_PRMPT_OBD_ECU            2
#define DSPSTR_PRMPT_RPGM_ECU           3
#define DSPSTR_PRMPT_ENG_TYPE           4
#define DSPSTR_PRMPT_PWRTRN_TYPE        5
#define DSPSTR_STMT_COMPLIANCE_TYPE     6
#define DSPSTR_PRMPT_VEH_TYPE           7
#define DSPSTR_PRMPT_ISO15765_TYPE      8
#define DSPSTR_RSLT_TOT_USR_ERROR       9
#define DSPSTR_RSLT_TOT_J2534_FAIL      10
#define DSPSTR_RSLT_TOT_WARN            11
#define DSPSTR_RSLT_TOT_FAIL            12
#define DSPSTR_RSLT_TOT_COMMENTS        13

#define DSPSTR_TOTAL                    14


// maximum length for a log filename
#define MAX_LOGFILENAME          80


// LogMsg Flags
#define LOG_NORMAL_MSG          0
#define LOG_REQ_MSG             1

// logging related maximums
#define MAX_LOG_STRING_SIZE      2048   // max. size of a single log entry
#define MAX_MESSAGE_LOG_SIZE     640    // max. number of message bytes in a single log entry

// Function return value definitions (sometimes treated as bit map, DO NOT CHANGE VALUES!)
typedef enum
{
	PASS=0x00,
	FAIL=0x02,
	ABORT=0x04,
	ERRORS=0x08,
	RETRY=0x10,
	CTRL_C=0x20,
	EXIT=0x40
} STATUS;

// Macros
#define ABORT_RETURN   {gbTestAborted = TRUE;gbTestSectionAborted = TRUE;return ABORT;}


// Drive Cycle completion flags
#define IDLE_TIME           0x01
#define ATSPEED_TIME        0x02
#define CUMULATIVE_TIME     0x04
#define FEO_TIME            0x08


// DID type enumeration
#define NUM_ID_SUP_TYPES 5
// values here must match offsets for the appropriate string in Sid[] and IDTypeString[]
typedef enum
{
	PIDREQUEST=0,    // Service $1 - PID
	FFREQUEST=1,     // Service $2 - FF
	MIDREQUEST=2,    // Service $6 - MID
	TIDREQUEST=3,    // Service $8 - TID
	INFREQUEST=4     // Service $9 - INF
} IDTYPE;

#define ALLECUS 0xFF

// SID 9 InfoTypes
#define INF_TYPE_VIN_COUNT       0x01
#define INF_TYPE_VIN             0x02
#define INF_TYPE_CALID_COUNT     0x03
#define INF_TYPE_CALID           0x04
#define INF_TYPE_CVN_COUNT       0x05
#define INF_TYPE_CVN             0x06
#define INF_TYPE_IPT_COUNT       0x07
#define INF_TYPE_IPT_GAS         0x08
#define INF_TYPE_ECUNAME_COUNT   0x09
#define INF_TYPE_ECUNAME         0x0A
#define INF_TYPE_IPT_DIESEL      0x0B
#define INF_TYPE_ESN_COUNT       0x0C
#define INF_TYPE_ESN             0x0D
#define INF_TYPE_EROTAN_COUNT    0x0E
#define INF_TYPE_EROTAN          0x0F
#define INF_TYPE_PROTID          0x10
#define INF_TYPE_GTR             0x11
#define INF_TYPE_FEOCNTR         0x12
#define INF_TYPE_TG_EFN          0x13
#define INF_TYPE_EVAP_DIST       0x14
#define INF_TYPE_MTRCYCLE        0x15
#define INF_TYPE_ER_IT           0x16
#define INF_TYPE_DT_FC           0x17
#define INF_TYPE_PKE_EOE         0x18
#define INF_TYPE_PSA             0x19
#define INF_TYPE_PHEVDD          0x1A
#define INF_TYPE_PHEVFD          0x1B
#define INF_TYPE_PHEVGD          0x1C
#define INF_TYPE_AAF1OCCVD       0x1D
#define INF_TYPE_AAF2OCCVD       0x1E
#define INF_TYPE_AAF3OCCVD       0x1F
#define INF_TYPE_DSOMOCCVD       0x21
#define INF_TYPE_RTSSCOCCVD      0x22
#define INF_TYPE_DCTOCCVD        0x23
#define INF_TYPE_APTWUFOCCVD     0x24
#define INF_TYPE_OCCT1VD         0x25
#define INF_TYPE_OCCT2VD         0x26
#define INF_TYPE_OCCT3VD         0x27
#define INF_TYPE_OCCT4VD         0x28
#define INF_TYPE_OCCT5VD         0x29

#define INF_TYPE_HDGHGA100HD1    0x41
#define INF_TYPE_HDGHGA100HD2    0x42
#define INF_TYPE_HDGHGS100HD1    0x43
#define INF_TYPE_HDGHGS100HD2    0x44
#define INF_TYPE_HDGHGLD1        0x45
#define INF_TYPE_HDGHGLD2        0x46
#define INF_TYPE_HDGHGPSAD       0x47
#define INF_TYPE_HDGHGPHEVVD     0x48
#define INF_TYPE_HDGHGPHEVFD     0x49
#define INF_TYPE_HDGHGPHEVGD     0x50
#define INF_TYPE_HDGHGATSS       0x51
#define INF_TYPE_HDGHGATAES      0x52
#define INF_TYPE_HDGHGATWHR      0x53
#define INF_TYPE_HDGHGAT1AT2     0x54
#define INF_TYPE_HDGHGAT3AT4     0x55
#define INF_TYPE_HDGHGAT5AT6     0x56
#define INF_TYPE_HDGHGAT7AT8     0x57
#define INF_TYPE_HDGHGAT9AT10    0x58
#define INF_TYPE_HDGHGAT11AT12   0x59
#define INF_TYPE_HDGHGAT13AT14   0x5A
#define INF_TYPE_HDGHGAT15AT16   0x5B

#define INF_TYPE_NOx100HMEOA     0x61
#define INF_TYPE_NOx100HMTA      0x62
#define INF_TYPE_NOx100HEOEA     0x63
#define INF_TYPE_NOx100HDTA      0x64
#define INF_TYPE_NOx100HERTA     0x65
#define INF_TYPE_NOx100HVFCA     0x66
#define INF_TYPE_NOx100HMEOS     0x67
#define INF_TYPE_NOx100HMTS      0x68
#define INF_TYPE_NOx100HEOES     0x69
#define INF_TYPE_NOx100HDTS      0x6A
#define INF_TYPE_NOx100HERTS     0x6B
#define INF_TYPE_NOx100HVFCS     0x6C
#define INF_TYPE_NOxVMEOL        0x6D
#define INF_TYPE_NOxVMTL         0x6E
#define INF_TYPE_NOxVEOEL        0x6F
#define INF_TYPE_NOxVDTL         0x70
#define INF_TYPE_NOxVERTL        0x71
#define INF_TYPE_NOxVVFCL        0x72
#define INF_TYPE_NOxEAEOEL       0x73
#define INF_TYPE_NOxEADTL        0x74
#define INF_TYPE_NOxEAERTL       0x75
#define INF_TYPE_NOxEAVFCL       0x76
#define INF_TYPE_NOxPMRVD        0x77
#define INF_TYPE_ER              0x78


// OBD message response data structures
#define MAX_NUM_SUP_BYTES        8    // $00, $20, $40, $60, $80, $A0, $C0, $E0
#define MAX_RESP_BUF_SIZE 2048
#define MAX_PID_RESP_SIZE 41
#define MAX_IPT_NODI        28      // number of IPT data items


typedef struct
{
	BYTE ID;
	BYTE Data[MAX_PID_RESP_SIZE];
} PID;

typedef struct
{
	BYTE ID;
	BYTE FrameNumber;
	BYTE Data[MAX_RESP_BUF_SIZE];
} FREEZEFRAME;

typedef struct
{
	BYTE ID;
	BYTE SDTID;
	BYTE UASID;
	BYTE TVHI;
	BYTE TVLO;
	BYTE MINTLHI;
	BYTE MINTLLO;
	BYTE MAXTLHI;
	BYTE MAXTLLO;
} MID;

typedef struct
{
	BYTE ID;
	BYTE NODI;
	BYTE Data[MAX_RESP_BUF_SIZE];
} INF;

typedef struct
{
	BYTE           ID;          // INF ID - 0x08 or 0x0B
	BYTE           NODI;        // number data items
	unsigned short Data[MAX_IPT_NODI];
	unsigned short Flags;       // application flags. set 1 when valid
} IPT;
#define  VALIDDATA   0x01
#define  IMREADYDONE 0x02
#define  IPTDONE     0x04
#define  ECUDONE     0x80

typedef struct
{
	BYTE ID;
	BYTE SupBits[4];
} ID_SUPPORT;

typedef struct
{
	BYTE ID;
	BYTE FrameNumber;
	BYTE SupBits[4];
} FF_SUPPORT;

typedef struct
{
	BYTE            Header[4];

	BOOL            bResponseReceived;  // used to check for multiple responses

	BOOL            bLinkActive;

	BYTE            PidSupportSize;
	ID_SUPPORT      PidSupport[MAX_NUM_SUP_BYTES];
	unsigned short  PidSize;            // number of bytes in array Pid
	BYTE            Pid[246];           // 6 * largest PID (81 - 41 bytes)

	BYTE            FFSupportSize;
	FF_SUPPORT      FFSupport[MAX_NUM_SUP_BYTES];
	unsigned short  FFSize;             // number of bytes in array FF
	BYTE            FF[MAX_RESP_BUF_SIZE];

	BOOL            bConfDTCSupported;
	unsigned short  ConfDTCSize;        // number of bytes in array ConfDTC
	BYTE            ConfDTC[MAX_RESP_BUF_SIZE];

	unsigned short  ClrDTCSize;
	BYTE            ClrDTC[8];

	BYTE            O2TidSupportSize;
	ID_SUPPORT      O2TidSupport[MAX_NUM_SUP_BYTES];
	unsigned short  O2TidSize;          // number of bytes in array O2Tid
	BYTE            O2Tid[MAX_RESP_BUF_SIZE];

	BYTE            MidSupportSize;
	ID_SUPPORT      MidSupport[MAX_NUM_SUP_BYTES];
	unsigned short  MidSize;            // number of bytes in array Mid
	BYTE            Mid[MAX_RESP_BUF_SIZE];

	BOOL            bPendDTCSupported;
	unsigned short  PendDTCSize;        // number of bytes in array PendDTC
	BYTE            PendDTC[MAX_RESP_BUF_SIZE];

	BYTE            TidSupportSize;
	ID_SUPPORT      TidSupport[MAX_NUM_SUP_BYTES];
	unsigned short  TidSize;            // number of bytes in array Tid
	BYTE            Tid[MAX_RESP_BUF_SIZE];

	BYTE            InfSupportSize;
	ID_SUPPORT      InfSupport[MAX_NUM_SUP_BYTES];
	unsigned short  InfSize;            // number of bytes in array INF
	BYTE            Inf[MAX_RESP_BUF_SIZE];

	BOOL            bPermDTCSupported;
	unsigned short  PermDTCSize;        // number of bytes in array PermDTC
	BYTE            PermDTC[MAX_RESP_BUF_SIZE];
} OBD_DATA;

typedef struct
{
	unsigned long  EcuId;                       // ID of the ECU
	BOOL           bNAKReceived;                // set if this ECU recieved a NAK on the latest request
	BOOL           bFFReceived;                 // set if this ECU recieved a First Frame of the latest response
	unsigned long  ResponseTimeExtensionMsecs;
	unsigned long  ResponsePendingDelayTimeMsecs;
	unsigned long  AggregateResponseTimeMsecs;  // Total Accumulated Response Time for this ECU
	unsigned long  AggregateResponses;          // Total number of responses from this ECU
	unsigned long  LongestResponsesTimeMsecs;   // Longest response time from this ECU
	unsigned long  RespTimeOutofRange;          // Count of response times outside expected range
	unsigned long  RespTimeTooLate;             // Count of response times too long
	unsigned long  RespTimeTooSoon;             // Count of response times too short
} ECU_TIMING_DATA;

#define  ECUNAME_BUFFER_SIZE  18
#define  TGEFN_BUFFER_SIZE    13
#define  VIN_BUFFER_SIZE      18  // 17 charters + NULL
#define  CVN_BUFFER_SIZE      16  // $XX $XX $XX $XX+NULL
#define  CALID_BUFFER_SIZE    17  // 123456789ABCDEF0+NULL
typedef struct
{
	unsigned long  EcuId;                       // ID of the ECU
	PID            Pid01;                       // this ECU's SID 01 PID 01 response
	PID            Pid41;                       // this ECU's SID 01 PID 41 response
	BOOL           bVinValid;                   // set if this ECU has a valid VIN
	char           VinString[VIN_BUFFER_SIZE];  // this ECU's VIN response
	unsigned int   CvnCount;                    // the number of CVN's in this ECU's response
	char          *pCvnString;                  // this ECU's CVN response
	unsigned int   CalidCount;                  // the number of CALID's in this ECU's response
	char          *pCalidString;                // this ECU's CALID response
	IPT           *pTest10_10_Ipt;              // this ECU's IPT response in Test 10.10
	IPT           *pIpt;                        // this ECU's IPT response
	INF           *pFEOCNTR;                    // this ECU's FEOCNTR response
} ECU_SID_DATA;

// Service ID (Mode) request structure
typedef struct
{
	BYTE SID;
	BYTE NumIds;
	BYTE ID[6];
} REQ_MSG;

typedef struct
{
	unsigned short Size;
	BYTE           DTC[2048];
} DTC_LIST;

#define MAX_CODE_STR_LEN  10

typedef struct
{
	ENGINETYPE     eEngineType;
	PWRTRNTYPE     ePwrTrnType;
	VEHICLETYPE    eVehicleType;
	COMPLIANCETYPE eComplianceType; // type of compliance being tested for
	SCANTABLETYPE  eScanTable;      // table of permutations used for OBD protocol scans
	BYTE           MaxProtocols;    // maximum number of OBD protocols
	BYTE           NumDCToSetMIL;   // count of drive cycles (either "two" or "three" ) with fault to set MIL
} USER_INPUT;


// Global function prototypes
// j1699.c
char * substring ( char       *str,
                   const char *substr ); // returns loc. of 'substr' in 'str'
unsigned long GetFailureCount ( void );     // returns global failure count
void   ClearKeyboardBuffer  ( void );
// end j1699.c
STATUS ClearCodes ( void );
// ConnectOBDProtocol.c
STATUS ConnectOBDProtocol ( void );
STATUS StartPeriodicMsg ( void );
STATUS StopPeriodicMsg ( BOOL bLogError );
// end ConnectOBDProtocol.c
// DetermineOBDProtocol.c
STATUS DetermineOBDProtocol ( void );
unsigned long GetEcuId ( BYTE EcuIdx );
// end DetermineOBDProtocol.c
STATUS DisconnectOBDProtocol ( void );
// IDSupport.c
STATUS RequestIDSupportData ( IDTYPE IdType,
                              BOOL   bVerifyECUCommunication );
STATUS RequestGroupIDSupportData ( IDTYPE IdType );
STATUS VerifyIDSupportData ( IDTYPE IdType );
STATUS CompareIDSupport ( BYTE       EcuIdx,          // The index of the current ECU
                          IDTYPE     IdType,          // Type of PID support array
                          BYTE       ResponseSize,    // Size of group/reverse PID Support response
                          BYTE       CompareSize,     // Size of single/normal PID Support response
                          ID_SUPPORT ResponseData[],  // Data of group/reverse PID Support response
                          ID_SUPPORT CompareData[],   // Data of single/normal PID Support response
                          BOOL       bGroup );        // Flag indicating if this is a group PID Support response
BOOL   IsIDSupported ( BYTE         EcuIdx,
                       IDTYPE       IdType,
                       unsigned int PidIdx );
// end IDSupport.c
STATUS IsDTCPending ( unsigned long Flags );
STATUS IsDTCStored ( unsigned long Flags );
void   LogMsg ( PASSTHRU_MSG *,
                unsigned long);
char   Log ( LOGTYPE      eLogType,
             SCREENOUTPUT ScreenOutput,
             LOGOUTPUT    LogOutput,
             PROMPTTYPE   ePromptType,
             const char  *LogString, ... );
STATUS RequestSid ( REQ_MSG *,
                    unsigned long );
void   StopTest ( STATUS ExitStatus,
                  TEST_PHASE eTestPhase );

STATUS Test5_NoDtc ( void );
STATUS Test6_PendingDtc ( void );
STATUS Test7_ConfirmedDtc ( void );
STATUS Test8_FaultRepaired ( void );
STATUS Test9_NoFaultsAfter3DriveCycles ( void );
STATUS Test9_8to21_PermanentCodes ( void );
STATUS Test10_InUseCounters ( BOOL *pbReEnterTest );
STATUS Test11_PerformanceCounters ( BOOL *pbReEnterTest );

STATUS VerifyTIDSupportAndData ( void );
STATUS VerifyPidBurstSupport ( void );
// VerifyPidSupportAndData.c
STATUS VerifyPidSupportAndData ( BOOL bEngineDontCare );
STATUS VerifyIM_Ready ( void );
// end VerifyPidSupportAndData.c
STATUS VerifyPendingDTCData ( void );
STATUS VerifyStoredDTCData ( void );
STATUS VerifyFFSupportAndData ( void );
STATUS VerifyECUCommunication ( void );
STATUS VerifyMILData ( void );
STATUS VerifyMIDSupportAndResults ( void );
STATUS VerifyO2TestResults ( void );
STATUS VerifyPermanentCodeSupport ( void );
STATUS VerifyReservedServices ( void );
STATUS VerifyINFSupportAndData ( void );
STATUS VerifyVehicleState ( BOOL ucEngineRunning,
                            BOOL ucHybrid );


// Global variables
extern FILE           *gTempLogFileHandle;
extern FILE           *gLogFileHandle;

extern char            gLogFileNameString[MAX_LOGFILENAME];
extern int             gModelYear;                        // integer version of model year entered by the user
extern int             gVINModelYear;                     // integer version of model year entered by the user (used for VIN checks)
extern char            gUserMakeString[80];               // make of vehicle entered by the user
extern char            gUserModelString[80];              // model of vehicle entered by the user
extern BYTE            gUserNumOfECUs;                    // number of ECUs entered by the user
extern BYTE            gUserNumOfECUsReprgm;              // number of reprogrammable ECUs entered by the user
extern BYTE            gNumOfECUsForAlloc;                // number of ECUs used for memory allocation
extern USER_INPUT      gstUserInput;                      // structure for user selected compliance test information
extern char           *gEngineTypeStrings[3];       // strings that represent the user selected engine type
extern char           *gPwrTrnTypeStrings[5];       // strings that represent the user selected powertrain type
extern char           *gVehicleTypeStrings[4];      // strings that represent the user selected vehicle type
extern char           *gComplianceTestTypeStrings[10];  // strings that represent the user selected compliance test
extern char           *gDisplayStrings[DSPSTR_TOTAL];   // strings used for display/logging
extern BOOL            gbDiesel;                          // set by the user if this is a compression ignition (diesel) vehicle
extern BOOL            gbHybrid;                          // set by the user if this is a hybrid vehicle
extern BOOL            gbPlugIn;                          // set by the user if this is a plug-in vehicle
extern BOOL            gbDynoCert;                        // set by the user if this is a Dyno Certified vehicle
extern BOOL            gbIgnoreUnsupported;               // set if a response to an unsupported PID should not Log a warning

extern BOOL            gbProtocolDetermined;              // set if a OBD protocol found
extern unsigned long   gRequestDelayTimeMsecs;
extern unsigned short  gProtocolIdx;                      // index of the OBD protocol being used
extern PROTOCOL_LIST   gstProtocolList[OBD_MAX_PROTOCOLS];
extern BYTE            gNumOfECUs;                        // number of responding ECUs
extern BYTE            gNumOfECUsResp;                    // number of responding ECUs
extern BOOL            gbSuspendScreenOutput;
extern BOOL            gbSuspendLogOutput;
extern OBD_DATA       *gstResponse;                       // pointer to the data from the latest response
extern OBD_DATA       *gstCompareResponse;                // pointer to the data from a previous response

extern BYTE            gReverseOrderStateArray[MAX_ECUS];  // state of reverse order request
#define NOT_REVERSE_ORDER              0x00  // not reverse order
#define REVERSE_ORDER_REQUESTED        0x01  // reverse order requested, no response yet
#define REVERSE_ORDER_RESPONSE         0x02  // first reverse order response received, SupportSize cleared
#define REVERSE_ORDER_GROUP_REQUESTED  0x04  // reverse order group requested, no response yet
#define REVERSE_ORDER_GROUP_RESPONSE1  0x08  // first reverse order group response received, $EO and $C0 and SupportSize cleared
#define REVERSE_ORDER_GROUP_RESPONSE2  0x10  // second reverse order group response received, $A0-$00 cleared

extern unsigned long   gDeviceID;               // global storage for J2534-1 Device ID
extern TEST_PHASE      geTestPhase;             // The current Test Phase
extern BYTE            gTestSubsection;         // The test subsection (to be used in conjunction with geTestPhase)
extern BOOL            gbDetermineProtocol;
extern BOOL            gbVerifyLink;            // set if in VerifyECUCommunication function
extern BOOL            gbEngineRunning;         // set if engine should be running
extern BOOL            gbEngineWarm;            // set if engine should be warm
extern BOOL            gbDTCPending;            // set if a DTC should be pending
extern BOOL            gbDTCStored;             // set if a DTC should be stored
extern BOOL            gbDTCHistorical;
extern BOOL            gbDTCPermanent;          // set if a DTC should be permanent
extern BOOL            gbTestSectionAborted;    // set if a test section (Static/Dynamic) was aborted,
                                                // clear only before the Static test and before Dynamic tests
extern BOOL            gbTestSectionFailed;     // set if a test (static/dynamic) failed,
                                                // clear only at the beginning of the Static or Dynamic test
extern BOOL            gbTestSubsectionFailed;  // set if a test subsection failed,
                                                // clear before each subsection (ie test 5.10, test 7.4, etc)
extern BOOL            gbTestAborted;           // set if any test was aborted,
                                                // clear only before running Static and Dynamic tests
extern BOOL            gbTestFailed;            // set if any test failed,
                                                // clear only before running Static and Dynamic tests

extern char            gVINString[VIN_BUFFER_SIZE];
extern DTC_LIST       *gstDTCList;
extern ECU_TIMING_DATA *gstEcuTimingData;
extern ECU_SID_DATA   *gstEcuSIDData;
