/*
********************************************************************************
** SAE J1699-3 Test Source Code
**
**  Copyright (C) 2002 Drew Technologies. http://j1699-3.sourceforge.net/
**
** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation; either version 2 of the License, or
**  (at your option) any later version.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**
** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**
** This source code, when compiled and used with an SAE J2534-compatible pass
** thru device, is intended to run the tests described in the SAE J1699-3
** document in an automated manner.
**
** This computer program is based upon SAE Technical Report J1699,
** which is provided "AS IS"
**
** See j1699.c for details of how to build and run this test.
**
********************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include "j2534.h"
#include "j1699.h"

/*
***************************************************************************************************
** ClearCodes - Function to clear OBD diagnostic information
***************************************************************************************************
*/
STATUS ClearCodes(void)
{
	SID_REQ       SidReq;
	STATUS eReturnCode = PASS;  // saves the return code from function calls
	unsigned long EcuIndex;
	unsigned short usIMReadinessCount = 0;
	unsigned short usIMRPosAckCount = 0;
	unsigned short usPositiveAckCount = 0;
	unsigned short usRetryCount = 0;

	/* Reset the global DTC data */
	gOBDDTCPending = FALSE;
	gOBDDTCStored  = FALSE;

	usIMReadinessCount = 0;
	usIMRPosAckCount   = 0;
	usPositiveAckCount = 0;

	/* Send SID 4 request */
	SidReq.SID = 4;
	SidReq.NumIds = 0;
	eReturnCode = SidRequest(&SidReq, SID_REQ_ALLOW_NO_RESPONSE);

	/* Delay after request to allow time for codes to clear */
	Sleep (CLEAR_CODES_DELAY_MSEC);

	if (eReturnCode != FAIL)
	{
		eReturnCode = PASS;  // mark it as PASS, since ERROR can get here too

		if (gOBDNumEcusResp == 0)
		{
			if ( gOBDEngineRunning == FALSE )
			{
				Log( FAILURE, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				     "No response to SID $4 request\n");
				eReturnCode = FAIL;
			}
			else
			{
				Log( WARNING, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				     "No response to SID $4 request\n");
			}
		}
		else
		{
			/* all ECUs must respond with the same ackowledgement (positive or negative) with engine running */
			for (EcuIndex = 0; EcuIndex < gUserNumEcus; EcuIndex++)
			{
				if ( (Sid1Pid1[EcuIndex].Data[1] & 0x03) != 0x00 ||
				     (Sid1Pid1[EcuIndex].Data[2] & 0xFF) != 0x00 )
				{
					usIMReadinessCount++;
				}

				if ( gOBDResponse[EcuIndex].Sid4Size > 0 && gOBDResponse[EcuIndex].Sid4[0] == 0x44 )
				{
					if ( gOBDEngineRunning == TRUE  &&
					     ( (Sid1Pid1[EcuIndex].Data[1] & 0x03) != 0x00 ||
					       (Sid1Pid1[EcuIndex].Data[2] & 0xFF) != 0x00 ) )
					{
						usIMRPosAckCount++;
					}
					else
					{
						usPositiveAckCount++;
					}
					Log( INFORMATION, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
					     "ECU %X  Positive response to SID $4 request\n",
					     GetEcuId(EcuIndex) );
				}

				if ( gOBDEngineRunning == TRUE  &&
				     ( Sid1Pid1[EcuIndex].Data[1] != 0x00 ||
				       Sid1Pid1[EcuIndex].Data[2] != 0x00 ) )
				{
					Log( INFORMATION, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				         "ECU %X  IM Readiness in SID $1 PID $01  Byte B = 0x%02X  Byte C = 0x%02X\n",
				         GetEcuId(EcuIndex),
				         Sid1Pid1[EcuIndex].Data[1],
				         Sid1Pid1[EcuIndex].Data[2] );
				}
			}

			// IF the number of responding ECUs is greater than the user entered number
			// OR there are no responding ECUs.
			if ( gOBDNumEcusResp > gUserNumEcus  ||
			     gOBDNumEcusResp == 0 )
			{
				Log( FAILURE, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				     "Incorrect number of responses to SID $4 request\n");
				eReturnCode = FAIL;
			}

			/* Check that all ECUs with IM Readiness response the same
			// (all positive or all negative) with engine running */
			if ( gOBDEngineRunning == TRUE &&
			     usIMReadinessCount != 0 &&
			     ( ( usPositiveAckCount != 0 ||
			           usIMRPosAckCount != 0 ) &&
			       usIMReadinessCount != usIMRPosAckCount ) )
			{
				Log( FAILURE, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				     "Received both positive and negative responses from ECUs containing IM Readiness.\n" );
				eReturnCode = FAIL;
			}
			else if ( gOBDEngineRunning == FALSE &&
			          gOBDNumEcusResp != (unsigned long)(usPositiveAckCount + usIMRPosAckCount) )
			{
				Log( FAILURE, SCREENOUTPUTON, LOGOUTPUTON, NO_PROMPT,
				     "Not all ECU responses positive.\n" );
				eReturnCode = FAIL;
			}
		}
	}

	return(eReturnCode);
}
