#include "stdafx.h"
#include "RFEmbProtocol.h"
#include "Utility.h"

typedef struct _RF_CMD 
{
	BYTE*	pCmd;
	BYTE	bCmdData;
	BYTE	bRcvData;
}RF_CMD, *PRF_CMD;

RF_CMD tbCmd[] =
{
	{(BYTE*)"\x01\x01\x01", 0x03, 0x0F}, // get serial 
	{(BYTE*)"\x01\x01\x02", 0x03, 0x0F}, // get reader type
	{(BYTE*)"\x01\x01\x03", 0x03, 0x0F},	// get hard rev
	{(BYTE*)"\x01\x01\x04", 0x03, 0x0F},	// get software rev
	{(BYTE*)"\x01\x01\x05", 0x03, 0x0F},	// get bootloader rev
	{(BYTE*)"\x01\x01\x07", 0x03, 0x0F},	// get current state
	{(BYTE*)"\x01\x02\x01", 0x03, 0x10}, // get attenuation
	{(BYTE*)"\x01\x02\x02", 0x03, 0x10}, // get freq
	{(BYTE*)"\x01\x02\x03", 0x03, 0x12}, // get sensivity
	{(BYTE*)"\x01\x03\x01", 0x03, 0x00}, // reboot
	{(BYTE*)"\x01\x03\x03", 0x03, 0x0C}, // antena on/off
	{(BYTE*)"\x01\x03\x04", 0x03, 0x0C}, // set attenuation
	{(BYTE*)"\x01\x03\x05", 0x03, 0x0C}, // set freq
	{(BYTE*)"\x01\x03\x06", 0x03, 0x0E}, // set sensivity
	{(BYTE*)"\x01\x03\x20", 0x03, 0x0B}, // reset to default settings
	{(BYTE*)"\x01\x03\x21", 0x03, 0x0B}, // save settings
	{(BYTE*)"\x01\x50\x01", 0x03, 0x0B}, // inventory single
	{(BYTE*)"\x01\x50\x02", 0x03, 0x0B}, // inventory cycling
	{(BYTE*)"\x01\x50\x03", 0x03, 0x0B}, // read from tag
	{(BYTE*)"\x01\x50\x04", 0x03, 0x0B}, // write to tag
	{(BYTE*)"\x01\x50\x05", 0x03, 0x0B}, // lock tag
	{(BYTE*)"\x01\x50\x06", 0x03, 0x0B}, // kill tag
	{(BYTE*)"\x01\x90\x02", 0x03, 0x0B}, // inventory cycling int
	{(BYTE*)"\x01\x90\x03", 0x03, 0x0B}, // state change int
	{(BYTE*)"\x01\x90\x05", 0x03, 0x0B}, // boot ready - valid only for embeded device
};

#define TAG_LEN		0x02
#define TAG_DATA	0x03
#define TAG_BCC		0x04

#define START_CMD		(BYTE*)"\x52\x46\x45" // RFE
#define START_CMD_LEN	0x03

#define CMD_LEN		0x03
#define DATA_LEN	0x02
#define BCC_LEN		0x02

CRFEmbProtocol::CRFEmbProtocol() 
{
	m_bUseTab		= FALSE;
	m_bUseReturn	= FALSE;
	ZeroMemory(&m_stReadWriteInfo, sizeof(READ_WRITE_INFO));
}

CRFEmbProtocol::~CRFEmbProtocol()
{

}

EERROR CRFEmbProtocol::Open()
{
	return m_clsTransport.Open();
}

void CRFEmbProtocol::SetCom(UINT nCom)
{
	m_clsTransport.SetOption(nCom, 115200);
}

 void CRFEmbProtocol::SetTabAndReturn(BOOL bUseTab, BOOL bUseReturn)
 {
	m_bUseTab		= bUseTab;
	m_bUseReturn	= bUseReturn;
 }

 BOOL CRFEmbProtocol::IsReturnUsed()
 {
	 return m_bUseReturn;
 }

 BOOL CRFEmbProtocol::IsTabUsed()
 {
	 return m_bUseTab;
 }

 void CRFEmbProtocol::SetReadWriteInfo(READ_WRITE_INFO* pReadWriteInfo)
 {
	 if(pReadWriteInfo != NULL)
	 {
		m_stReadWriteInfo = *pReadWriteInfo;
	 }
 }

