#include "StdAfx.h"
#include "GobiApiPds.h"
#include "FuncList.h"
#include "StatusCtrl.h"
#include "GobiConnectionMgmtAPI.h"
#include <GobiAPI.h>
#include "SwiWwanCmApi.h"
#include "winsock2.h"

#define FUNC_GetPDSState					L"GetPDSState"
#define FUNC_SetPDSState					L"SetPDSState"
#define FUNC_StartPDSTrackingSession		L"StartPDSTrackingSession"
#define FUNC_StopPDSTrackingSession			L"StopPDSTrackingSession"
#define FUNC_PDSInjectTimeReference			L"PDSInjectTimeReference"
#define FUNC_GetPDSDefaults					L"GetPDSDefaults"
#define FUNC_SetPDSDefaults					L"SetPDSDefaults"
#define FUNC_GetXTRAAutomaticDownload		L"GetXTRAAutomaticDownload"
#define FUNC_SetXTRAAutomaticDownload		L"SetXTRAAutomaticDownload"
#define FUNC_GetXTRANetwork					L"GetXTRANetwork"
#define FUNC_SetXTRANetwork					L"SetXTRANetwork"
#define FUNC_GetXTRAValidity				L"GetXTRAValidity"
#define FUNC_ForceXTRADownload				L"ForceXTRADownload"
#define FUNC_GetAGPSConfig					L"GetAGPSConfig"
#define FUNC_SetAGPSConfig					L"SetAGPSConfig"
#define FUNC_GetServiceAutomaticTracking	L"GetServiceAutomaticTracking"
#define FUNC_SetServiceAutomaticTracking	L"SetServiceAutomaticTracking"
#define FUNC_GetPortAutomaticTracking		L"GetPortAutomaticTracking"
#define FUNC_SetPortAutomaticTracking		L"SetPortAutomaticTracking"
#define FUNC_ResetPDSData					L"ResetPDSData"
#define FUNC_GetXTRADataState				L"GetXTRADataState"
#define FUNC_SetXTRADataState				L"SetXTRADataState"
#define FUNC_GetXTRATimeState				L"GetXTRATimeState"
#define FUNC_SetXTRATimeState				L"SetXTRATimeState"
#define FUNC_GetWiFiState					L"GetWiFiState"
#define FUNC_SetWiFiState					L"SetWiFiState"
#define FUNC_SetNMEACallback				L"SetNMEACallback"
#define FUNC_SetNMEAPlusCallback			L"SetNMEAPlusCallback"
#define FUNC_SetPDSStateCallback			L"SetPDSStateCallback"
#define FUNC_LTEGetAGPSConfig				L"LTEGetAGPSConfig"
#define FUNC_LTESetAGPSConfig				L"LTESetAGPSConfig"
#define FUNC_GetAGPSProtocol                L"GetAGPSProtocol"
#define FUNC_SetAGPSProtocol                L"SetAGPSProtocol"

#define PARAM_SetPDSState					L"PDS State"
#define PARAM_PDSInjectTimeReference		L"System Time"
#define PARAM_PDSInjectTimeDiscont			L"System Discontinuities"
#define PARAM_Operation						L"Operation"
#define PARAM_Timeout						L"Timeout"
#define PARAM_Interval						L"Interval"
#define PARAM_Accuracy						L"Accuracy"
#define PARAM_Enabled						L"Enabled"
#define PARAM_Preference					L"Preference"
#define PARAM_ServerAddress					L"ServerAddress"
#define PARAM_ServerPort					L"ServerPort"
#define PARAM_AutoTracking					L"Auto Tracking"
#define PARAM_GPSDataMask					L"GPS Data Mask"
#define PARAM_CellDataMask					L"Cell Data Mask"
#define PARAM_PositionMethodState			L"Position Meshod state"
#define PARAM_Enable						L"Enable"
#define PARAM_NetworkMode					L"Network Mode"

CParamList CGobiApiPds::m_sSetPostionMothodState;
CParamList CGobiApiPds::m_sSetPDSState;
CParamList CGobiApiPds::m_sPDSInjectTimeReference;
CParamList CGobiApiPds::m_sSetPDSDefaults;
CParamList CGobiApiPds::m_sSetXTRAAutomaticDownload;
CParamList CGobiApiPds::m_sSetXTRANetwork;
CParamList CGobiApiPds::m_sSetAGPSConfig;
CParamList CGobiApiPds::m_sSetServiceAutomaticTracking;
CParamList CGobiApiPds::m_sResetPDSData;
CParamList CGobiApiPds::m_sSetPortAutomaticTracking;
CParamList CGobiApiPds::m_sSetNMEACallback;
CParamList CGobiApiPds::m_sSetNMEAPlusCallback;
CParamList CGobiApiPds::m_sSetPDSStateCallback;
CParamList CGobiApiPds::m_sLTEGetAGPSConfig;
CParamList CGobiApiPds::m_sLTESetAGPSConfig;
CParamList CGobiApiPds::m_sAGPSProtocol;

