/*******************************************************************************
********************************************************************************
**
**  Copyright(c) 2022, Alliance for Automotive Innovation
**  Used only under license from the Alliance for Automotive Innovation. All Rights Reserved.
**
**  Project:  J1699-3
**  FileName: InitProtocol.c
**  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
**
********************************************************************************
*******************************************************************************/

#include <stdio.h>    // C Library input and output declarations
#include <string.h>   // C Library character array declarations
#include <windows.h>  // Windows API declarations
#include "j2534.h"    // j1699 project j2534 declarations
#include "j1699.h"    // j1699 project general declarations


/*******************************************************************************
**  Protocol Init and Permutation data
*******************************************************************************/
typedef struct
{
	unsigned long  eProtocol;     // generic protocol (for J2534-1)
	unsigned long  eInitFlags;    // J2534-1 ConnectFlags
	BYTE           HeaderSize;    // size of message header
	unsigned long  BaudRate;      // link data rate
	unsigned long  eProtocolTag;  // tag that uniquely identifies each protocol
	char          *Name;          // ASCII string for the protocol name
} PROTOCOL_INIT;

// The order of this must match the ProtocolTag definitions in J1699.h
static PROTOCOL_INIT ProtocolInitData[] =
{
  // Protocol Flags                  HeaderSize  Baud    ProtocolTag             Name (<25 char - see PROTOCOL_LIST)
	{J1850PWM, 0,                    3,          41600,  J1850PWM_I,             "J1850PWM"},
	{J1850VPW, 0,                    3,          10400,  J1850VPW_I,             "J1850VPW"},
	{ISO9141,  ISO9141_K_LINE_ONLY,  3,          10400,  ISO9141_I,              "ISO9141"},
	{ISO14230, FAST_INIT,            3,          10400,  ISO14230_FAST_INIT_I,   "ISO14230 Fast Init"},
	{ISO14230, 0,                    3,          10400,  ISO14230_I,             "ISO14230"},
	{ISO15765, 0,                    4,          500000, ISO15765_I,             "500K ISO15765 11 Bit"},
	{ISO15765, CAN_29BIT_ID,         4,          500000, ISO15765_29_BIT_I,      "500K ISO15765 29 Bit"},
	{ISO15765, 0,                    4,          250000, ISO15765_250K_11_BIT_I, "250K ISO15765 11 Bit"},
	{ISO15765, CAN_29BIT_ID,         4,          250000, ISO15765_250K_29_BIT_I, "250K ISO15765 29 Bit"}
};

static unsigned int USProtocolPerm[][OBD_MAX_US_PROTOCOLS] =
{
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I, ISO15765_I, ISO15765_29_BIT_I},  // 5.2, 10.1
	{J1850PWM_I, J1850VPW_I, ISO14230_FAST_INIT_I, ISO9141_I, ISO14230_I, ISO15765_29_BIT_I, ISO15765_I},  // 5.8
	{J1850PWM_I, J1850VPW_I, ISO14230_FAST_INIT_I, ISO14230_I, ISO9141_I, ISO15765_I, ISO15765_29_BIT_I},  // 6.2
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_29_BIT_I, ISO15765_I},  // 7.2
	{J1850VPW_I, J1850PWM_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_29_BIT_I, ISO15765_I},  // 8.2
	{ISO15765_I, ISO15765_29_BIT_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I},  // 9.2
	{ISO15765_29_BIT_I, ISO15765_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I},  // 9.9
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_29_BIT_I, ISO15765_I},  // 9.13
	{ISO15765_29_BIT_I, ISO15765_I, J1850VPW_I, J1850PWM_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I},  // 9.17
	{ISO15765_I, ISO15765_29_BIT_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I}   // 9.21
};
#define NUM_US_PROTOCOL_PERM   (sizeof ( USProtocolPerm ) / sizeof ( USProtocolPerm[0] ))

static unsigned int EUProtocolPerm[][OBD_MAX_EU_PROTOCOLS] =
{
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I, ISO15765_I, ISO15765_250K_11_BIT_I, ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I},  // 5.2, 10.1
	{J1850PWM_I, J1850VPW_I, ISO14230_FAST_INIT_I, ISO9141_I, ISO14230_I, ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I, ISO15765_I, ISO15765_250K_11_BIT_I},  // 5.8
	{J1850PWM_I, J1850VPW_I, ISO14230_FAST_INIT_I, ISO14230_I, ISO9141_I, ISO15765_I, ISO15765_250K_11_BIT_I, ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I},  // 6.2
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I, ISO15765_I, ISO15765_250K_11_BIT_I},  // 7.2
	{J1850VPW_I, J1850PWM_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I, ISO15765_I, ISO15765_250K_11_BIT_I},  // 8.2
	{ISO15765_I, ISO15765_250K_11_BIT_I, ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I},  // 9.2
	{ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I, ISO15765_I, ISO15765_250K_11_BIT_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I},  // 9.9
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I, ISO15765_I, ISO15765_250K_11_BIT_I},  // 9.13
	{ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I, ISO15765_I, ISO15765_250K_11_BIT_I, J1850VPW_I, J1850PWM_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I},  // 9.17
	{ISO15765_I, ISO15765_250K_11_BIT_I, ISO15765_29_BIT_I, ISO15765_250K_29_BIT_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I}   // 9.21
};
#define NUM_EU_PROTOCOL_PERM   (sizeof ( EUProtocolPerm ) / sizeof ( EUProtocolPerm[0] ))