EERROR CRFEmbProtocol::SendCmd(ERF_CMD eCmd, BYTE* pData, DWORD dwData)
{
	// total Len = 3 bytes RFE + cmd +  2 bytes len + data + 2 bytes check sum
	DWORD dwCmdLen = 0x03 + tbCmd[eCmd].bCmdData + DATA_LEN + (dwData > 0 ? (1 + dwData) : 0)  + BCC_LEN;

	BYTE* pDataSend = new BYTE[dwCmdLen];
	ZeroMemory(pDataSend, dwCmdLen);

	// START + CMD tag
	BYTE* pDataNav = pDataSend;
	memcpy_s(pDataNav, dwCmdLen, START_CMD, START_CMD_LEN);					pDataNav = pDataNav + START_CMD_LEN;
	memcpy_s(pDataNav, dwCmdLen, tbCmd[eCmd].pCmd, tbCmd[eCmd].bCmdData);	pDataNav = pDataNav + tbCmd[eCmd].bCmdData;

	// len tag
	*pDataNav = TAG_LEN;		pDataNav++;
	*pDataNav = (BYTE)dwData;	pDataNav++;

	// data tag
	if(dwData > 0x00)
	{
		*pDataNav = TAG_DATA;		pDataNav++;
		memcpy_s(pDataNav, dwCmdLen, pData, dwData); pDataNav += dwData;
	}

	// bcc data
	*pDataNav = TAG_BCC;		pDataNav++;
	*pDataNav = CUtility::CalcBCC(pDataSend, dwCmdLen - 1);

	EERROR eRet = m_clsTransport.Write(pDataSend, dwCmdLen);
	delete[] pDataSend;

	return eRet;

}

DWORD CRFEmbProtocol::IdentifyCmd(BYTE* pData)
{
	for(UINT nCount = 0; nCount < sizeof(tbCmd) / sizeof(RF_CMD); nCount++)
	{
		if(memcmp(pData, tbCmd[nCount].pCmd, CMD_LEN) == 0)
		{
			return nCount;
		}
	}
	return RF_UNKNOWN;
}