const TableFuncEntry CGobiApiPds::m_TableFunc[] = 
{
	{FUNC_GetPDSState, FuncGetPDSState},
	{FUNC_SetPDSState, FuncSetPDSState, &m_sSetPDSState},
//	{FUNC_StartPDSTrackingSession, FuncStartPDSTrackingSession},
//	{FUNC_StopPDSTrackingSession, FuncStopPDSTrackingSession},
	{FUNC_PDSInjectTimeReference, FuncPDSInjectTimeReference, &m_sPDSInjectTimeReference},
	{FUNC_GetPDSDefaults, FuncGetPDSDefaults},
	{FUNC_SetPDSDefaults, FuncSetPDSDefaults, &m_sSetPDSDefaults},
	{FUNC_GetXTRAAutomaticDownload, FuncGetXTRAAutomaticDownload},
	{FUNC_SetXTRAAutomaticDownload, FuncSetXTRAAutomaticDownload, &m_sSetXTRAAutomaticDownload},
	{FUNC_GetXTRANetwork, FuncGetXTRANetwork},
	{FUNC_SetXTRANetwork, FuncSetXTRANetwork, &m_sSetXTRANetwork},
	{FUNC_GetXTRAValidity, FuncGetXTRAValidity},
	{FUNC_ForceXTRADownload, FuncForceXTRADownload},
	{FUNC_GetAGPSConfig, FuncGetAGPSConfig},
	{FUNC_SetAGPSConfig, FuncSetAGPSConfig, &m_sSetAGPSConfig},
	{FUNC_GetServiceAutomaticTracking, FuncGetServiceAutomaticTracking},
	{FUNC_SetServiceAutomaticTracking, FuncSetServiceAutomaticTracking, &m_sSetServiceAutomaticTracking},
	{FUNC_GetPortAutomaticTracking, FuncGetPortAutomaticTracking},
	{FUNC_SetPortAutomaticTracking, FuncSetPortAutomaticTracking, &m_sSetPortAutomaticTracking},
	{FUNC_ResetPDSData, FuncResetPDSData, &m_sResetPDSData},
	{FUNC_GetXTRADataState, FuncGetXTRADataState},
	{FUNC_SetXTRADataState, FuncSetXTRADataState, &m_sSetPostionMothodState},
	{FUNC_GetXTRATimeState, FuncGetXTRATimeState},
	{FUNC_SetXTRATimeState, FuncSetXTRATimeState, &m_sSetPostionMothodState},
	{FUNC_GetWiFiState, FuncGetWiFiState},
	{FUNC_SetWiFiState, FuncSetWiFiState, &m_sSetPostionMothodState},
//	{FUNC_SetNMEACallback, FuncSetNMEACallback, &m_sSetNMEACallback},
	{FUNC_SetNMEAPlusCallback, FuncSetNMEAPlusCallback, &m_sSetNMEAPlusCallback},
	{FUNC_SetPDSStateCallback, FuncSetPDSStateCallback, &m_sSetPDSStateCallback},
	{FUNC_LTEGetAGPSConfig, FuncLTEGetAGPSConfig, &m_sLTEGetAGPSConfig},
	{FUNC_LTESetAGPSConfig, FuncLTESetAGPSConfig, &m_sLTESetAGPSConfig},
    {FUNC_GetAGPSProtocol, FuncGetAGPSProtocol},
    {FUNC_SetAGPSProtocol, FuncSetAGPSProtocol, &m_sAGPSProtocol},
	{FUNC_EndOfList}
};

