//
// Copyright (c) 2015-2016 DashLogic, Inc.
// All Rights Reserved.
//
// http://www.dashlogic.com
// sales@dashlogic.com
//
// Redistribution and use in source and binary forms, with or without
// modification, including use for commercial purposes, are permitted
// provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materials provided with the
//    distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// 4. Redistributions of any form whatsoever must retain the following
//    acknowledgment: 'This product includes software developed by 
//    "DashLogic, Inc." (http://www.dashlogic.com/).'
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//


//
// Formatting:
//  Indents:	Use tabs only (1 tab per indent)
//	Tab Size:	4 spaces
//
// File Revision:
// $Rev: 5220 $
// $Date: 2016-03-16 08:31:37 -0600 (Wed, 16 Mar 2016) $
//


#ifndef __PASSTHRUHELPER0404_H
#define __PASSTHRUHELPER0404_H



//
// If you already have your own J2534 API defines set up
// in your own header files, you can #define the macro
// DONT_INCLUDE_J2534_DEFINES so that we don't include
// them again, which would result in a macro redefined
// warning or error.
//
#ifndef DONT_INCLUDE_J2534_DEFINES
  #include "J2534_v0404.h"
#endif


//
// The purpose of the PassThruHelper0404ApiFuncs class is to hold pointers to all of
// the Pass-Thru J2534 API functions. The PassThruHelper0404 class will instantiate a
// PassThruHelper0404ApiFuncs object upon loading a J2534 DLL. This class is also
// virtual, which allows you as the user to derive your own class from it and provide
// the API functions yourself. This will allow you to call your own functions and/or
// intercept return values, etc. When you provide your own PassThruHelper0404ApiFuncs
// object, you simply give the PassThruHelper0404 class a pointer to it, and you are
// responsible for managing and freeing the memory associated with it as well as
// loading and unloading of any associated J2534 DLLs.
//
class PassThruHelper0404ApiFuncs
{
	friend class PassThruHelper0404;

public:
	PassThruHelper0404ApiFuncs();
	virtual ~PassThruHelper0404ApiFuncs();

protected:
	void*			m_pPassThruOpenFunc;
	void*			m_pPassThruCloseFunc;
	void*			m_pPassThruConnectFunc;
	void*			m_pPassThruDisconnectFunc;
	void*			m_pPassThruReadMsgsFunc;
	void*			m_pPassThruWriteMsgsFunc;
	void*			m_pPassThruStartPeriodicMsgFunc;
	void*			m_pPassThruStopPeriodicMsgFunc;
	void*			m_pPassThruStartMsgFilterFunc;
	void*			m_pPassThruStopMsgFilterFunc;
	void*			m_pPassThruSetProgrammingVoltageFunc;
	void*			m_pPassThruReadVersionFunc;
	void*			m_pPassThruGetLastErrorFunc;
	void*			m_pPassThruIoctlFunc;

public:
	virtual long	PassThruOpen(void *pName, unsigned long *pDeviceID);
	virtual long	PassThruClose(unsigned long DeviceID);
	virtual long	PassThruConnect(unsigned long DeviceID, unsigned long ProtocolID, unsigned long Flags, unsigned long BaudRate, unsigned long *pChannelID);
	virtual long	PassThruDisconnect(unsigned long ChannelID);
	virtual long	PassThruReadMsgs(unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
	virtual long	PassThruWriteMsgs(unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
	virtual long	PassThruStartPeriodicMsg(unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval);
	virtual long	PassThruStopPeriodicMsg(unsigned long ChannelID, unsigned long MsgID);
	virtual long	PassThruStartMsgFilter(unsigned long ChannelID, unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg, PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID);
	virtual long	PassThruStopMsgFilter(unsigned long ChannelID, unsigned long FilterID);
	virtual long	PassThruSetProgrammingVoltage(unsigned long DeviceID, unsigned long PinNumber, unsigned long Voltage);
	virtual long	PassThruReadVersion(unsigned long DeviceID, char *pFirmwareVersion, char *pDllVersion, char *pApiVersion);
	virtual long	PassThruGetLastError(char *pErrorDescription);
	virtual long	PassThruIoctl(unsigned long ChannelID, unsigned long IoctlID, void *pInput, void *pOutput);
};


#define PT0404HELPER_MAX_DEVICES		4		// Max open devices at any one time (per class instance object)
#define PT0404HELPER_MAX_CHANNELS		40		// Max open channels at any one time (per class instance object)
#define PT0404HELPER_MAX_FILTERS		200		// Max number of filters (across all open channels in a single class instance object)
#define PT0404HELPER_MAX_PERIODICS		200		// Max number of periodics (across all open channels in a single class instance object)

typedef struct 
{
	bool			m_bDeviceOpen;
	unsigned long	m_DeviceId;
} PT0404HELPER_DEVICE_INFO;

typedef struct 
{
	bool			m_bChannelOpen;
	unsigned long	m_DeviceId;
	unsigned long	m_ChannelId;
} PT0404HELPER_CHANNEL_INFO;

typedef struct 
{
	bool			m_bFilterInUse;
	unsigned long	m_ChannelId;
	unsigned long	m_FilterId;
} PT0404HELPER_FILTER_INFO;

typedef struct 
{
	bool			m_bPeriodicInUse;
	unsigned long	m_ChannelId;
	unsigned long	m_PeriodicId;
} PT0404HELPER_PERIODIC_INFO;

typedef void	(*ENUMERATE_PASSTHRU_DEVICES_CALLBACK_PROTOTYPE) (const char* strVendorName, const char* strDeviceName, const char* strLibraryPath);


//
// The PassThruHelper0404 encapsulates the J2534 v04.04 API and provides
// a C++ interface to it. This class will also automatically clean up
// upon destruction by closing all open devices (which implicitly closes
// all open channels, which in turn clears all filters and periodics).
//
class PassThruHelper0404
{
public:
	PassThruHelper0404();
	virtual ~PassThruHelper0404();

private:
	PassThruHelper0404ApiFuncs*		m_pApiFuncs;
	bool							m_bUserProvidedApiFuncs;

	void*							m_PassThruLibraryHandle;
	bool							m_bPassThruLibraryHandleValid;

	PT0404HELPER_DEVICE_INFO		m_DeviceList[PT0404HELPER_MAX_DEVICES];
	PT0404HELPER_CHANNEL_INFO		m_ChannelList[PT0404HELPER_MAX_CHANNELS];
	PT0404HELPER_FILTER_INFO		m_FilterList[PT0404HELPER_MAX_FILTERS];
	PT0404HELPER_PERIODIC_INFO		m_PeriodicList[PT0404HELPER_MAX_PERIODICS];

	bool							m_bHasLocalError;
	char							m_strLocalErrorDescription[100];

public:
	// J2534 DLL Enumeration Functions
	bool			EnumeratePassThruDevices(ENUMERATE_PASSTHRU_DEVICES_CALLBACK_PROTOTYPE pCallback);

public:
	// Initialization Functions
	bool			LoadPassThruLibrary(const char* strLibraryPath);
	void			CloseAllAndUnloadPassThruLibrary();		// Closes the device and all channels and then unloads the J2534 DLL (if we loaded it)

	// J2534 API Functions
	long			PassThruOpen(void *pName, unsigned long *pDeviceID);
	long			PassThruClose(unsigned long DeviceID);
	long			PassThruConnect(unsigned long DeviceID, unsigned long ProtocolID, unsigned long Flags, unsigned long BaudRate, unsigned long *pChannelID);
	long			PassThruDisconnect(unsigned long ChannelID);
	long			PassThruReadMsgs(unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
	long			PassThruWriteMsgs(unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
	long			PassThruStartPeriodicMsg(unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval);
	long			PassThruStopPeriodicMsg(unsigned long ChannelID, unsigned long MsgID);
	long			PassThruStartMsgFilter(unsigned long ChannelID, unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg, PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID);
	long			PassThruStopMsgFilter(unsigned long ChannelID, unsigned long FilterID);
	long			PassThruSetProgrammingVoltage(unsigned long DeviceID, unsigned long PinNumber, unsigned long Voltage);
	long			PassThruReadVersion(unsigned long DeviceID, char *pFirmwareVersion, char *pDllVersion, char *pApiVersion);
	long			PassThruGetLastError(char *pErrorDescription);
	long			PassThruIoctl(unsigned long ChannelID, unsigned long IoctlID, void *pInput, void *pOutput);

private:
	// Internal Functions
	long			ReturnLocalError(unsigned long ErrorCode, const char* strErrorDescription);
};



#endif // __PASSTHRUHELPER0404_H
