/*******************************************************************************
********************************************************************************
**
**  Copyright(c) 2022, Alliance for Automotive Innovation
**  Used only under license from the Alliance for Automotive Innovation. All Rights Reserved.
**
**  Project:  J1699-5
**  FileName: InitOBDProtocolList.c
**  Author:   EnGenius
**  Date:     2/25/2022
**  Email:    <support@autosinnovate.org>
**
**  Purpose:  SAE J1699-5 Vehicle OBD II Compliance Test Cases Source Code.
**            This source code is intended to run the tests described in
**            the SAE J1699-5 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:  03/13/2023  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
*******************************************************************************/
// Maximum number of bytes in ISO15765 frame
#define ISO15765_MAX_BYTES_PER_FRAME 7
#define ISO15765_HEADER_SIZE         4
#define ISO15765_SID_OFFSET          ISO15765_HEADER_SIZE
#define ISO15765_DID_MSB_OFFSET      ISO15765_HEADER_SIZE + 1
#define ISO15765_DID_LSB_OFFSET      ISO15765_HEADER_SIZE + 2
#define ISO15765_DATA_OFFSET         ISO15765_HEADER_SIZE + 3

#define DOIP_HEADER_SIZE             12
#define DOIP_SID_OFFSET              DOIP_HEADER_SIZE
#define DOIP_DID_MSB_OFFSET          DOIP_HEADER_SIZE + 1
#define DOIP_DID_LSB_OFFSET          DOIP_HEADER_SIZE + 2
#define DOIP_DATA_OFFSET             DOIP_HEADER_SIZE + 3

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[OBD_MAX_PROTOCOLS] =
{
	// Protocol  Flags                                   HeaderSize             Baud     ProtocolTag                 Name (<25 char - see PROTOCOL_LIST)
	{ISO15765,   0,                                      ISO15765_HEADER_SIZE,  500000,  ISO15765_I,                 "500K ISO15765 11 Bit"},
	{ISO15765,   CAN_29BIT_ID,                           ISO15765_HEADER_SIZE,  500000,  ISO15765_29_BIT_I,          "500K ISO15765 29 Bit"},
	{ISO15765,   CLASSIC_J1979_SERVICES,                 ISO15765_HEADER_SIZE,  500000,  ISO15765_CLASSIC_I,         "500K ISO15765 11 Bit (Classic J1979 Services)"},
	{ISO15765,   CLASSIC_J1979_SERVICES | CAN_29BIT_ID,  ISO15765_HEADER_SIZE,  500000,  ISO15765_CLASSIC_29_BIT_I,  "500K ISO15765 29 Bit (Classic J1979 Services)"},
};

static unsigned int ProtocolPerm[][OBD_MAX_PROTOCOLS] =
{
	{ISO15765_CLASSIC_I,        ISO15765_CLASSIC_29_BIT_I, ISO15765_I,                ISO15765_29_BIT_I},          // 5.2, 10.1
	{ISO15765_29_BIT_I,         ISO15765_I,                ISO15765_CLASSIC_29_BIT_I, ISO15765_CLASSIC_I },        // 5.8
	{ISO15765_I,                ISO15765_29_BIT_I,         ISO15765_CLASSIC_I,        ISO15765_CLASSIC_29_BIT_I},  // 6.2
	{ISO15765_CLASSIC_29_BIT_I, ISO15765_CLASSIC_I,        ISO15765_29_BIT_I,         ISO15765_I},                 // 7.2
	{ISO15765_CLASSIC_I,        ISO15765_I,                ISO15765_CLASSIC_29_BIT_I, ISO15765_29_BIT_I},          // 8.2
	{ISO15765_29_BIT_I,         ISO15765_CLASSIC_29_BIT_I, ISO15765_I,                ISO15765_CLASSIC_I},         // 9.2
	{ISO15765_29_BIT_I,         ISO15765_CLASSIC_I,        ISO15765_CLASSIC_29_BIT_I, ISO15765_I},                 // 9.9
	{ISO15765_CLASSIC_29_BIT_I, ISO15765_29_BIT_I,         ISO15765_CLASSIC_I,        ISO15765_I},                 // 9.13
	{ISO15765_I,                ISO15765_CLASSIC_I,        ISO15765_29_BIT_I,         ISO15765_CLASSIC_29_BIT_I},  // 9.17
	{ISO15765_CLASSIC_I,        ISO15765_29_BIT_I,         ISO15765_I,                ISO15765_CLASSIC_29_BIT_I}   // 9.21
};
#define NUM_PROTOCOL_PERM   (sizeof ( ProtocolPerm )/sizeof ( ProtocolPerm[0] ))