CGobiApiPds::CGobiApiPds(HMODULE hQCDll)
{
	// Initialize the Qualcomm Dll pointer
	m_hQCDll = hQCDll;

	// Define Set PDS State configurable parameters
	m_sSetPDSState.Add(PARAM_SetPDSState, L"0");

	// Define PDS Inject Time Reference configurable parameters
	m_sPDSInjectTimeReference.Add(PARAM_PDSInjectTimeReference, L"00000000000000000");
	m_sPDSInjectTimeReference.Add(PARAM_PDSInjectTimeDiscont,  L"0");

	// Define PDS Set Defaults configurable parameters
	m_sSetPDSDefaults.Add(PARAM_Operation, L"0");
	m_sSetPDSDefaults.Add(PARAM_Timeout,   L"0");
	m_sSetPDSDefaults.Add(PARAM_Interval,  L"0");
	m_sSetPDSDefaults.Add(PARAM_Accuracy,  L"0");
	
	m_sSetXTRAAutomaticDownload.Add (PARAM_Enabled,  L"0");
	m_sSetXTRAAutomaticDownload.Add (PARAM_Interval, L"0");

	m_sSetXTRANetwork.Add (PARAM_Preference, L"0");

	m_sSetAGPSConfig.Add (PARAM_ServerAddress, L"0");
	m_sSetAGPSConfig.Add (PARAM_ServerPort, L"0");

	m_sSetServiceAutomaticTracking.Add (PARAM_AutoTracking, L"1");
	m_sSetPortAutomaticTracking.Add (PARAM_AutoTracking, L"1");

	m_sResetPDSData.Add (PARAM_GPSDataMask, L"0x00000000");
	m_sResetPDSData.Add (PARAM_CellDataMask, L"0x00000000");
    
	// Define Postion Method State Set Defaults configurable parameter
	m_sSetPostionMothodState.Add (PARAM_PositionMethodState, L"1");

	// Define configurable parameters for callback functions
	m_sSetNMEACallback.Add(PARAM_Enable, L"1");
	m_sSetNMEAPlusCallback.Add(PARAM_Enable, L"1");
	m_sSetPDSStateCallback.Add(PARAM_Enable, L"1");

	m_sLTEGetAGPSConfig.Add (PARAM_NetworkMode, L"0");

	m_sLTESetAGPSConfig.Add (PARAM_ServerAddress, L"0");
	m_sLTESetAGPSConfig.Add (PARAM_ServerPort, L"0");
	m_sLTESetAGPSConfig.Add (PARAM_NetworkMode, L"0");
    
    m_sAGPSProtocol.Add( PARAM_NetworkMode, L"0" );
}

CGobiApiPds::~CGobiApiPds(void)
{
}

BOOL CGobiApiPds::GetAvailFuncList(CFuncList* pFuncList)
{
	TBD_FUNCTION(CGobiApiPds::GetAvailFuncList);

	int iIndex = 0;

	while (m_TableFunc[iIndex].szFuncName.Compare(FUNC_EndOfList))
	{
		pFuncList->Add(L"Position Determination", m_TableFunc[iIndex].szFuncName, m_TableFunc[iIndex].pParamList);
		TBD_OUTPUT(TBDCT_INFO, TBDOL_INFORMATION, m_TableFunc[iIndex].szFuncName);
		iIndex++;
	}

	return TRUE;
}

UINT CGobiApiPds::ExecuteFunctions(CFuncList* pFuncList, UINT &nTotalExec)
{
	TBD_FUNCTION(CGobiApiPds::Execute);

	int iIndex = 0;
	m_nNumErrors = 0;
	nTotalExec = 0;

	while (m_TableFunc[iIndex].szFuncName.Compare(FUNC_EndOfList))
	{
		if (pFuncList->Find(m_TableFunc[iIndex].szFuncName))
		{
			// Get list of parameters
			CParamList sParams;
			pFuncList->GetFuncParams(m_TableFunc[iIndex].szFuncName, sParams);

			// execute function
			if (!m_TableFunc[iIndex].pFunc(&sParams))
				// increment error counter
				m_nNumErrors++;

			// increment total functions executed
			nTotalExec++;
		}

		iIndex++;
	}

	return m_nNumErrors;
}

// Unit test functions