#define READ_UNTIL_DATA	0x09	// it's possible that in embbeded word first char if wrong
EERROR CRFEmbProtocol::GetData(DWORD& dwCmd, BYTE** pData, DWORD& dwData)
{
	EERROR eRet = ER_INVALID_DATA;
	if(pData != NULL)
	{
		BYTE pDataRcv[MAX_PATH];
		ZeroMemory(pDataRcv, MAX_PATH);
		ULONG uRead = READ_UNTIL_DATA;
		if((eRet = m_clsTransport.Read(pDataRcv, uRead)) == ER_OK)
		{
			eRet = ER_TAG_START;

			// check if we have RFE
			UINT nNextChar = 0x00;
			if(memcmp(pDataRcv, START_CMD, START_CMD_LEN) == 0x00)
			{
				eRet = ER_OK;
			}
#ifdef WINCE			
			// first char can be wrong in case of embeded world so check next char
			if((eRet != ER_OK) && (memcmp(pDataRcv + 0x01, START_CMD, START_CMD_LEN) == 0x00))
			{
				eRet = ER_OK;
				nNextChar++;
			}
#endif
			if(eRet == ER_OK)
			{
				uRead = pDataRcv[(READ_UNTIL_DATA + nNextChar) - 0x02] + 0x02 + nNextChar;
				if((eRet = m_clsTransport.Read(pDataRcv + READ_UNTIL_DATA, uRead)) == ER_OK)
				{
					// check if we have RFE
					BYTE* pDataNav = pDataRcv + nNextChar;

					pDataNav += START_CMD_LEN;

					dwCmd = IdentifyCmd(pDataNav);

					// check if we have tag len
					pDataNav += CMD_LEN;
					eRet = ER_TAG_LEN;
					if(*pDataNav == TAG_LEN)
					{
						// we know how much data do we have
						// then allocated againg/ copy data/perfom cheking
						dwData = *(pDataNav + 1);
						pDataNav += DATA_LEN;

						// if we have data 
						if(dwData > 0x00)
						{
							// check tag data + copy data 
							eRet = ER_TAG_DATA;
							if(*pDataNav == TAG_DATA)
							{
								pDataNav++;
								*pData = new BYTE[dwData];
								memcpy_s(*pData, dwData, pDataNav, dwData);
								pDataNav += dwData;
							}
						}

						// check bcc
						eRet = ER_BCC;
						if(*pDataNav == TAG_BCC)
						{
							pDataNav++;
							if(*pDataNav == CUtility::CalcBCC(pDataRcv + nNextChar, READ_UNTIL_DATA + dwData + BCC_LEN - 0x01))
							{
								eRet = ER_OK;
							}
						}	
					}
				}
			}
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetData(ERF_CMD eCmd, BYTE** pData, DWORD& dwData)
{
	DWORD dwCmd = RF_UNKNOWN, dwCount = 0x00;
	EERROR eRet = ER_READ;
	while((eRet == ER_READ) && (dwCount < 0x80))
	{
		eRet = GetData(dwCmd, pData, dwData);
		Sleep(10);
		dwCount++;
	}

	if(eRet == ER_OK)
	{
		eRet = ER_TAG_CMD;
		if(eCmd == dwCmd)
		{
			eRet = ER_OK;
		}
	}
	return eRet;
}

// this function are used for compatibility with keyboard emulation
EERROR CRFEmbProtocol::GetFirmware(char* szData, DWORD dwSize)
{
	EERROR eRet = SendCmd(RF_GET_SERIAL, NULL, 0);
	if(eRet == ER_OK)
	{
		BYTE* pData = NULL; DWORD dwData = 0;
		if((eRet = GetData(RF_GET_SERIAL, &pData, dwData)) == ER_OK)
		{
			std::string strRet = CUtility::DataToString(pData, dwData);
			eRet = strRet.size() > dwSize - 1 ? ER_MORE_DATA : ER_OK;
			ZeroMemory(szData, MAX_PATH);
			memcpy_s(szData, dwSize - 1, strRet.c_str(), strRet.size() > dwSize - 1 ? dwSize - 1 : strRet.size());
			delete[] pData;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetFirmwareRaw(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_GET_SERIAL, NULL, 0);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0;
		if((eRet = GetData(RF_GET_SERIAL, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = CUtility::SetDataByte(pDataRet, dwDataRet, pData, dwSize);
			delete[] pDataRet;
		}
	}
	return eRet;
}

// this function are used for compatibility with keyboard emulation
EERROR CRFEmbProtocol::GetReaderType(char* szData, DWORD dwSize)
{
	EERROR eRet = SendCmd(RF_READER_TYPE, NULL, 0);
	if(eRet == ER_OK)
	{
		BYTE* pData = NULL; DWORD dwData = 0;
		if((eRet = GetData(RF_READER_TYPE, &pData, dwData)) == ER_OK)
		{
			std::string strRet = CUtility::DataToString(pData, dwData);
			eRet = strRet.size() > dwSize - 1 ? ER_MORE_DATA : ER_OK;
			ZeroMemory(szData, MAX_PATH);
			memcpy_s(szData, dwSize - 1, strRet.c_str(), strRet.size() > dwSize - 1 ? dwSize - 1 : strRet.size());
			delete[] pData;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetReaderTypeRaw(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_READER_TYPE, NULL, 0);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0;
		if((eRet = GetData(RF_READER_TYPE, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = CUtility::SetDataByte(pDataRet, dwDataRet, pData, dwSize);
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetHardwareRev(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_HARDWARE_REV, NULL, 0);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0;
		if((eRet = GetData(RF_HARDWARE_REV, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = CUtility::SetDataByte(pDataRet, dwDataRet, pData, dwSize);
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetSoftwareRev(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_SOFTWARE_REV, NULL, 0); 
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0;
		if((eRet = GetData(RF_SOFTWARE_REV, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = CUtility::SetDataByte(pDataRet, dwDataRet, pData, dwSize);
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetBootLoaderRev(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_BOOTLOADER_REV, NULL, 0);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0;
		if((eRet = GetData(RF_BOOTLOADER_REV, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = CUtility::SetDataByte(pDataRet, dwDataRet, pData, dwSize);
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetCurrentState(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_CURRENT_STATE, NULL, 0);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0;
		if((eRet = GetData(RF_CURRENT_STATE, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = CUtility::SetDataByte(pDataRet, dwDataRet, pData, dwSize);
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetAttenuation(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_GET_ATTENUATION, NULL, 0x00);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
		if((eRet = GetData(RF_GET_ATTENUATION, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pDataRet == 0x00)
			{
				eRet = CUtility::SetDataByte(pDataRet + 0x01, dwDataRet - 0x01, pData, dwSize);
			}
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetSensivity(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_GET_SENSIVITY, NULL, 0x00);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
		if((eRet = GetData(RF_GET_SENSIVITY, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pDataRet == 0x00)
			{
				eRet = CUtility::SetDataByte(pDataRet + 0x01, dwDataRet - 0x01, pData, dwSize);
			}
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetFreq(BYTE* pData, DWORD& dwSize)
{
	EERROR eRet = SendCmd(RF_GET_FREQ, NULL, 0x00);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
		if((eRet = GetData(RF_GET_FREQ, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pDataRet == 0x00)
			{
				eRet = CUtility::SetDataByte(pDataRet + 0x02, dwDataRet - 0x02, pData, dwSize);
			}
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::Reboot()
{
	return SendCmd(RF_REBOOT, NULL, 0x00);
}

EERROR CRFEmbProtocol::ResetSettings()
{
	EERROR eRet = SendCmd(RF_RESET_SETTINGS, NULL, 0x00);
	if(eRet == ER_OK)
	{
		BYTE* pData = NULL; DWORD dwData = 0x00;
		if((eRet = GetData(RF_RESET_SETTINGS, &pData, dwData)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pData == 0x00)
			{
				eRet = ER_OK;
			}
			delete[] pData;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::SaveSettings()
{
	EERROR eRet = SendCmd(RF_SAVE_SETTINGS, NULL, 0x00);
	if(eRet == ER_OK)
	{
		BYTE* pData = NULL; DWORD dwData = 0x00;
		if((eRet = GetData(RF_SAVE_SETTINGS, &pData, dwData)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pData == 0x00)
			{
				eRet = ER_OK;
			}
			delete[] pData;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::SetAttenuation(DWORD dwCurrent)
{
	BYTE pSendData[0x02];
	pSendData[0x00] = 0x00;
	pSendData[0x01] = (BYTE)(dwCurrent & 0xFF);

	EERROR eRet = SendCmd(RF_SET_ATTENUATION, pSendData, 0x02);
	if(eRet == ER_OK)
	{
		BYTE* pData = NULL; DWORD dwData = 0x00;
		if((eRet = GetData(RF_SET_ATTENUATION, &pData, dwData)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pData == 0x00)
			{
				eRet = ER_OK;
			}
			delete[] pData;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::SetSensivity(short shCurrent)
{
	BYTE pSendData[0x02];
	pSendData[0x00] = (BYTE)(shCurrent >> 0x08) & 0xFF;
	pSendData[0x01] = (BYTE)(shCurrent & 0xFF);

	EERROR eRet = SendCmd(RF_SET_SENSIVITY, pSendData, 0x02);
	if(eRet == ER_OK)
	{
		BYTE* pData = NULL; DWORD dwData = 0x00;
		if((eRet = GetData(RF_SET_SENSIVITY, &pData, dwData)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pData == 0x00)
			{
				eRet = ER_OK;
			}
			delete[] pData;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::SetFreq(BYTE* pData, UINT nDataSize)
{
	EERROR eRet = SendCmd(RF_SET_FREQ, pData, nDataSize);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
		if((eRet = GetData(RF_SET_FREQ, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pDataRet == 0x00)
			{
				eRet = ER_OK;
			}
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::GetCard(BYTE* pData, DWORD& dwData)
{
	EERROR eRet = SendCmd(RF_INVENTORY_SINGLE, NULL, 0x00);
	if(eRet == ER_OK)
	{
		BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
		if((eRet = GetData(RF_INVENTORY_SINGLE, &pDataRet, dwDataRet)) == ER_OK)
		{
			eRet = ER_EXEC_CMD;
			if(*pDataRet == 0x00)
			{
				eRet = CUtility::SetDataByte(pDataRet + 0x01, dwDataRet - 0x01, pData, dwData);
			}
			delete[] pDataRet;
		}
	}
	return eRet;
}

EERROR CRFEmbProtocol::Read(BYTE* pData, DWORD& dwData)
{
	EERROR eRet = ER_INVALID_DATA;
	if(pData != NULL)
	{
		// tag count + tag + bank memory + 0x02 start address + 0x04 pass + 0x01 size to read
		DWORD dwDataSend = 0x01 + m_stReadWriteInfo.nCardIdLen + 0x01 + 0x02 + 0x04 + 0x01;
		BYTE* pDataSend = new BYTE[dwDataSend];
		BYTE* pDataNav = pDataSend;

		pDataNav[0x00] = (BYTE)m_stReadWriteInfo.nCardIdLen; pDataNav++;
		memcpy_s(pDataNav, m_stReadWriteInfo.nCardIdLen, m_stReadWriteInfo.pCardId, m_stReadWriteInfo.nCardIdLen); pDataNav += m_stReadWriteInfo.nCardIdLen;
		pDataNav[0x00] = m_stReadWriteInfo.bBank; pDataNav++;

		// start address
		pDataNav[0x00] = (m_stReadWriteInfo.ulStartAddress >> 0x08) & 0xFF ; pDataNav++;
		pDataNav[0x00] = m_stReadWriteInfo.ulStartAddress & 0xFF; pDataNav++;

		// pass
		memcpy_s(pDataNav, 0x04, m_stReadWriteInfo.pPass, 0x04); pDataNav += 0x04;

		// size
		pDataNav[0x00] = (BYTE)dwData; pDataNav++;

		eRet = SendCmd(RF_READ_FROM_TAG, pDataSend, dwDataSend);
		if(eRet == ER_OK)
		{
			BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
			if((eRet = GetData(RF_READ_FROM_TAG, &pDataRet, dwDataRet)) == ER_OK)
			{
				eRet = ER_EXEC_CMD;
				if(pDataRet[0x00] == 0x00)
				{
					CUtility::SetDataByte(pDataRet + 0x02, pDataRet[0x01], pData, dwData);
					eRet = ER_OK;
				}
			}
			delete[] pDataRet;
		}
		delete[] pDataSend;
	}

	return eRet;
}

EERROR CRFEmbProtocol::Write(BYTE* pData, DWORD dwData)
{
	EERROR eRet = ER_INVALID_DATA;
	if(pData != NULL)
	{
		// tag count + tag + bank memory + 0x02 start address + 0x04 pass + 0x01 size to write + write data
		DWORD dwDataSend = 0x01 + m_stReadWriteInfo.nCardIdLen + 0x01 + 0x02 + 0x04 + 0x01 + dwData;
		BYTE* pDataSend = new BYTE[dwDataSend];
		BYTE* pDataNav = pDataSend;

		pDataNav[0x00] = (BYTE)m_stReadWriteInfo.nCardIdLen; pDataNav++;
		memcpy_s(pDataNav, m_stReadWriteInfo.nCardIdLen, m_stReadWriteInfo.pCardId, m_stReadWriteInfo.nCardIdLen); pDataNav += m_stReadWriteInfo.nCardIdLen;
		pDataNav[0x00] = m_stReadWriteInfo.bBank; pDataNav++;

		// start address
		pDataNav[0x00] = (m_stReadWriteInfo.ulStartAddress >> 0x08) & 0xFF ; pDataNav++;
		pDataNav[0x00] = m_stReadWriteInfo.ulStartAddress & 0xFF; pDataNav++;

		// pass
		memcpy_s(pDataNav, 0x04, m_stReadWriteInfo.pPass, 0x04); pDataNav += 0x04;

		// size
		pDataNav[0x00] = (BYTE)dwData; pDataNav++;
		memcpy_s(pDataNav, dwData, pData, dwData); pDataNav += dwData;

		eRet = SendCmd(RF_WRITE_TO_TAG, pDataSend, dwDataSend);
		if(eRet == ER_OK)
		{
			BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
			if((eRet = GetData(RF_WRITE_TO_TAG, &pDataRet, dwDataRet)) == ER_OK)
			{
				eRet = ER_EXEC_CMD;
				if(pDataRet[0x00] == 0x00)
				{
					eRet = ER_OK;
				}
			}
			delete[] pDataRet;
		}
		delete[] pDataSend;
	}

	return eRet;
}

EERROR CRFEmbProtocol::KillTag(KILL_TAG_INFO* pKillTagInfo)
{
	EERROR eRet = ER_INVALID_DATA;
	if(pKillTagInfo != NULL)
	{
		// tag count + tag + bank memory + 0x02 start address + 0x04 pass + 0x01 size to write + write data
		DWORD dwDataSend = 0x01 + pKillTagInfo->nCardIdLen + 0x04 + 0x01;
		BYTE* pDataSend = new BYTE[dwDataSend];
		BYTE* pDataNav = pDataSend;

		pDataNav[0x00] = (BYTE)pKillTagInfo->nCardIdLen; pDataNav++;
		memcpy_s(pDataNav, pKillTagInfo->nCardIdLen, pKillTagInfo->pCardId, pKillTagInfo->nCardIdLen); pDataNav += pKillTagInfo->nCardIdLen;

		// mode
		pDataNav[0x00] = 0x00; pDataNav++;

		// pass
		memcpy_s(pDataNav, 0x04, pKillTagInfo->pPass, 0x04); pDataNav += 0x04;


		eRet = SendCmd(RF_KILL_TAG, pDataSend, dwDataSend);
		if(eRet == ER_OK)
		{
			BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
			if((eRet = GetData(RF_KILL_TAG, &pDataRet, dwDataRet)) == ER_OK)
			{
				eRet = ER_EXEC_CMD;
				if(pDataRet[0x00] == 0x00)
				{
					eRet = ER_OK;
				}
			}
			delete[] pDataRet;
		}
		delete[] pDataSend;
	}

	return eRet;
}

EERROR CRFEmbProtocol::LockTag(LOCK_TYPE_INFO* pLockTypeInfo)
{
	EERROR eRet = ER_INVALID_DATA;
	if(pLockTypeInfo != NULL)
	{
		// tag count + tag + bank memory + card id + 0x04 pass + 0x02 mode lock
		DWORD dwDataSend = 0x01 + pLockTypeInfo->nCardIdLen + 0x04 + 0x02;
		BYTE* pDataSend = new BYTE[dwDataSend];
		BYTE* pDataNav = pDataSend;

		pDataNav[0x00] = (BYTE)pLockTypeInfo->nCardIdLen; pDataNav++;
		memcpy_s(pDataNav, pLockTypeInfo->nCardIdLen, pLockTypeInfo->pCardId, pLockTypeInfo->nCardIdLen); pDataNav += pLockTypeInfo->nCardIdLen;

		// lock type
		pDataNav[0x00] = pLockTypeInfo->bLockType; pDataNav++;

		// mem bank
		pDataNav[0x00] = pLockTypeInfo->bBank; pDataNav++;

		// pass
		memcpy_s(pDataNav, 0x04, pLockTypeInfo->pPass, 0x04); pDataNav += 0x04;


		eRet = SendCmd(RF_LOCK_TAG, pDataSend, dwDataSend);
		if(eRet == ER_OK)
		{
			BYTE* pDataRet = NULL; DWORD dwDataRet = 0x00;
			if((eRet = GetData(RF_LOCK_TAG, &pDataRet, dwDataRet)) == ER_OK)
			{
				eRet = ER_EXEC_CMD;
				if(pDataRet[0x00] == 0x00)
				{
					eRet = ER_OK;
				}
			}
			delete[] pDataRet;
		}
		delete[] pDataSend;
	}

	return eRet;
}

DWORD WINAPI ThreadRead(LPVOID lpParameter)
{
	BOOL bStop = FALSE;
	CRFEmbProtocol* pProtocol = (CRFEmbProtocol*)lpParameter;
	if(pProtocol != NULL)
	{
		CDataTransfer* pDataTranfer = &pProtocol->m_clsDataTranfer;
		if(pDataTranfer != NULL)
		{
			BYTE bStart = TRUE;
			if(pProtocol->SendCmd(RF_INVENTORY_CYCLIC, &bStart, sizeof(BYTE)) == ER_OK)
			{
				while(bStop == FALSE)
				{
					EERROR eRet = ER_UNKNOWN;
					BYTE* pData = NULL; DWORD dwSize = 0x00, dwCmd = RF_UNKNOWN;;
					if(((eRet = pProtocol->GetData(dwCmd, &pData, dwSize)) == ER_OK))
					{
						switch(dwCmd)
						{
							case RF_INVENTORY_CYCLIC:	
							{
								// if stop then nothing anymore
								if((bStop = pDataTranfer->IsThreadStoped()))
								{
									pProtocol->Close();
								}
							}break;

							case RF_INVENTORY_CYCLIC_INT:
							{
								// duisplay first card only
								std::string strData = CUtility::DataToString(pData + 0x02, pData[0x01], FALSE);
								if(pProtocol->IsTabUsed())
								{
									strData += "\x09";
								}

								if(pProtocol->IsReturnUsed())
								{
									strData += "\x0D";
								}
								
								if(pDataTranfer->GetData() != strData)
								{
									INPUT* pInput = new INPUT[strData.size()];

									UINT nCount = 0x00;
									std::string::iterator it = strData.begin();
									while(it != strData.end())
									{
										pInput[nCount].type				= INPUT_KEYBOARD;
										pInput[nCount].ki.wVk			= *it;
										pInput[nCount].ki.wScan			= 0;
										pInput[nCount].ki.dwFlags		= 0;
										pInput[nCount].ki.time			= 0;
										pInput[nCount].ki.dwExtraInfo	= 0; //GetMessageExtraInfo();
										SendInput(0x01, &pInput[nCount], sizeof(INPUT));
										Sleep(10);
										it++;
										nCount++;
									}
									// SendInput((UINT)strData.size(), pInput, sizeof(INPUT));
									// Sleep(100);
									delete[] pInput;
								}
								pDataTranfer->InsertData(strData);
							}break;

							case RF_STATE_CHANGE_INT:
							{
							}break;
						}

						delete[] pData;
						dwSize = 0x00;
					}

					if((eRet == ER_OPEN) && (pDataTranfer->IsThreadStoped()))
					{
						bStop = TRUE;
					}
				}
			}
		}
	}

	return 0x00;
}

EERROR CRFEmbProtocol::StartReading()
{
	m_clsDataTranfer.StopThread(FALSE);
	CreateThread(NULL, 0x00, ThreadRead, this, 0x00, NULL);
	return ER_OK;
}

EERROR CRFEmbProtocol::StopReading()
{
	m_clsDataTranfer.StopThread(TRUE);
	BYTE bStart = FALSE;
	EERROR eRet = SendCmd(RF_INVENTORY_CYCLIC, &bStart, sizeof(BYTE));
	return eRet;
}

EERROR CRFEmbProtocol::Close()
{
	return m_clsTransport.Close();
}