// The order of this must match the ProtocolTag definitions in J1699.h
static PROTOCOL_INIT ProtocolZEVInitData[OBD_ZEV_MAX_PROTOCOLS] =
{
	// Protocol  Flags          HeaderSize             Baud       ProtocolTag           Name (<25 char - see PROTOCOL_LIST)
	{ISO15765,   0,             ISO15765_HEADER_SIZE,    500000,  ISO15765_ZEV,         "500K ISO15765 11 Bit"},
	{ISO15765,   CAN_29BIT_ID,  ISO15765_HEADER_SIZE,    500000,  ISO15765_29_BIT_ZEV,  "500K ISO15765 29 Bit"},
//	{DOIP,       0,             DOIP_HEADER_SIZE,      10000000,  ETHERNET,             "10M DoIP"},
	{DOIP_NDIS,  0,             DOIP_HEADER_SIZE,      10000000,  ETHERNET_NDIS,        "10M DoIP_NDIS"},
};


static unsigned int ProtocolZEVPerm[][OBD_ZEV_MAX_PROTOCOLS] =
{
//	{ISO15765_I,   ISO15765_29_BIT_I,  DOIP_I,            DOIP_NDIS_I},
	{ISO15765_ZEV,   ISO15765_29_BIT_ZEV,  DOIP_NDIS_I},
//	{DOIP_NDIS_I,  DOIP_I,             ISO15765_29_BIT_I, ISO15765_I},
	{DOIP_NDIS_I,  ISO15765_29_BIT_ZEV,  ISO15765_ZEV},
};
#define NUM_PROTOCOL_ZEV_PERM   (sizeof ( ProtocolZEVPerm )/sizeof ( ProtocolZEVPerm[0] ))


unsigned short   gProtocolSrchIdx = 0;


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


	if ( gstUserInput.eEnergyType != ZEV )
	{
		gstUserInput.MaxProtocols = OBD_MAX_PROTOCOLS;

		// initialize gstProtocolList
		for ( i = 0;
		      i < gstUserInput.MaxProtocols;
		      i++ )
		{
			j = ProtocolPerm[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_PROTOCOL_PERM )
		{
			gProtocolSrchIdx = 0;
		}
	}
	else
	{
		gstUserInput.MaxProtocols = OBD_ZEV_MAX_PROTOCOLS;

		// initialize gstProtocolList
		for ( i = 0;
		      i < gstUserInput.MaxProtocols;
		      i++ )
		{
			j = ProtocolZEVPerm[gProtocolSrchIdx][i];

			gstProtocolList[i].eProtocol     = ProtocolZEVInitData[j].eProtocol;
			gstProtocolList[i].eInitFlags    = ProtocolZEVInitData[j].eInitFlags;
			gstProtocolList[i].HeaderSize    = ProtocolZEVInitData[j].HeaderSize;
			gstProtocolList[i].BaudRate      = ProtocolZEVInitData[j].BaudRate;
			gstProtocolList[i].eProtocolTag  = ProtocolZEVInitData[j].eProtocolTag;
			strcpy_s ( gstProtocolList[i].Name,
			           MAX_PROTOCOL_NAME,
			           ProtocolZEVInitData[j].Name );
	
			gstProtocolList[i].ChannelID  = 0;
		}
	
		// If at end of order, start over
		if ( ++gProtocolSrchIdx >= NUM_PROTOCOL_ZEV_PERM )
		{
			gProtocolSrchIdx = 0;
		}
	}
}