BOOL CGobiApiPds::FuncGetPDSState(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetPDSState", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG EnabledStatus  = 0xFFFFFFFF;
	ULONG TrackingStatus = 0xFFFFFFFF;


	ULONG nRet = GetPDSState(&EnabledStatus, &TrackingStatus);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Enabled status: %s, Tracking status: %d",
			EnabledStatus ? L"Enabled" : L"Disabled",
			TrackingStatus);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETPDSSTATE) (ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETPDSSTATE pFn = (LPFN_GETPDSSTATE)GetProcAddress_W(m_hQCDll, FUNC_GetPDSState);

		// execute function
		if (pFn)
		{
			ULONG QcEnabledStatus  = 0xFFFFFFFF;
			ULONG QcTrackingStatus = 0xFFFFFFFF;

			ULONG nQcRet = pFn(&QcEnabledStatus, &QcTrackingStatus);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcEnabledStatus != EnabledStatus)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetPDSState(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetPDSState", STATUSMSG_Send);

	BOOL bRet = FALSE;
	// 0 = disable
	// all else = enable

	ULONG nEnable = 0;

	// Get user selected parameters
	if (pParams)
	{
		nEnable = _ttoi(pParams->GetValue(PARAM_SetPDSState));
	}


	ULONG nRet = SetPDSState(nEnable);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Value set: %d",nEnable);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL - Cannot do two sets to same value in a row, 
	// We do a get to check the status.
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETPDSSTATE) (ULONG *, ULONG *);

		ULONG QcEnabledStatus  = 0xFFFFFFFF;
		ULONG QcTrackingStatus = 0xFFFFFFFF;

		// get pointer to function
		LPFN_GETPDSSTATE pFn = (LPFN_GETPDSSTATE)GetProcAddress_W(m_hQCDll, FUNC_GetPDSState);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(&QcEnabledStatus, &QcTrackingStatus);
			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcEnabledStatus != nEnable)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncPDSInjectTimeReference(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncPDSInjectTimeReference", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONGLONG systemTime = 0xFFFFFFFFFFFFFFFF;
	USHORT systemDiscontinuities = 1;

	// 0 = disable
	// all else = enable

	ULONG nEnable = 0;

	// Get user selected parameters
	if (pParams)
	{
		systemTime = _ttoi(pParams->GetValue(PARAM_PDSInjectTimeReference));
		systemDiscontinuities = (USHORT)_ttoi(pParams->GetValue(PARAM_PDSInjectTimeDiscont));
	}

	ULONG nRet = PDSInjectTimeReference(systemTime, systemDiscontinuities);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Value set: %d",nEnable);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_PDSINJECTTIMEREFERENCE) (ULONGLONG, USHORT);

		// get pointer to function
		LPFN_PDSINJECTTIMEREFERENCE pFn = (LPFN_PDSINJECTTIMEREFERENCE)GetProcAddress_W(m_hQCDll, FUNC_PDSInjectTimeReference);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(systemTime, systemDiscontinuities);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
//			else if (QcEnabledStatus != EnabledStatus)
//			{
//				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
//				bRet = FALSE;
//			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetPDSDefaults(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetPDSDefaults", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG Operation;
	BYTE  Timeout;
	ULONG Interval;
	ULONG Accuracy;

	ULONG nRet = GetPDSDefaults(&Operation, &Timeout, &Interval, &Accuracy);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Operation: %d, Timeout: %d, Interval: %d, Accuracy: %d",
			Operation,
			Timeout,
			Interval,
			Accuracy);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETPDSDEFAULTS) (ULONG*, BYTE*, ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETPDSDEFAULTS pFn = (LPFN_GETPDSDEFAULTS)GetProcAddress_W(m_hQCDll, FUNC_GetPDSDefaults);

		// execute function
		if (pFn)
		{
			ULONG QcOperation;
			BYTE  QcTimeout;
			ULONG QcInterval = 0;
			ULONG QcAccuracy;

			ULONG nQcRet = pFn(&QcOperation, &QcTimeout, &QcInterval, &QcAccuracy);

			if (!nRet)
			{
				strTemp.Format(L"QcOperation: %d, QcTimeout: %d, QcInterval: %d, QcAccuracy: %d",
					QcOperation,
					QcTimeout,
					QcInterval,
					QcAccuracy);
				ADDSTATUS(strTemp, STATUSMSG_Receive);
			}

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcOperation != Operation || 
					 QcTimeout   != Timeout   || 
					 QcInterval  != Interval  || 
					 QcAccuracy  != Accuracy)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetPDSDefaults(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetPDSDefaults", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG Operation = 0;
	BYTE  Timeout = 0;
	ULONG Interval = 0;
	ULONG Accuracy = 0;

	// Get user selected parameters
	if (pParams)
	{
		Operation = _ttoi(pParams->GetValue(PARAM_Operation));
		Timeout   = (BYTE)_ttoi(pParams->GetValue(PARAM_Timeout));
		Interval  = _ttoi(pParams->GetValue(PARAM_Interval));
		Accuracy  = _ttoi(pParams->GetValue(PARAM_Accuracy));
	}

	ULONG nRet = SetPDSDefaults(Operation, Timeout, Interval, Accuracy);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETPDSDEFAULTS) (ULONG, ULONG, ULONG, ULONG);

		// get pointer to function
		LPFN_SETPDSDEFAULTS pFn = (LPFN_SETPDSDEFAULTS)GetProcAddress_W(m_hQCDll, FUNC_SetPDSDefaults);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(Operation, Timeout, Interval, Accuracy);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetXTRAAutomaticDownload(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetXTRAAutomaticDownload", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  bEnabled;
	USHORT Interval;

	ULONG nRet = GetXTRAAutomaticDownload(&bEnabled, &Interval);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Enabled status: %s, Interval: %d",
			bEnabled ? L"true" : L"false",
			Interval);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}
	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETXTRAAUTOMATICDOWNLOAD) (ULONG*, USHORT*);

		// get pointer to function
		LPFN_GETXTRAAUTOMATICDOWNLOAD pFn = (LPFN_GETXTRAAUTOMATICDOWNLOAD)GetProcAddress_W(m_hQCDll, FUNC_GetXTRAAutomaticDownload);

		// execute function
		if (pFn)
		{
			ULONG  QcbEnabled;
			USHORT QcInterval;

			ULONG nQcRet = pFn(&QcbEnabled, &QcInterval);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcbEnabled != bEnabled || 
					 QcInterval != Interval )
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetXTRAAutomaticDownload(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetXTRAAutomaticDownload", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  bEnabled = FALSE;
	USHORT Interval = 0;

	// Get user selected parameters
	if (pParams)
	{
		bEnabled  = _ttoi(pParams->GetValue(PARAM_Enabled));
		Interval  = (USHORT)_ttoi(pParams->GetValue(PARAM_Interval));
	}

	ULONG nRet = SetXTRAAutomaticDownload(bEnabled, Interval);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETXTRAAUTOMATICDOWNLOAD) (ULONG, USHORT);

		// get pointer to function
		LPFN_SETXTRAAUTOMATICDOWNLOAD pFn = (LPFN_SETXTRAAUTOMATICDOWNLOAD)GetProcAddress_W(m_hQCDll, FUNC_SetXTRAAutomaticDownload);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(bEnabled, Interval);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetXTRANetwork(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetXTRANetwork", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  Preference;

	ULONG nRet = GetXTRANetwork(&Preference);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Preference: %d",
			Preference);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETXTRANETWORK) (ULONG*);

		// get pointer to function
		LPFN_GETXTRANETWORK pFn = (LPFN_GETXTRANETWORK)GetProcAddress_W(m_hQCDll, FUNC_GetXTRANetwork);

		// execute function
		if (pFn)
		{
			ULONG  QcPreference;

			ULONG nQcRet = pFn(&QcPreference);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcPreference != Preference)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetXTRANetwork(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetXTRANetwork", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  Preference = 0;

	// Get user selected parameters
	if (pParams)
	{
		Preference  = _ttoi(pParams->GetValue(PARAM_Preference));
	}

	ULONG nRet = SetXTRANetwork(Preference);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETXTRANETWORK) (ULONG);

		// get pointer to function
		LPFN_SETXTRANETWORK pFn = (LPFN_SETXTRANETWORK)GetProcAddress_W(m_hQCDll, FUNC_SetXTRANetwork);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(Preference);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetXTRAValidity(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetXTRAValidity", STATUSMSG_Send);

	BOOL bRet = FALSE;

	USHORT GPSWeek;
	USHORT GPSWeekOffset;
	USHORT Duration;

	ULONG nRet = GetXTRAValidity(&GPSWeek, &GPSWeekOffset, &Duration);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"GPSWeek: %i, GPSWeekOffset: %i, Duration: %i",
			GPSWeek, GPSWeekOffset, Duration);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETXTRAVALIDITY) (USHORT*, USHORT*, USHORT*);

		// get pointer to function
		LPFN_GETXTRAVALIDITY pFn = (LPFN_GETXTRAVALIDITY)GetProcAddress_W(m_hQCDll, FUNC_GetXTRAValidity);

		// execute function
		if (pFn)
		{
			USHORT QcGPSWeek;
			USHORT QcGPSWeekOffset;
			USHORT QcDuration;

			ULONG nQcRet = pFn(&QcGPSWeek, &QcGPSWeekOffset, &QcDuration);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcGPSWeek != GPSWeek || QcGPSWeekOffset != GPSWeekOffset || QcDuration != Duration)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncForceXTRADownload(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncForceXTRADownload", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG nRet = ForceXTRADownload();

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_FORCEXTRADOWNLOAD) ();

		// get pointer to function
		LPFN_FORCEXTRADOWNLOAD pFn = (LPFN_FORCEXTRADOWNLOAD)GetProcAddress_W(m_hQCDll, FUNC_ForceXTRADownload);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn();

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetAGPSConfig(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetAGPSConfig", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG ServerAddress;
	ULONG ServerPort;

	ULONG nRet = GetAGPSConfig(&ServerAddress, &ServerPort);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
        // display IP address
        strTemp.Format(L"ServerAddress: %d.%d.%d.%d", (ServerAddress & 0xFF000000)>> 24, (ServerAddress & 0x00FF0000) >> 16, (ServerAddress & 0x0000FF00) >> 8, ServerAddress & 0x000000FF);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
        strTemp.Format(L"ServerPort: %d", ServerPort);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETAGPSCONFIG) (ULONG*, ULONG*);

		// get pointer to function
		LPFN_GETAGPSCONFIG pFn = (LPFN_GETAGPSCONFIG)GetProcAddress_W(m_hQCDll, FUNC_GetAGPSConfig);

		// execute function
		if (pFn)
		{
			ULONG QcServerAddress;
			ULONG QcServerPort;

			ULONG nQcRet = pFn(&QcServerAddress, &QcServerPort);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if ((QcServerAddress != ServerAddress) || 
					 (QcServerPort    != ServerPort) )
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetAGPSConfig(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetAGPSConfig", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG ServerAddress = 0;
	ULONG ServerPort = 0;

    // Get user selected parameters
	if (pParams)
	{
		const UINT nMaxStrLen = 0xFF;
		CHAR szIpAddress[nMaxStrLen] = "";
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_ServerAddress), -1, szIpAddress, nMaxStrLen, 0, 0);
		ServerAddress = ntohl(inet_addr(szIpAddress));
		ServerPort    = _ttoi(pParams->GetValue(PARAM_ServerPort));
	}

	ULONG nRet = SetAGPSConfig(ServerAddress, ServerPort);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
        // display IP address
        strTemp.Format(L"ServerAddress: %d.%d.%d.%d", (ServerAddress & 0xFF000000)>> 24, (ServerAddress & 0x00FF0000) >> 16, (ServerAddress & 0x0000FF00) >> 8, ServerAddress & 0x000000FF);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
        strTemp.Format(L"ServerPort: %d", ServerPort);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETAGPSCONFIG) (ULONG, ULONG);

		// get pointer to function
		LPFN_SETAGPSCONFIG pFn = (LPFN_SETAGPSCONFIG)GetProcAddress_W(m_hQCDll, FUNC_SetAGPSConfig);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(ServerAddress, ServerPort);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetServiceAutomaticTracking(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetServiceAutomaticTracking", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  bAuto = 0xFF;

	ULONG nRet = GetServiceAutomaticTracking(&bAuto);

	CString strTemp;
	strTemp.Format(L"Return: %d, Tracking State: %s", nRet, bAuto ? L"Started" : L"Not Started");
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETSERVICEAUTOMATICTRACKING) (ULONG*);

		// get pointer to function
		LPFN_GETSERVICEAUTOMATICTRACKING pFn = (LPFN_GETSERVICEAUTOMATICTRACKING)GetProcAddress_W(m_hQCDll, FUNC_GetServiceAutomaticTracking);

		// execute function
		if (pFn)
		{
			ULONG  QcbAuto = 0xFF;;

			ULONG nQcRet = pFn(&QcbAuto);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcbAuto != bAuto)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetServiceAutomaticTracking(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetServiceAutomaticTracking", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  bAuto = 0;

	// Get user selected parameters
	if (pParams)
	{
		bAuto  = _ttoi(pParams->GetValue(PARAM_AutoTracking));
	}

	ULONG nRet = SetServiceAutomaticTracking(bAuto);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETSERVICEAUTOMATICTRACKING) (ULONG);

		// get pointer to function
		LPFN_SETSERVICEAUTOMATICTRACKING pFn = (LPFN_SETSERVICEAUTOMATICTRACKING)GetProcAddress_W(m_hQCDll, FUNC_SetServiceAutomaticTracking);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(bAuto);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetPortAutomaticTracking(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetPortAutomaticTracking", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  bAuto = 0xFF;

	ULONG nRet = GetPortAutomaticTracking(&bAuto);

	CString strTemp;
	strTemp.Format(L"Return: %d, Tracking State: %s", nRet, bAuto ? L"Enabled" : L"Disabled");
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETSERVICEAUTOMATICTRACKING) (ULONG*);

		// get pointer to function
		LPFN_GETSERVICEAUTOMATICTRACKING pFn = (LPFN_GETSERVICEAUTOMATICTRACKING)GetProcAddress_W(m_hQCDll, FUNC_GetPortAutomaticTracking);

		// execute function
		if (pFn)
		{
			ULONG  QcbAuto = 0xFF;;

			ULONG nQcRet = pFn(&QcbAuto);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcbAuto != bAuto)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetPortAutomaticTracking(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetPortAutomaticTracking", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  bAuto = 0;

	// Get user selected parameters
	if (pParams)
	{
		bAuto  = _ttoi(pParams->GetValue(PARAM_AutoTracking));
	}

	ULONG nRet = SetPortAutomaticTracking(bAuto);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETSERVICEAUTOMATICTRACKING) (ULONG);

		// get pointer to function
		LPFN_SETSERVICEAUTOMATICTRACKING pFn = (LPFN_SETSERVICEAUTOMATICTRACKING)GetProcAddress_W(m_hQCDll, FUNC_SetPortAutomaticTracking);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(bAuto);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncResetPDSData(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncResetPDSData", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  nGPSDataMask  = 0x00000000;
	ULONG  nCellDataMask = 0x00000000;

	// Get user selected parameters
	if (pParams)
	{
		nGPSDataMask   = _tcstol(pParams->GetValue(PARAM_GPSDataMask), NULL, 16);
		nCellDataMask  = _tcstol(pParams->GetValue(PARAM_CellDataMask), NULL, 16);
	}

	CString strTemp;
	strTemp.Format(L"GPSMask: 0x%08x, CellMask: 0x%08x", nGPSDataMask, nCellDataMask);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	ULONG nRet = ResetPDSData(&nGPSDataMask, &nCellDataMask);

	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_RESETPDSDATA) (ULONG*, ULONG*);

		// get pointer to function
		LPFN_RESETPDSDATA pFn = (LPFN_RESETPDSDATA)GetProcAddress_W(m_hQCDll, FUNC_ResetPDSData);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(&nGPSDataMask, &nCellDataMask);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