static unsigned int EU250KProtocolPerm[][OBD_MAX_EU250K_PROTOCOLS] =
{
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I, ISO15765_250K_11_BIT_I, ISO15765_250K_29_BIT_I},  // 5.2, 10.1
	{J1850PWM_I, J1850VPW_I, ISO14230_FAST_INIT_I, ISO9141_I, ISO14230_I, ISO15765_250K_29_BIT_I, ISO15765_250K_11_BIT_I},  // 5.8
	{J1850PWM_I, J1850VPW_I, ISO14230_FAST_INIT_I, ISO14230_I, ISO9141_I, ISO15765_250K_11_BIT_I, ISO15765_250K_29_BIT_I},  // 6.2
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_250K_29_BIT_I, ISO15765_250K_11_BIT_I},  // 7.2
	{J1850VPW_I, J1850PWM_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_250K_29_BIT_I, ISO15765_250K_11_BIT_I},  // 8.2
	{ISO15765_250K_11_BIT_I, ISO15765_250K_29_BIT_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I},  // 9.2
	{ISO15765_250K_29_BIT_I, ISO15765_250K_11_BIT_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I},  // 9.9
	{J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I, ISO15765_250K_29_BIT_I, ISO15765_250K_11_BIT_I},  // 9.13
	{ISO15765_250K_29_BIT_I, ISO15765_250K_11_BIT_I, J1850VPW_I, J1850PWM_I, ISO9141_I, ISO14230_I, ISO14230_FAST_INIT_I},  // 9.17
	{ISO15765_250K_11_BIT_I, ISO15765_250K_29_BIT_I, J1850PWM_I, J1850VPW_I, ISO9141_I, ISO14230_FAST_INIT_I, ISO14230_I}   // 9.21
};
#define NUM_EU250K_PROTOCOL_PERM   (sizeof ( EU250KProtocolPerm ) / sizeof ( EU250KProtocolPerm[0] ))

unsigned short   gProtocolSrchIdx = 0;


/*******************************************************************************
**
**  Function:  InitOBDProtocolList
**
**  Purpose:   Initialize the protocol list
**
*******************************************************************************/
void InitOBDProtocolList ( void )
{
	unsigned long i;
	unsigned long j;


	if ( gstUserInput.eScanTable == USOBD )
	{
		gstUserInput.MaxProtocols = OBD_MAX_US_PROTOCOLS;

		// initialize gstProtocolList for US
		for ( i = 0;
		      i < gstUserInput.MaxProtocols;
		      i++ ) // should be OBD_MAX_US_PROTOCOLS
		{
			j = USProtocolPerm[gProtocolSrchIdx][i];

			gstProtocolList[i].eProtocol    = ProtocolInitData[j].eProtocol;
			gstProtocolList[i].eInitFlags   = ProtocolInitData[j].eInitFlags;
			gstProtocolList[i].HeaderSize   = ProtocolInitData[j].HeaderSize;
			gstProtocolList[i].BaudRate     = ProtocolInitData[j].BaudRate;
			gstProtocolList[i].eProtocolTag = ProtocolInitData[j].eProtocolTag;
			strcpy_s ( gstProtocolList[i].Name, MAX_PROTOCOL_NAME, ProtocolInitData[j].Name );

			gstProtocolList[i].ChannelID  = 0;
		}

		// If at end of order, start over
		if ( ++gProtocolSrchIdx >= NUM_US_PROTOCOL_PERM )
		{
			gProtocolSrchIdx = 0;
		}
	}
	else if ( gstUserInput.eScanTable == EOBD )
	{
		gstUserInput.MaxProtocols = OBD_MAX_EU_PROTOCOLS;

		// initialize gstProtocolList for EU
		for ( i = 0;
		      i < gstUserInput.MaxProtocols;
		      i++ ) // should be OBD_MAX_EU_PROTOCOLS
		{
			j = EUProtocolPerm[gProtocolSrchIdx][i];

			gstProtocolList[i].eProtocol    = ProtocolInitData[j].eProtocol;
			gstProtocolList[i].eInitFlags   = ProtocolInitData[j].eInitFlags;
			gstProtocolList[i].HeaderSize   = ProtocolInitData[j].HeaderSize;
			gstProtocolList[i].BaudRate     = ProtocolInitData[j].BaudRate;
			gstProtocolList[i].eProtocolTag = ProtocolInitData[j].eProtocolTag;
			strcpy_s ( gstProtocolList[i].Name, MAX_PROTOCOL_NAME, ProtocolInitData[j].Name );

			gstProtocolList[i].ChannelID  = 0;
		}

		// If at end of order, start over
		if ( ++gProtocolSrchIdx >= NUM_EU_PROTOCOL_PERM )
		{
			gProtocolSrchIdx = 0;
		}
	}
	else if ( gstUserInput.eScanTable == EOBD_250K )
	{
		gstUserInput.MaxProtocols = OBD_MAX_EU250K_PROTOCOLS;

		// initialize gstProtocolList for EU
		for ( i = 0;
		      i < gstUserInput.MaxProtocols;
		      i++ ) // should be OBD_MAX_EU_PROTOCOLS
		{
			j = EU250KProtocolPerm[gProtocolSrchIdx][i];

			gstProtocolList[i].eProtocol    = ProtocolInitData[j].eProtocol;
			gstProtocolList[i].eInitFlags   = ProtocolInitData[j].eInitFlags;
			gstProtocolList[i].HeaderSize   = ProtocolInitData[j].HeaderSize;
			gstProtocolList[i].BaudRate     = ProtocolInitData[j].BaudRate;
			gstProtocolList[i].eProtocolTag = ProtocolInitData[j].eProtocolTag;
			strcpy_s ( gstProtocolList[i].Name, MAX_PROTOCOL_NAME, ProtocolInitData[j].Name );

			gstProtocolList[i].ChannelID  = 0;
		}

		// If at end of order, start over
		if ( ++gProtocolSrchIdx >= NUM_EU_PROTOCOL_PERM )
		{
			gProtocolSrchIdx = 0;
		}
	}
}