// PDS Callback functions

static void SWICALLBACK NewNMEACallback( const CHAR * pNMEA )
{
	CString strTemp;
	strTemp.Format(L"NMEA String: %s", CA2T(pNMEA));
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

#if 0	// deprecated
BOOL CGobiApiPds::FuncSetNMEACallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetNMEACallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetNMEACallback(NewNMEACallback);
	}
	else
	{
		ret = SetNMEACallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}
#endif

static void SWICALLBACK NewNMEAPlusCallback( const CHAR * pNMEA,  ULONG mode)
{
	CString strTemp;
	strTemp.Format(L"Mode: %u NMEA String: %s", mode, CA2T(pNMEA));
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

BOOL CGobiApiPds::FuncSetNMEAPlusCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetNMEAPlusCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetNMEAPlusCallback(NewNMEAPlusCallback);
	}
	else
	{
		ret = SetNMEAPlusCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}

static void SWICALLBACK PDSStateCallback( ULONG enableStatus, ULONG trackingStatus )
{
	CString strTemp;
	strTemp.Format(L"PDS State: %d ; Tracking Status: %d", enableStatus, trackingStatus);
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

BOOL CGobiApiPds::FuncSetPDSStateCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetPDSStateCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetPDSStateCallback(PDSStateCallback);;
	}
	else
	{
		ret = SetPDSStateCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}


BOOL CGobiApiPds::FuncGetXTRADataState(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetXTRADataState", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  nState  = 0;

	ULONG nRet = GetXTRADataState(&nState);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"State of XTRA Data Positioning: %d", nState);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETXTRADATASTATE) (ULONG*);

		// get pointer to function
		LPFN_GETXTRADATASTATE pFn = (LPFN_GETXTRADATASTATE)GetProcAddress_W(m_hQCDll, FUNC_GetXTRADataState);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(&nState);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetXTRADataState(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetXTRADataState", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG  nState  = 0;

	// Get user selected parameters
	if (pParams)
	{
		nState   = _tcstol(pParams->GetValue(PARAM_PositionMethodState), NULL, 16);
	}

	CString strTemp;
	strTemp.Format(L"XTRA Data Positioning State: %d", nState);
	ADDSTATUS(strTemp, STATUSMSG_Send);


	ULONG nRet = SetXTRADataState(nState);

	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETXTRADATASTATE) (ULONG);

		// get pointer to function
		LPFN_SETXTRADATASTATE pFn = (LPFN_SETXTRADATASTATE)GetProcAddress_W(m_hQCDll, FUNC_SetXTRADataState);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(nState);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetXTRATimeState(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetXTRATimeState", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  nState  = 0;

	ULONG nRet = GetXTRATimeState(&nState);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"State of XTRA Time Positioning: %d", nState);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETXTRATIMESTATE) (ULONG*);

		// get pointer to function
		LPFN_GETXTRATIMESTATE pFn = (LPFN_GETXTRATIMESTATE)GetProcAddress_W(m_hQCDll, FUNC_GetXTRATimeState);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(&nState);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetXTRATimeState(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetXTRATimeState", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG  nState  = 0;

	// Get user selected parameters
	if (pParams)
	{
		nState   = _tcstol(pParams->GetValue(PARAM_PositionMethodState), NULL, 16);
	}

	CString strTemp;
	strTemp.Format(L"XTRA Time Positioning State: %d", nState);
	ADDSTATUS(strTemp, STATUSMSG_Send);


	ULONG nRet = SetXTRATimeState(nState);

	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETXTRATIMESTATE) (ULONG);

		// get pointer to function
		LPFN_SETXTRATIMESTATE pFn = (LPFN_SETXTRATIMESTATE)GetProcAddress_W(m_hQCDll, FUNC_SetXTRATimeState);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(nState);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncGetWiFiState(CParamList* pParams /*= NULL*/)
{
    UNREFERENCED_PARAMETER(pParams);
	ADDSTATUS(L"FuncGetWiFiState", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  nState  = 0;

	ULONG nRet = GetWiFiState(&nState);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"State of WiFi Positioning: %d", nState);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_GETWIFISTATE) (ULONG*);

		// get pointer to function
		LPFN_GETWIFISTATE pFn = (LPFN_GETWIFISTATE)GetProcAddress_W(m_hQCDll, FUNC_GetWiFiState);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(&nState);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetWiFiState(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetWiFiState", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG  nState  = 0;

	// Get user selected parameters
	if (pParams)
	{
		nState   = _tcstol(pParams->GetValue(PARAM_PositionMethodState), NULL, 16);
	}

	CString strTemp;
	strTemp.Format(L"WiFi Positioning State: %d", nState);
	ADDSTATUS(strTemp, STATUSMSG_Send);


	ULONG nRet = SetWiFiState(nState);

	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (SWICMAPI*LPFN_SETWIFISTATE) (ULONG);

		// get pointer to function
		LPFN_SETWIFISTATE pFn = (LPFN_SETWIFISTATE)GetProcAddress_W(m_hQCDll, FUNC_SetWiFiState);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(nState);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiPds::FuncLTEGetAGPSConfig(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncLTEGetAGPSConfig", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG ServerAddress;
	ULONG ServerPort;
	ULONG NetworkMode = 0;

	if (pParams)
	{
		NetworkMode   = _ttoi(pParams->GetValue(PARAM_NetworkMode));
	}

	ULONG nRet = LTEGetAGPSConfig(&ServerAddress, &ServerPort, NetworkMode);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
        // display IP address
        strTemp.Format(L"ServerAddress: %d.%d.%d.%d", (ServerAddress & 0xFF000000)>> 24, (ServerAddress & 0x00FF0000) >> 16, (ServerAddress & 0x0000FF00) >> 8, ServerAddress & 0x000000FF);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
        strTemp.Format(L"ServerPort: %d", ServerPort);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	return bRet;
}

BOOL CGobiApiPds::FuncLTESetAGPSConfig(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetLTEAGPSConfig", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG ServerAddress = 0;
	ULONG ServerPort = 0;
	ULONG NetworkMode = 0;

    // Get user selected parameters
	if (pParams)
	{
		const UINT nMaxStrLen = 0xFF;
		CHAR szIpAddress[nMaxStrLen] = "";
		WideCharToMultiByte(CP_ACP, 0, pParams->GetValue(PARAM_ServerAddress), -1, szIpAddress, nMaxStrLen, 0, 0);
		ServerAddress = ntohl(inet_addr(szIpAddress));
		ServerPort    = _ttoi(pParams->GetValue(PARAM_ServerPort));
		NetworkMode   = _ttoi(pParams->GetValue(PARAM_NetworkMode));
	}

	ULONG nRet = LTESetAGPSConfig(ServerAddress, ServerPort, NetworkMode);

	CString strTemp;
	strTemp.Format(L"Return: %d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
        // display IP address
        strTemp.Format(L"ServerAddress: %d.%d.%d.%d", (ServerAddress & 0xFF000000)>> 24, (ServerAddress & 0x00FF0000) >> 16, (ServerAddress & 0x0000FF00) >> 8, ServerAddress & 0x000000FF);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
        strTemp.Format(L"ServerPort: %d", ServerPort);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
        strTemp.Format(L"NetworkMode: %d", NetworkMode);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = TRUE;
	}

	return bRet;
}

BOOL CGobiApiPds::FuncSetAGPSProtocol( CParamList * pParams /* = NULL */ )
{
    ADDSTATUS( L"FuncSetAGPSProtocol", STATUSMSG_Send );

    BOOL bRet = FALSE;
    ULONG NetworkMode = 0;

    if (pParams)
    {
        NetworkMode = _ttoi(pParams->GetValue(PARAM_NetworkMode));
    }

    ULONG nRet = SetAGPSProtocol( NetworkMode );

    CString strTemp;
    strTemp.Format( L"Result: %d", nRet );
    ADDSTATUS( strTemp, STATUSMSG_Receive );

    if (!nRet)
    {
        bRet = TRUE;
    }

    return bRet;
}

BOOL CGobiApiPds::FuncGetAGPSProtocol( CParamList * pParams /* = NULL */ )
{
    UNREFERENCED_PARAMETER(pParams);
    ADDSTATUS( L"FuncGetAGPSProtocol", STATUSMSG_Send );

    BOOL bRet = FALSE;
    ULONG NetworkMode = 0;

    ULONG nRet = GetAGPSProtocol( &NetworkMode );

    CString strTemp;
    strTemp.Format( L"Result: %d", nRet );
    ADDSTATUS( strTemp, STATUSMSG_Receive );

    if (!nRet)
    {
        strTemp.Format( L"Network Mode: %d", NetworkMode );
        ADDSTATUS( strTemp, STATUSMSG_Receive );

        bRet = TRUE;
    }

    return bRet;
}