/*
 * QrfeProtocollHandlerRFE.cpp
 *
 *  Created on: 15.01.2009
 *      Author: stefan.detter
 */

#include <QrfeProtocolHandlerRFE.h>
#include <QrfeProtocolHandlerRFE_Defines.h>

#include <QrfeCRC>
#include <QrfeSleeper>
#include <QrfeMutexLocker>


QrfeProtocolHandlerRFE::QrfeProtocolHandlerRFE(QIODevice* dev, QrfeGlobal::DeviceType deviceType, QObject* parent) :
	QrfeProtocolHandler(dev, deviceType, parent)
{
	m_MAX_WAIT_TIME_IN_MS = 1000;
	if (deviceType == QrfeGlobal::DEVICE_TCP)
		m_MAX_WAIT_TIME_IN_MS = 2000;

	m_MAX_PENDING_WAIT_TIME_IN_MS = 10000;

	m_interruptsBlocked = false;

	m_state = START_BYTE_1;
	m_payloadIndex = 0;
	m_payloadLength = 0;
	m_command1 = 0;
	m_command2 = 0;
	m_lastReturnCode = RFE_RET_SUCCESS;

	m_pendingResultsQueue.setSingleThread(false);

	m_classInitialized = true;

	m_useDeprecatedRfFunctions = true;
}

QrfeProtocolHandlerRFE::~QrfeProtocolHandlerRFE()
{
	m_classInitialized = false;
}


eRFE_RET_VALUE QrfeProtocolHandlerRFE::lastReturnCode()
{
	return m_lastReturnCode;
}

void QrfeProtocolHandlerRFE::useDeprecatedRfFunctions ( bool use )
{
	trc(1, "Using deprecated RF functions");
	m_useDeprecatedRfFunctions = use;
}


QrfeGlobal::Result QrfeProtocolHandlerRFE::getReaderID(ulong &readerID)
{
	trc(1, "Get Reader ID - Trying to get Reader ID");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_SERIAL_NUMBER;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Reader ID", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 4){
		warning("Get Reader ID - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	readerID = 0;
	readerID |= (((ulong) (uchar) response.at(0)) << 24);
	readerID |= (((ulong) (uchar) response.at(1)) << 16);
	readerID |= (((ulong) (uchar) response.at(2)) << 8);
	readerID |= (ulong) (uchar) response.at(3);

	this->traceModuleName = prepareModuleName("ProtclHndl-" + QString("%1").arg(readerID, 8, 16, QChar('0')));

	trc(1, "Get Reader ID - OK : Serial Number = " + QString("%1").arg(readerID, 8, 16,
			QChar('0')));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getReaderType(ulong &readerType)
{
	trc(1, "Get Reader Type - Trying to get Reader Type");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_READER_TYPE;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Reader Type", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 4){
		warning("Get Reader Type - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	readerType = 0;
	readerType |= (((ulong) (uchar) response.at(0)) << 24);
	readerType |= (((ulong) (uchar) response.at(1)) << 16);
	readerType |= (((ulong) (uchar) response.at(2)) << 8);
	readerType |= (ulong) (uchar) response.at(3);

	trc(1, "Get Reader Type - OK : Reader Type = " + QString("%1").arg(readerType, 8, 16, QChar('0')));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getHardwareRevision(
		ulong &hardwareRevision)
{
	trc(1, "Get Hardware Rev - Trying to get hardware ID");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_HARDWARE_REVISION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Hardware Revision", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0){
		warning("Get Hardware Rev - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	// set the variable to the new value

	hardwareRevision = 0;
	hardwareRevision |= (((ulong) (uchar) response.at(0)) << 24);
	hardwareRevision |= (((ulong) (uchar) response.at(1)) << 16);
	hardwareRevision |= (((ulong) (uchar) response.at(2)) << 8);
	hardwareRevision |= (ulong) (uchar) response.at(3);

	trc(1, "Get Hardware Rev - OK : Hardware Revision = " + QString("%1").arg(hardwareRevision, 8, 16, QChar('0')));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getSoftwareRevision(
		ulong &softwareRevision)
{
	trc(1, "Get Software Rev - Trying to get software ID");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_SOFTWARE_REVISION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Software Revision", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0){
		warning("Get Software Rev - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	// set the variable to the new value
	softwareRevision = 0;
	softwareRevision |= (((ulong) (uchar) response.at(0)) << 24);
	softwareRevision |= (((ulong) (uchar) response.at(1)) << 16);
	softwareRevision |= (((ulong) (uchar) response.at(2)) << 8);
	softwareRevision |= (ulong) (uchar) response.at(3);

	trc(1, "Get Software Rev - OK : Software Revision = " + QString("%1").arg(softwareRevision, 8, 16, QChar('0')));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getBootloaderRevision(
		ulong &bootloaderRevision)
{
	trc(1, "Get Bootloader Rev - Trying to get bootloader ID");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_BOOTLOADER_REVISION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Bootloader Revision", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 4){
		warning("Get Bootloader Rev - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	// set the variable to the new value
	bootloaderRevision = 0;
	bootloaderRevision |= (((ulong) (uchar) response.at(0)) << 24);
	bootloaderRevision |= (((ulong) (uchar) response.at(1)) << 16);
	bootloaderRevision |= (((ulong) (uchar) response.at(2)) << 8);
	bootloaderRevision |= (ulong) (uchar) response.at(3);

	trc(1, "Get Bootloader Rev - OK : Bootloader Revision = " + QString("%1").arg(bootloaderRevision, 8, 16, QChar('0')));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getCurrentSystem(
		QString &currentSystem)
{
	trc(1, "Get Current System - Trying to get current System");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_CURRENT_SYSTEM;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Current System", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 1){
		trc(1, "Get Current System - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	if ((uchar) response.at(0) == FIRMWARE)
	{
		currentSystem = "Firmware";
	}
	else if ((uchar) response.at(0) == BOOTLOADER)
	{
		currentSystem = "Bootloader";
	}
	else
	{
		warning("Get Current System - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Get Current System - OK : System " + currentSystem);

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getCurrentState(
		QrfeGlobal::ReaderState &currentState)
{
	trc(1, "Get Current State - Trying to get current State");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_CURRENT_STATE;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Current State", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 1){
		trc(1, "Get Current State - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	if ((uchar) response.at(0) == RFE_STATE_IDLE)
	{
		currentState = QrfeGlobal::STATE_IDLE;
	}
	else if ((uchar) response.at(0) == RFE_STATE_SCANNING)
	{
		currentState = QrfeGlobal::STATE_SCANNING;
	}
	else if ((uchar) response.at(0) == RFE_STATE_REBOOTING)
	{
		currentState = QrfeGlobal::STATE_REBOOTING;
	}
	else
	{
		warning("Get Current State - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Get Current State - OK : State " + QString::number(currentState));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getStatusRegister ( qulonglong &statusRegister )
{
	trc(1, "Get Status Register - Trying to get current State");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_STATUS_REGISTER;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Status Register", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 8){
		warning("Get Status Register - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	statusRegister = 0;
	statusRegister |= (((qulonglong) (uchar) response.at(0)) << 56);
	statusRegister |= (((qulonglong) (uchar) response.at(1)) << 48);
	statusRegister |= (((qulonglong) (uchar) response.at(2)) << 40);
	statusRegister |= (((qulonglong) (uchar) response.at(3)) << 32);
	statusRegister |= (((qulonglong) (uchar) response.at(4)) << 24);
	statusRegister |= (((qulonglong) (uchar) response.at(5)) << 16);
	statusRegister |= (((qulonglong) (uchar) response.at(6)) << 8);
	statusRegister |= (qulonglong) (uchar) response.at(7);

	trc(1, "Get Status Register - OK : Status Register = " + QString("%1").arg(statusRegister, 16, 16, QChar('0')));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getAntennaCount ( uchar &count )
{
	trc(1, "Get Antenna Count - Trying to get Antenna Count");
	uchar com1 = RFE_COM1_READER_COMMON;
	uchar com2 = RFE_COM2_GET_ANTENNA_COUNT;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Antenna Count", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 2 || response.at(0) != RFE_RET_SUCCESS){
		warning("Get Antenna Count - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	count = (uchar) response.at(1);

	trc(1, "Get Antenna Count - OK : Count = " + QString("%1").arg(count));

	return QrfeGlobal::RES_OK;
}


QrfeGlobal::Result QrfeProtocolHandlerRFE::getAttenuation(
		ushort &maxOutputPower, ushort &currentOutputPower)
{
	trc(1, "Get Attenuation - Trying to attenuation");
	uchar com1 = RFE_COM1_READER_RF;
	uchar com2 = RFE_COM2_GET_ATTENUATION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Attenuatuin", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 5 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Get Attenuation - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	// set the variable to the new value
	maxOutputPower = 0;
	maxOutputPower |= (((ushort) (uchar) response.at(1)) << 8);
	maxOutputPower |= ((ushort) (uchar) response.at(2));

	currentOutputPower = 0;
	currentOutputPower |= (((ushort) (uchar) response.at(3)) << 8);
	currentOutputPower |= (ushort) (uchar) response.at(4);

	trc(1, "Get Attenuation - OK : Maximum Attenuation " + QString::number(maxOutputPower) +
								 " Current Attenuation " + QString::number(currentOutputPower));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getFrequency(uchar &mode,
		uchar &maxFrequencyCount, QList<uint> &frequencies)
{
	trc(1, "Get Frequency - Trying to frequency");
	uchar com1 = RFE_COM1_READER_RF;
	uchar com2 = RFE_COM2_GET_FREQUENCY;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Frequency", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() < 5 || response.at(0)
			!= RFE_RET_SUCCESS)
	{
		warning("Get Frequency - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	mode = response.at(1);
	maxFrequencyCount = response.at(2);
	frequencies.clear();
	uchar count = response.at(3);
	uchar index = 4;
	for (int i = 0; i < count; i++)
	{
		uint freq = 0;
		freq |= (((ulong) (uchar) response.at(index++)) << 16);
		freq |= (((ulong) (uchar) response.at(index++)) << 8);
		freq |= (ulong) (uchar) response.at(index++);

		frequencies.append(freq);
	}

	trc(1, "Get Frequency - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getSensitivity( short &maxSensitivity, short &minSensitivity, short &currentSensitivity )
{
	trc(1, "Get Sensitivity - Trying to get Sensitivity");

	uchar com1 = RFE_COM1_READER_RF;
	uchar com2 = RFE_COM2_GET_SENSITIVITY;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Sensitivity", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 7 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Get Sensitivity - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	// set the variable to the new value
	maxSensitivity = 0;
	maxSensitivity |= (((short) (uchar) response.at(1)) << 8);
	maxSensitivity |= (short) (uchar) response.at(2);

	minSensitivity = 0;
	minSensitivity |= (((short) (uchar) response.at(3)) << 8);
	minSensitivity |= (short) (uchar) response.at(4);

	currentSensitivity = 0;
	currentSensitivity |= (((short) (uchar) response.at(5)) << 8);
	currentSensitivity |= (short) (uchar) response.at(6);

	trc(1, "Get Sensitivity - OK : Maximum Sensitivity " + QString::number(maxSensitivity) +
								 " Minimum Sensitivity " + QString::number(minSensitivity) +
								 " Current Sensitivity " + QString::number(currentSensitivity));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getLbtParams ( ushort &listenTime, ushort &idleTime, ushort &maxAllocTime, short &rssiThreshold )
{
	trc(1, "Get LBT-Params - Trying to get LBT Params");

	uchar com1 = RFE_COM1_READER_RF;
	uchar com2 = RFE_COM2_GET_LBT_PARAMS;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get LBT-Params", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 9 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Get LBT-Params - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	// set the variable to the new value
	listenTime = 0;
	listenTime |= (((ushort) (uchar) response.at(1)) << 8);
	listenTime |= (ushort) (uchar) response.at(2);

	idleTime = 0;
	idleTime |= (((ushort) (uchar) response.at(3)) << 8);
	idleTime |= (ushort) (uchar) response.at(4);

	maxAllocTime = 0;
	maxAllocTime |= (((ushort) (uchar) response.at(5)) << 8);
	maxAllocTime |= (ushort) (uchar) response.at(6);

	rssiThreshold = 0;
	rssiThreshold |= (((short) (uchar) response.at(7)) << 8);
	rssiThreshold |= (short) (uchar) response.at(8);

	trc(1, "Get LBT-Params - OK : Listen Time " + QString::number(listenTime) +
								 " Idle Time " + QString::number(idleTime) +
								 " Maximum Allocation Time " + QString::number(maxAllocTime) +
								 " RSSI Threshold " + QString::number(rssiThreshold));

	return QrfeGlobal::RES_OK;

}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setAttenuation(ushort value)
{
	trc(1, "Set Attenuation - Trying to set output power to " + QString::number(value));

	QByteArray payload;
	payload.resize(2);
	payload[0] = (uchar) (value >> 8);
	payload[1] = (uchar) (value);

	uchar com1 = RFE_COM1_READER_RF;
	uchar com2 = RFE_COM2_SET_ATTENUATION;

	if(m_useDeprecatedRfFunctions)
	{
		com1 = RFE_COM1_READER_CONTROL;
		com2 = RFE_COM2_SET_ATTENUATION_DEPRECATED;
	}

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Attenuation", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Set Attenuation - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Attenuation - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setFrequency(uchar mode, const QList<uint> & frequencies)
{
	trc(1, "Set Frequency - Trying to set frequency");

	QByteArray payload;
	payload.resize(2);
	payload[0] = mode;
	payload[1] = frequencies.size();

	for (int i = 0; i < frequencies.size(); i++)
	{
		payload.append((frequencies.at(i) >> 16));
		payload.append((frequencies.at(i) >> 8));
		payload.append((frequencies.at(i)));
	}

	uchar com1 = RFE_COM1_READER_RF;
	uchar com2 = RFE_COM2_SET_FREQUENCY;

	if(m_useDeprecatedRfFunctions)
	{
		com1 = RFE_COM1_READER_CONTROL;
		com2 = RFE_COM2_SET_FREQUENCY_DEPRECATED;
	}

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Frequency", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Set Frequency - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Frequency - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setSensitivity ( short targetValue, short &actualValue )
{
	trc(1, "Set Sensitivity - Trying to set sensitvity to " + QString::number(targetValue));

	QByteArray payload;
	payload.resize(2);
	payload[0] = (uchar) (targetValue >> 8);
	payload[1] = (uchar) (targetValue);

	uchar com1 = RFE_COM1_READER_RF;
	uchar com2 = RFE_COM2_SET_SENSITIVITY;

	if(m_useDeprecatedRfFunctions)
	{
		com1 = RFE_COM1_READER_CONTROL;
		com2 = RFE_COM2_SET_SENSITIVITY_DEPRECATED;
	}

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Sensitivity", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Set Sensitivity - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	actualValue = 0;
	actualValue |= (((short) (uchar) response.at(1)) << 8);
	actualValue |= (short) (uchar) response.at(2);

	trc(1, "Set Sensitivity - OK : Set to " + QString::number(actualValue));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setLbtParams ( ushort listenTime, ushort idleTime, ushort maxAllocTime, short rssiThreshold )
{
	trc(1, "Set LBT-Params - Trying to set lbt params: Listen Time " + QString::number(listenTime) +
													 " Idle Time " + QString::number(idleTime) +
													 " Maximum Allocation Time " + QString::number(maxAllocTime) +
													 " RSSI Threshold " + QString::number(rssiThreshold));

	QByteArray payload;
	payload.resize(8);
	payload[0] = (uchar) (listenTime >> 8);
	payload[1] = (uchar) (listenTime);
	payload[2] = (uchar) (idleTime >> 8);
	payload[3] = (uchar) (idleTime);
	payload[4] = (uchar) (maxAllocTime >> 8);
	payload[5] = (uchar) (maxAllocTime);
	payload[6] = (uchar) (rssiThreshold >> 8);
	payload[7] = (uchar) (rssiThreshold);

	uchar com1 = RFE_COM1_READER_RF;
	uchar com2 = RFE_COM2_SET_LBT_PARAMS;

	if(m_useDeprecatedRfFunctions)
	{
		com1 = RFE_COM1_READER_CONTROL;
		com2 = RFE_COM2_SET_LBT_PARAMS_DEPRECATED;
	}

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set LBT-Params", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Set LBT-Params - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set LBT-Params - OK");

	return QrfeGlobal::RES_OK;
}




QrfeGlobal::Result QrfeProtocolHandlerRFE::reboot()
{
	trc(1, "Reboot - Trying to reboot");

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_REBOOT;

	// send the command
	QrfeGlobal::Result res = send2ReaderWithoutResponse(com1, com2, "Reboot");
	if (res != QrfeGlobal::RES_OK){
		error("Reboot - NOK - Send");
		return res;
	}

	QrfeSleeper::MSleepAlive(50);

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setHeartBeat ( eRFE_HEARTBEAT_TYPE type, ushort interval )
{
	trc(1, "Set Heartbeat - Trying to set heartbeat to type #" + QString::number(type));

	QByteArray payload;
	payload.resize(1);
	payload[0] = type;
	if (interval != 0)
	{
		payload.resize(3);
		payload[1] = (uchar) (interval >> 8);
		payload[2] = (uchar) (interval);
	}

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_SET_HEARTBEAT;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Heartbeat", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0)
			!= RFE_RET_SUCCESS)
	{
		warning("Set Heartbeat - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Heartbeat - OK");

	return QrfeGlobal::RES_OK;

}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setAntennaPower(bool on)
{
	trc(1, "Set Antenna - Trying to set antenna power " + QString((on) ? "ON" : "OFF"));

	QByteArray payload;
	payload.resize(1);
	payload[0] = (on) ? ANTENNA_ON : ANTENNA_OFF;

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_SET_ANTENNA_POWER;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Antenna Power", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Set Antenna - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Antenna - OK");

	return QrfeGlobal::RES_OK;
}


QrfeGlobal::Result QrfeProtocolHandlerRFE::saveSettingsPermanent()
{
	trc(1, "Save Settings - Trying save settings permanent");

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_SAVE_SETTINGS_PERMANENT;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Save Settings", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0)
			!= RFE_RET_SUCCESS)
	{
		warning("Save Settings - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Save Settings - OK");

	return QrfeGlobal::RES_OK;

}

QrfeGlobal::Result QrfeProtocolHandlerRFE::restoreFactorySettings()
{
	trc(1, "Restore Settings - Trying to restore settings");
	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_RESTORE_FACTORY_SETTINGS;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Restore Settings", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0)
			!= RFE_RET_SUCCESS)
	{
		warning("Restore Settings - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode
				= (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Restore Settings - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getParam(ushort address,
		QByteArray &value)
{
	trc(1, "Get Param - Trying to get param of address " + QString::number(	address));

	QByteArray payload;
	payload.resize(2);
	payload[0] = (uchar) (address >> 8);
	payload[1] = (uchar) (address);

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_GET_PARAM;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Get Param", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0)
			!= RFE_RET_SUCCESS)
	{
		warning("Get Param - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	value.clear();
	value.append(response.right(response.size() - 2));

	trc(1, "Get Param - OK : " + value.toHex());

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setParam(ushort address,
		QByteArray value)
{
	trcBytes(1, "Set Param - Trying to set param at address "
			+ QString::number(address) + " to ", value);

	QByteArray payload;
	payload.resize(3);
	payload[0] = (uchar) (address >> 8);
	payload[1] = (uchar) (address);
	payload[2] = (uchar) value.size();
	payload.append(value);

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_SET_PARAM;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Param", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0)
			!= RFE_RET_SUCCESS)
	{
		warning("Set Param - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Param - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getDeviceName ( QString &name )
{
	trc(1, "Get Reader Name - Trying to get Reader Name");

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_GET_DEVICE_NAME;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Reader Name", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() < 1 || response.at(0) != RFE_RET_SUCCESS){
		warning("Get Reader Name - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	name = QString::fromLatin1( response.right(response.size()-1) );

	trc(1, "Get Reader Name - OK : Reader Name = " + name);

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setDeviceName ( const QString &name )
{
	trc(1, "Set Reader Name - Trying to set Reader Name to " + name);

	if(name.size() > 254){
		error("Set Reader Name - Given name is too large");
		return QrfeGlobal::RES_ERROR;
	}


	QByteArray payload = name.toLatin1();

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_SET_DEVICE_NAME;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Device Name", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 1 || response.at(0) != RFE_RET_SUCCESS){
		warning("Set Reader Name - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Reader Name - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getDeviceLocation ( QString &location )
{
	trc(1, "Get Reader Location - Trying to get Reader Name");

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_GET_DEVICE_LOCATION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Device Location", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() < 1 || response.at(0) != RFE_RET_SUCCESS){
		warning("Get Reader Location - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	location = QString::fromLatin1( response.right(response.size()-1) );

	trc(1, "Get Reader Location - OK : Reader Location = " + location);

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setDeviceLocation ( const QString &location )
{
	trc(1, "Set Reader Location - Trying to set Reader Locationt to " + location);

	if(location.size() > 254){
		error("Set Reader Location - Given location is too large");
		return QrfeGlobal::RES_ERROR;
	}

	QByteArray payload = location.toLatin1();

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_SET_DEVICE_LOCATION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Device Location", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 1 || response.at(0) != RFE_RET_SUCCESS){
		warning("Set Reader Location - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Reader Location - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::switchCommBaudrate ( ulong baudRate )
{
	trc(1, "Switch Comm Baudrate - Trying to switch comm baudrate");

	QByteArray payload;
	payload.resize(3);
	payload[0] = (uchar) (baudRate >> 16);
	payload[1] = (uchar) (baudRate >> 8);
	payload[2] = (uchar) (baudRate >> 0);

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_SWITCH_COMM_BAUD;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Switch Comm Baudrate", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0)
			!= RFE_RET_SUCCESS)
	{
		warning("Switch Comm Baudrate - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Switch Comm Baudrate - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::switchCommInterface ( eRFE_COMM_INTERFACE_ID id )
{
	trc(1, "Switch Comm Interface - Trying to switch comm interface");

	QByteArray payload;
	payload.resize(1);
	payload[0] = (uchar) (id);

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_SWITCH_COMM_INTERFACE;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Switch Comm Interface", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0)
			!= RFE_RET_SUCCESS)
	{
		warning("Switch Comm Interface - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Switch Comm Interface - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::switchSystem()
{
	trc(1, "Switch System - Trying to switch system");

	// send the command
	QrfeGlobal::Result res = send2ReaderWithoutResponse(RFE_COM1_READER_CONTROL, RFE_COM2_SWITCH_SYSTEM, "Switch System");
	if (res != QrfeGlobal::RES_OK){
		error("Switch System - NOK - Send");
		return res;
	}

	QrfeSleeper::MSleepAlive(50);

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::bootloader(QByteArray &getMessage,
		QByteArray setMessage)
{
	trc(1, "Bootloader - Trying to get bootloader Message");

	uchar com1 = RFE_COM1_READER_CONTROL;
	uchar com2 = RFE_COM2_BOOTLOADER_COMMAND;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, setMessage, m_MAX_WAIT_TIME_IN_MS*5, "Bootloader", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0){
		warning("Bootloader - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	getMessage = response;

	trc(1, "Bootloader - OK : Received bootloader message: " + getMessage.toHex());

	return QrfeGlobal::RES_OK;

}

QrfeGlobal::Result QrfeProtocolHandlerRFE::bootloader(QByteArray setMessage)
{
    trc(1, "Bootloader - Trying to get bootloader Message");

    uchar com1 = RFE_COM1_READER_CONTROL;
    uchar com2 = RFE_COM2_BOOTLOADER_COMMAND;

    QByteArray response;
    QrfeGlobal::Result res = send2ReaderWithoutResponse(com1, com2, setMessage, "Bootloader");

    if(res != QrfeGlobal::RES_OK)
        return res;

    QrfeSleeper::MSleepAlive(50);

    return QrfeGlobal::RES_OK;
}


QrfeGlobal::Result QrfeProtocolHandlerRFE::setTagType(uint /*type*/)
{
	return QrfeGlobal::RES_NA;
}


QrfeGlobal::Result QrfeProtocolHandlerRFE::getGPIOCaps ( ulong &mask, ulong &output, ulong &input )
{
	trc(1, "Get GPIO Caps - Trying to get GPIO Caps");

	uchar com1 = RFE_COM1_READER_GPIO;
	uchar com2 = RFE_COM2_GET_GPIO_CAPS;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get GPIO Caps", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 12){
		warning("Get GPIO Caps - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	mask = 0;
	mask |= (((ulong) (uchar) response.at(0)) << 24);
	mask |= (((ulong) (uchar) response.at(1)) << 16);
	mask |= (((ulong) (uchar) response.at(2)) << 8);
	mask |= (ulong) (uchar) response.at(3);

	output = 0;
	output |= (((ulong) (uchar) response.at(4)) << 24);
	output |= (((ulong) (uchar) response.at(5)) << 16);
	output |= (((ulong) (uchar) response.at(6)) << 8);
	output |= (ulong) (uchar) response.at(7);

	input = 0;
	input |= (((ulong) (uchar) response.at(8)) << 24);
	input |= (((ulong) (uchar) response.at(9)) << 16);
	input |= (((ulong) (uchar) response.at(10)) << 8);
	input |= (ulong) (uchar) response.at(11);

	trc(1, "Get GPIO Caps - OK : Mask   = " + QString("%1").arg(mask, 8, 16, QChar('0')) +
							   " Output = " + QString("%1").arg(output, 8, 16, QChar('0')) +
							   " Input  = " + QString("%1").arg(input, 8, 16, QChar('0')) );

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getGPIODirection ( ulong &direction )
{
	trc(1, "Get GPIO Direction - Trying to get GPIO Direction");

	uchar com1 = RFE_COM1_READER_GPIO;
	uchar com2 = RFE_COM2_GET_GPIO_DIRECTION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get GPIO Direction", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 4){
		warning("Get GPIO Direction - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	direction = 0;
	direction |= (((ulong) (uchar) response.at(0)) << 24);
	direction |= (((ulong) (uchar) response.at(1)) << 16);
	direction |= (((ulong) (uchar) response.at(2)) << 8);
	direction |= (ulong) (uchar) response.at(3);

	trc(1, "Get GPIO Direction - OK : Direction = " + QString("%1").arg(direction, 8, 16, QChar('0')) );

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setGPIODirection ( ulong direction )
{
	trc(1, "Set GPIO Direction - Trying to set GPIO Direction: Direction = " + QString("%1").arg(direction, 8, 16, QChar('0')));

	QByteArray payload;
	payload.resize(4);
	payload[0] = (uchar) (direction >> 24);
	payload[1] = (uchar) (direction >> 16);
	payload[2] = (uchar) (direction >> 8);
	payload[3] = (uchar) (direction);

	uchar com1 = RFE_COM1_READER_GPIO;
	uchar com2 = RFE_COM2_SET_GPIO_DIRECTION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set GPIO Direction", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS) {
		warning("Set GPIO Direction - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set GPIO Direction - OK" );

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getGPIO ( ulong &mask )
{
	trc(1, "Get GPIO - Trying to get GPIO Value");

	uchar com1 = RFE_COM1_READER_GPIO;
	uchar com2 = RFE_COM2_GET_GPIO;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get GPIO", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 4){
		warning("Get GPIO - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	mask = 0;
	mask |= (((ulong) (uchar) response.at(0)) << 24);
	mask |= (((ulong) (uchar) response.at(1)) << 16);
	mask |= (((ulong) (uchar) response.at(2)) << 8);
	mask |= (ulong) (uchar) response.at(3);

	trc(1, "Get GPIO Value - OK : Mask = " + QString("%1").arg(mask, 8, 16, QChar('0')) );

	return QrfeGlobal::RES_OK;

}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setGPIO ( ulong mask )
{
	trc(1, "Set GPIO - Trying to set GPIO: Mask = " + QString("%1").arg(mask, 8, 16, QChar('0')) );

	QByteArray payload;
	payload.resize(4);
	payload[0] = (uchar) (mask >> 24);
	payload[1] = (uchar) (mask >> 16);
	payload[2] = (uchar) (mask >> 8);
	payload[3] = (uchar) (mask);


	uchar com1 = RFE_COM1_READER_GPIO;
	uchar com2 = RFE_COM2_SET_GPIO;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set GPIO", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS) {
		warning("Set GPIO - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set GPIO - OK" );

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::clearGPIO ( ulong mask )
{
	trc(1, "Clear GPIO - Trying to clear GPIO: Mask = " + QString("%1").arg(mask, 8, 16, QChar('0')) );

	QByteArray payload;
	payload.resize(4);
	payload[0] = (uchar) (mask >> 24);
	payload[1] = (uchar) (mask >> 16);
	payload[2] = (uchar) (mask >> 8);
	payload[3] = (uchar) (mask);

	uchar com1 = RFE_COM1_READER_GPIO;
	uchar com2 = RFE_COM2_CLEAR_GPIO;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Clear GPIO", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS) {
		warning("Clear GPIO - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Clear GPIO - OK ");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::clearSetGPIO ( ulong clearMask, ulong setMask )
{
	trc(1, "ClearSet GPIO - Trying to clear GPIO: Mask = " + QString("%1").arg(clearMask, 8, 16, QChar('0')) +
						" and Trying to set GPIO: Mask = " + QString("%1").arg(setMask, 8, 16, QChar('0')) );

	QByteArray payload;
	payload.resize(8);
	payload[0] = (uchar) (clearMask >> 24);
	payload[1] = (uchar) (clearMask >> 16);
	payload[2] = (uchar) (clearMask >> 8);
	payload[3] = (uchar) (clearMask);
	payload[4] = (uchar) (setMask >> 24);
	payload[5] = (uchar) (setMask >> 16);
	payload[6] = (uchar) (setMask >> 8);
	payload[7] = (uchar) (setMask);


	uchar com1 = RFE_COM1_READER_GPIO;
	uchar com2 = RFE_COM2_CLEAR_SET_GPIO;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "ClearSet GPIO", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS) {
		warning("ClearSet GPIO - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "ClearSet GPIO - OK ");

	return QrfeGlobal::RES_OK;
}



QrfeGlobal::Result QrfeProtocolHandlerRFE::setAntennaSequence ( const QList<QPair<uchar,ulong> > & sequence )
{
	trc(1, "Set Antenna Sequence - Trying to set antenna sequence");

	for(int i = 0; i < sequence.size(); i++)
	{
		trc(1, QString("[%1] Antenna #%2 for %3ms").arg(i).arg(sequence.at(i).first).arg(sequence.at(i).second));
	}

	QByteArray payload;
	payload.resize(1);
	payload[0] = (uchar) (sequence.size());

	for(int i = 0; i < sequence.size(); i++)
	{
		payload.append(sequence.at(i).first);
		payload.append((sequence.at(i).second >> 24));
		payload.append((sequence.at(i).second >> 16));
		payload.append((sequence.at(i).second >> 8));
		payload.append((sequence.at(i).second));
	}

	uchar com1 = RFE_COM1_READER_ANTENNA;
	uchar com2 = RFE_COM2_SET_ANTENNA_SEQUENCE;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Antenna Sequence", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Set Antenna Sequence - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Antenna Sequence - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getAntennaSequence ( QList<QPair<uchar,ulong> > & sequence )
{
	trc(1, "Get Antenna Sequence - Trying to get antenna sequence");

	sequence.clear();

	uchar com1 = RFE_COM1_READER_ANTENNA;
	uchar com2 = RFE_COM2_GET_ANTENNA_SEQUENCE;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Antenna Sequence", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() < 2 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Get Antenna Sequence - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	uchar sequenceCount = response.at(1);

	if ( response.size() < ((sequenceCount * 5) + 2) )
	{
		warning("Get Antenna Sequence - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	uchar index = 2;
	for(uchar i = 0; i < sequenceCount; i++)
	{
		uchar antennaIndex = response.at(index++);

		ulong time = 0;
		time |= (((ulong) (uchar) response.at(index++)) << 24);
		time |= (((ulong) (uchar) response.at(index++)) << 16);
		time |= (((ulong) (uchar) response.at(index++)) << 8);
		time |=  ((ulong) (uchar) response.at(index++));

		QPair<uchar,ulong> p;
		p.first = antennaIndex;
		p.second = time;

		sequence.append(p);
	}

	trc(1, "Get Antenna Sequence - OK:");
	for(uchar i = 0; i < sequence.size(); i++)
	{
		trc(1, " [" + QString::number(i) + "] Antenna #" + QString::number(sequence.at(i).first) +
				" for " + QString::number(sequence.at(i).second) + "ms");
	}

	return QrfeGlobal::RES_OK;

}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setWorkingAntenna ( uchar antennaIndex )
{
	trc(1, "Set Working Antenna - Trying to set antenna single to #" + QString::number(antennaIndex));

	QByteArray payload;
    payload.append((uchar) (antennaIndex));

	uchar com1 = RFE_COM1_READER_ANTENNA;
	uchar com2 = RFE_COM2_SET_WORKING_ANTENNA;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Set Working Antenna", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Set Working Antenna - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Set Working Antenna - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getWorkingAntenna ( uchar& antennaIndex )
{
	trc(1, "Get Working Antenna - Trying to get antenna sequence");

	uchar com1 = RFE_COM1_READER_ANTENNA;
	uchar com2 = RFE_COM2_GET_WORKING_ANTENNA;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Working Antenna", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() < 2 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Get Working Antenna - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	antennaIndex = response.at(1);

	trc(1, "Get Working Antenna - OK: " + QString::number(antennaIndex));

	return QrfeGlobal::RES_OK;
}




QrfeGlobal::Result QrfeProtocolHandlerRFE::activateNotification ( uchar id )
{
	trc(1, "Activate Notfication - Trying to activate notifcation: Id = " + QString("%1").arg(id) );

	QByteArray payload;
	payload.resize(1);
	payload[0] = (uchar) (id);

	uchar com1 = RFE_COM1_NOTFICATIONS;
	uchar com2 = RFE_COM2_ACTIVATE_NOTIFICATION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Activate Notfication", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS) {
		warning("Activate Notfication - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Activate Notfication - OK" );

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::deactivateNotification ( uchar id )
{
	trc(1, "Deactivate Notfication - Trying to deactivate notifcation: Id = " + QString("%1").arg(id) );

	QByteArray payload;
	payload.resize(1);
	payload[0] = (uchar) (id);

	uchar com1 = RFE_COM1_NOTFICATIONS;
	uchar com2 = RFE_COM2_DEACTIVATE_NOTIFICATION;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Deactivate Notfication", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS) {
		warning("Deactivate Notfication - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Deactivate Notfication - OK" );

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::getActiveNotifications ( qulonglong &notifications )
{
	trc(1, "Get Active Notifications - Trying to get Active Notifications");

	uchar com1 = RFE_COM1_NOTFICATIONS;
	uchar com2 = RFE_COM2_GET_ACTIVE_NOTIFICATIONS;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Active Notifications", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 8){
		warning("Get Active Notifications - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	notifications = 0;
	notifications |= (((qulonglong) (uchar) response.at(0)) << 56);
	notifications |= (((qulonglong) (uchar) response.at(1)) << 48);
	notifications |= (((qulonglong) (uchar) response.at(2)) << 40);
	notifications |= (((qulonglong) (uchar) response.at(3)) << 32);
	notifications |= (((qulonglong) (uchar) response.at(4)) << 24);
	notifications |= (((qulonglong) (uchar) response.at(5)) << 16);
	notifications |= (((qulonglong) (uchar) response.at(6)) << 8);
	notifications |= (qulonglong) (uchar) response.at(7);

	trc(1, "Get Active Notifications - OK : Status Register = " + QString("%1").arg(notifications, 16, 16, QChar('0')));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::applicationCommand ( const QByteArray& payload )
{
    QByteArray resp;
    return applicationCommand(payload, resp);
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::applicationCommand ( const QByteArray& payload, QByteArray& resp )
{
	trc(1, "App Command - Trying to send application command " + payload.toHex());

	uchar com1 = RFE_COM1_APPLICATION;
	uchar com2 = RFE_COM2_APPLICATION_CALL;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "App Command", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || (response.at(0) != RFE_RET_SUCCESS && response.at(0) != RFE_RET_RESULT_PENDING) )
	{
		warning("App Command - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	if(response.at(0) == RFE_RET_SUCCESS)
	{
		resp = response.right(response.size()-1);
	}
	else if(response.at(0) == RFE_RET_RESULT_PENDING)
	{
		warning("App Command - OK - Result Pending");

		if (response.size() != 2)
		{
			warning("App Command - NOK - Payl");
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
			m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
			return QrfeGlobal::RES_ERROR;
		}

		bool result = false;
		QByteArray pendingResp = m_pendingResultsQueue.waitForMessage((uchar)response.at(1), m_MAX_PENDING_WAIT_TIME_IN_MS, &result);
		if (!result){
			warning("App Command - NOK - Pending Resp");
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
			return QrfeGlobal::RES_NORESPONSE;
		}

		// set the variable to the new value
		if (pendingResp.size() == 0 || pendingResp.at(0) != RFE_RET_SUCCESS )
		{
			warning("App Command - NOK - Payl");
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex() + " | Recvd: " + pendingResp.toHex());
			m_lastReturnCode = (eRFE_RET_VALUE) (uchar) pendingResp.at(0);
			return QrfeGlobal::RES_ERROR;
		}

		resp = pendingResp.right(pendingResp.size()-1);
	}

	trc(1, "App Command - OK");

	return QrfeGlobal::RES_OK;
}


QrfeGlobal::Result QrfeProtocolHandlerRFE::doSingleInventory(QList<QrfeGlobal::TagEvent> &tagList)
{
	trc(1, "Single Inventory - Trying to do an inventory");

	uchar com1 = RFE_COM1_TAG_FUNCTIONS;
	uchar com2 = RFE_COM2_INVENTORY_SINGLE;

	QByteArray response;
	QrfeGlobal::Result res = send2Reader(com1, com2);

	if(res != QrfeGlobal::RES_OK)
		return res;

	tagList.clear();
	uchar epcsOverall = 0;
	uchar epcsReceived = 0;

	while(1)
	{
		QrfeGlobal::Result res = waitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Single Inventory", response);

		if(res != QrfeGlobal::RES_OK)
			return res;

		if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
		{
			warning("Single Inventory - NOK - Payl");
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
			m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
			return QrfeGlobal::RES_ERROR;
		}

		epcsOverall = response.at(1);
		uchar epcsInMessage = response.at(2);
		uchar index = 3;
		for (int i = 0; i < epcsInMessage; i++)
		{
            QByteArray tagEventPayload = response.mid(index+1, (uchar)response.at(index));
            bool ok = false;
            QrfeGlobal::TagEvent tagEvent = parseTagEvent(tagEventPayload, ok);

            if(!ok)
            	return QrfeGlobal::RES_ERROR;

            tagList << tagEvent;

            index += (uchar)response.at(index);
            index++;
		}
		epcsReceived += epcsInMessage;

		if(epcsReceived >= epcsOverall)
			break;
	}

	trc(1, "Single Inventory - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::setCyclicInventory(bool on, ulong time)
{
	trc(1, "Cyclic Inventory - Trying to set cyclic inventory to " + QString::number(on));

	QByteArray payload;
	payload.resize(1);
	if (on){
		payload[0] = INVENTORY_ON;
		if(time != 0)
		{
			payload.append((time >> 24));
			payload.append((time >> 16));
			payload.append((time >> 8));
			payload.append((time));
		}
	}
	else{
		payload[0] = INVENTORY_OFF;
	}

	uchar com1 = RFE_COM1_TAG_FUNCTIONS;
	uchar com2 = RFE_COM2_INVENTORY_CYCLIC;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Cyclic Inventory", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Cyclic Inventory - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Cyclic Inventory - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::readFromTag(QByteArray epc,
		uchar mem_bank, ushort address, QByteArray passwd, uchar count,
		QByteArray &data)
{
	trc(1, "Read From Tag - Trying to read from tag " + epc.toHex() + " from memory bank "
			+ QString::number(mem_bank) + " and address " + QString::number(
			address) + " the count " + QString::number(count));

	if (passwd.size() != 4){
		error("Read From Tag - NOK - Data");
		return QrfeGlobal::RES_ERROR;
	}


	QByteArray payload;
	payload.append(epc.size());
	payload.append(epc);

	payload.append((char) mem_bank);
	payload.append((char) (address >> 8));
	payload.append((char) address);
	payload.append(passwd);

	payload.append(count);

	uchar com1 = RFE_COM1_TAG_FUNCTIONS;
	uchar com2 = RFE_COM2_READ_FROM_TAG;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS * 4, "Read From Tag", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || (response.at(0) != RFE_RET_SUCCESS && response.at(0) != RFE_RET_RESULT_PENDING) )
	{
		warning("Read From Tag - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	if(response.at(0) == RFE_RET_SUCCESS)
	{
		data = response.mid(2, (uchar)response.at(1));
	}
	else if(response.at(0) == RFE_RET_RESULT_PENDING)
	{
		warning("Read From Tag - OK - Result Pending");

		if (response.size() != 2)
		{
			warning("Read From Tag - NOK - Payl");
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
			m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
			return QrfeGlobal::RES_ERROR;
		}

		QByteArray pendingResp;
		QrfeGlobal::Result pend_res = waitForPendingMessage((uchar)response.at(1), m_MAX_PENDING_WAIT_TIME_IN_MS, "Read From Tag", pendingResp);

		if(pend_res != QrfeGlobal::RES_OK)
		{
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
			return pend_res;
		}

		// set the variable to the new value
		if (pendingResp.size() == 0 || pendingResp.at(0) != RFE_RET_SUCCESS )
		{
			warning("Read From Tag - NOK - Payl");
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex() + " | Recvd: " + pendingResp.toHex());
			m_lastReturnCode = (eRFE_RET_VALUE) (uchar) pendingResp.at(0);
			return QrfeGlobal::RES_ERROR;
		}

		data = pendingResp.mid(2, (uchar)pendingResp.at(1));
	}


	trc(1, "Read From Tag - OK : Read the data from the tag: " + data.toHex());

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::readMultipleFromTag(QByteArray epc,
		QList<uchar> mem_bank, QList<ushort> address, QList<QByteArray> passwd, QList<uchar> count,
		QList<QByteArray> &data)
{
	if(mem_bank.size() != address.size() || address.size() != passwd.size() || passwd.size() != count.size()){
		error("Read Multiple From Tag - NOK - Data");
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Read Multiple From Tag - Trying to read from tag " + epc.toHex());
	for(int i = 0; i < mem_bank.size(); i++){
		trc(1, "     From memory bank "	+ QString::number(mem_bank.at(i)) +
					" and address " + QString::number(address.at(i)) + " the count " + QString::number(count.at(i)));
	}

	QByteArray payload;
	payload.append(epc.size());
	payload.append(epc);

	for(int i = 0; i < mem_bank.size(); i++){
		if (passwd.at(i).size() != 4){
			trc(1, "Read Multiple From Tag - NOK - Data");
			return QrfeGlobal::RES_ERROR;
		}

		payload.append((char) mem_bank.at(i));
		payload.append((char) (address.at(i) >> 8));
		payload.append((char) address.at(i));
		payload.append(passwd.at(i));
		payload.append(count.at(i));
	}

	uchar com1 = RFE_COM1_TAG_FUNCTIONS;
	uchar com2 = RFE_COM2_READ_MULTIPLE_FROM_TAG;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS * 4, "Read Multiple From Tag", response);

	if(res != QrfeGlobal::RES_OK)
		return res;


	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Read Multiple From Tag - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	data.clear();
	uchar indexOffset = 1;
	while(indexOffset != response.size()){
		data.append(response.mid(indexOffset+1, response.at(indexOffset)));
		indexOffset += response.at(indexOffset) + 1;
	}

	trc(1, "Read Multiple From Tag - OK : Read the data from the tag:");
	foreach(QByteArray t, data)
		trc(1, "     -> " + t.toHex());

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::writeToTag(QByteArray epc,
		uchar mem_bank, ushort address, QByteArray passwd, QByteArray data)
{
	trcBytes(1, "Write To Tag - Trying to write to tag " + epc.toHex() + " at bank "
			+ QString::number(mem_bank) + " and address " + QString::number(
			address) + " the bytes ", data);

	if (passwd.size() != 4){
		trc(1, "Write To Tag - NOK - Data");
		return QrfeGlobal::RES_ERROR;
	}

	QByteArray payload;
	payload.append(epc.size());
	payload.append(epc);

	payload.append((char) mem_bank);
	payload.append((char) (address >> 8));
	payload.append((char) address);
	payload.append(passwd);

	payload.append(data.size());
	payload.append(data);

	uchar com1 = RFE_COM1_TAG_FUNCTIONS;
	uchar com2 = RFE_COM2_WRITE_TO_TAG;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS * 4, "Write To Tag", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || (response.at(0) != RFE_RET_SUCCESS && response.at(0) != RFE_RET_RESULT_PENDING) )
	{
		warning("Write To Tag - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	if(response.at(0) == RFE_RET_RESULT_PENDING)
	{
		warning("Write To Tag - OK - Result Pending");

		if (response.size() != 2)
		{
			warning("Write To Tag - NOK - Payl");
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
			m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
			return QrfeGlobal::RES_ERROR;
		}

		QByteArray pendingResp;
		QrfeGlobal::Result pend_res = waitForPendingMessage((uchar)response.at(1), m_MAX_PENDING_WAIT_TIME_IN_MS, "Write To Tag", pendingResp);

		if(pend_res != QrfeGlobal::RES_OK)
		{
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
			return pend_res;
		}

		// set the variable to the new value
		if (pendingResp.size() == 0 || pendingResp.at(0) != RFE_RET_SUCCESS )
		{
			warning("Write To Tag - NOK - Payl");
			warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex() + " | Recvd: " + pendingResp.toHex());
			m_lastReturnCode = (eRFE_RET_VALUE) (uchar) pendingResp.at(0);
			return QrfeGlobal::RES_ERROR;
		}
	}

	trc(1, "Write To Tag - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::lockTag(QByteArray epc, uchar mode,
		uchar memory, QByteArray password)
{
	trc(1, "Lock Tag - Trying to lock tag " + epc.toHex() + " with the mode "
			+ QString::number(mode) + " the memory " + QString::number(memory));

	if (password.size() != 4){
		error("Lock Tag - NOK - Data");
		return QrfeGlobal::RES_ERROR;
	}

	QByteArray payload;
	payload.append(epc.size());
	payload.append(epc);

	payload.append((char) mode);
	payload.append((char) memory);
	payload.append(password);

	uchar com1 = RFE_COM1_TAG_FUNCTIONS;
	uchar com2 = RFE_COM2_LOCK_TAG;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS * 2, "Lock Tag", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Lock Tag - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Lock Tag - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::killTag(QByteArray epc, uchar rfu,
		uchar recom, QByteArray password)
{
	trc(1, "Kill Tag - Trying to kill tag " + epc.toHex() + " with the rfu "
			+ QString::number(rfu) + " the recom " + QString::number(recom));

	if (password.size() != 4){
		error("Kill Tag - NOK - Data");
		return QrfeGlobal::RES_ERROR;
	}

	QByteArray payload;
	payload.append(epc.size());
	payload.append(epc);

	payload.append(((rfu & 0x0F) << 4) | (recom & 0x0F));
	payload.append(password);

	uchar com1 = RFE_COM1_TAG_FUNCTIONS;
	uchar com2 = RFE_COM2_KILL_TAG;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS * 2, "Kill Tag", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Kill Tag - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Kill Tag - OK");

	return QrfeGlobal::RES_OK;

}

QrfeGlobal::Result QrfeProtocolHandlerRFE::customTagCommand(uchar commandId, QByteArray data, QByteArray &resultData)
{
    trc(1, "Custom Tag Command " + QString("%1").arg(commandId, 2, 16, QChar('0')) + " - Trying to execute custom tag command " + QString::number(commandId)
			+ " with data " + data.toHex());

	QByteArray payload;
	payload.append((char) commandId);
	payload.append(data);

	uchar com1 = RFE_COM1_TAG_FUNCTIONS;
	uchar com2 = RFE_COM2_CUSTOM_TAG_COMMAND;

	QByteArray response;
    QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS * 2, "Custom Tag Command" + QString("%1").arg(commandId, 2, 16, QChar('0')), response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
        warning("Custom Tag Command " + QString("%1").arg(commandId, 2, 16, QChar('0')) + " - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	resultData = response.right(response.size() - 1);

    trc(1, "Custom Tag Command " + QString("%1").arg(commandId, 2, 16, QChar('0')) + " - OK : Result data: " + resultData.toHex());

	return QrfeGlobal::RES_OK;

}


QrfeGlobal::Result QrfeProtocolHandlerRFE::acknowledgeStatusBit ( uchar number )
{
	trc(1, "Acknowledge Status Bit - Trying to Acknowledge Status Bit " + QString::number(number));

	QByteArray payload;
	payload.append((char) number);

	uchar com1 = RFE_COM1_ANALYSIS;
	uchar com2 = RFE_COM2_ACKNOWLEDGE_STATUS_BIT;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Acknowledge Status Bit", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Acknowledge Status Bit - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Acknowledge Status Bit - OK");

	return QrfeGlobal::RES_OK;

}

QrfeGlobal::Result QrfeProtocolHandlerRFE::executeAnalysisFunction ( uchar commandId, QByteArray data, QByteArray &resultData )
{
	trc(1, "Exec Analysis Function - Trying to Execute Analysis Function " + QString::number(commandId)
			+ " with data " + data.toHex());

	QByteArray payload;
	payload.append((char) commandId);
	payload.append((char)data.size());
	payload.append(data);

	uchar com1 = RFE_COM1_ANALYSIS;
	uchar com2 = RFE_COM2_EXEC_ANALYSIS_FUNCTION;

	QByteArray response;
    QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS * 2, "Exec Analysis Function", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Execute Analysis Function - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	resultData.clear();
	resultData.append(response.right(response.size() - 2));

	trc(1, "Execute Analysis Function - OK : Result data: " + resultData.toHex());

	return QrfeGlobal::RES_OK;
}



QrfeGlobal::Result QrfeProtocolHandlerRFE::licensePassThrough ( const QByteArray& data )
{
	trc(1, "Pass Through - Trying to send pass through message");

	QByteArray payload;
	payload.append(data);

	// send the command
	return send2ReaderWithoutResponse(RFE_COM1_LICENSE, RFE_COM2_PASS_THROUGH, payload, "Pass Through");
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::licenseStartLicenseProcedure ( )
{
	trc(1, "Start License - Trying to start license procedure");

	uchar com1 = RFE_COM1_LICENSE;
	uchar com2 = RFE_COM2_START_LICENSE;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Start License", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	// set the variable to the new value
	if (response.size() == 0 || response.at(0) != RFE_RET_SUCCESS)
	{
		warning("Start License - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		m_lastReturnCode = (eRFE_RET_VALUE) (uchar) response.at(0);
		return QrfeGlobal::RES_ERROR;
	}

	trc(1, "Start License - OK");

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::licenseGetLicenseInfo ( ulong& startId, ulong& startCount, ulong& nextId, ulong& remainingCount )
{
	trc(1, "Get License Info - Trying to get License Info");

	uchar com1 = RFE_COM1_LICENSE;
	uchar com2 = RFE_COM2_GET_LICENSE_INFO;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get License Info", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 16){
		warning("Get License Info - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	uchar index = 0;

	startId = 0;
	startId |= (((ulong) (uchar) response.at(index++)) << 24);
	startId |= (((ulong) (uchar) response.at(index++)) << 16);
	startId |= (((ulong) (uchar) response.at(index++)) << 8);
	startId |= (ulong) (uchar) response.at(index++);

	startCount = 0;
	startCount |= (((ulong) (uchar) response.at(index++)) << 24);
	startCount |= (((ulong) (uchar) response.at(index++)) << 16);
	startCount |= (((ulong) (uchar) response.at(index++)) << 8);
	startCount |= (ulong) (uchar) response.at(index++);

	nextId = 0;
	nextId |= (((ulong) (uchar) response.at(index++)) << 24);
	nextId |= (((ulong) (uchar) response.at(index++)) << 16);
	nextId |= (((ulong) (uchar) response.at(index++)) << 8);
	nextId |= (ulong) (uchar) response.at(index++);

	remainingCount = 0;
	remainingCount |= (((ulong) (uchar) response.at(index++)) << 24);
	remainingCount |= (((ulong) (uchar) response.at(index++)) << 16);
	remainingCount |= (((ulong) (uchar) response.at(index++)) << 8);
	remainingCount |= (ulong) (uchar) response.at(index++);

	trc(1, "Get License Info - OK : Count = " + QString::number(remainingCount) + "/" + QString::number(startCount) +
								  " StartID = " + QString("%1").arg(startId, 8, 16, QChar('0')) +
								  " NextID = " + QString("%1").arg(nextId, 8, 16, QChar('0')));


	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::licenseGetReportInfo ( ulong& reportCount )
{
	trc(1, "Get Report Info - Trying to get Report Info");

	uchar com1 = RFE_COM1_LICENSE;
	uchar com2 = RFE_COM2_GET_REPORT_INFO;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, m_MAX_WAIT_TIME_IN_MS, "Get Report Info", response);

	if(res != QrfeGlobal::RES_OK)
		return res;

	if (response.size() != 4){
		warning("Get Report Info - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	reportCount = 0;
	reportCount |= (((ulong) (uchar) response.at(0)) << 24);
	reportCount |= (((ulong) (uchar) response.at(1)) << 16);
	reportCount |= (((ulong) (uchar) response.at(2)) << 8);
	reportCount |= (ulong) (uchar) response.at(3);

	trc(1, "Get Report Info - OK : Report Count = " + QString::number(reportCount));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::licenseGetReportData ( ulong reportIndex,  ulong& readerType, ulong& readerId, ulong& flags )
{
	trc(1, "Get Report Data - Trying to get Report Data");

	QByteArray payload;
	payload.resize(4);
	payload[0] = (uchar) (reportIndex >> 24);
	payload[1] = (uchar) (reportIndex >> 16);
	payload[2] = (uchar) (reportIndex >> 8);
	payload[3] = (uchar) (reportIndex);

	uchar com1 = RFE_COM1_LICENSE;
	uchar com2 = RFE_COM2_GET_REPORT_DATA;

	QByteArray response;
	QrfeGlobal::Result res = send2ReaderWaitForResponse(com1, com2, payload, m_MAX_WAIT_TIME_IN_MS, "Get Report Data", response);

	if(res != QrfeGlobal::RES_OK)
		return res;


	if (response.size() != 12){
		warning("Get Report Data - NOK - Payl");
		warning(" Sent: " + m_lastSentMessage.toHex() + " | Recvd: " + response.toHex());
		return QrfeGlobal::RES_ERROR;
	}

	readerId = 0;
	readerId |= (((ulong) (uchar) response.at(0)) << 24);
	readerId |= (((ulong) (uchar) response.at(1)) << 16);
	readerId |= (((ulong) (uchar) response.at(2)) << 8);
	readerId |= (ulong) (uchar) response.at(3);

	readerType = 0;
	readerType |= (((ulong) (uchar) response.at(4)) << 24);
	readerType |= (((ulong) (uchar) response.at(5)) << 16);
	readerType |= (((ulong) (uchar) response.at(6)) << 8);
	readerType |= (ulong) (uchar) response.at(7);

	flags = 0;
	flags |= (((ulong) (uchar) response.at(8)) << 24);
	flags |= (((ulong) (uchar) response.at(9)) << 16);
	flags |= (((ulong) (uchar) response.at(10)) << 8);
	flags |= (ulong) (uchar) response.at(11);

	trc(1, "Get Report Data - OK : Report Data = " + QString("(%1 - %2)").arg(readerId, 8, 16, QChar('0')).arg(readerType, 8, 16, QChar('0')));

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::licenseGetErrorReport ( QList<ulong>& /*errorCounter*/ )
{
	return QrfeGlobal::RES_OK;
}


QrfeGlobal::Result QrfeProtocolHandlerRFE::sendHeartBeat()
{
	trc(4, "Sending Heartbeat");

	// send the command
	return send2ReaderWithoutResponse(RFE_COM1_INTERRUPT, RFE_COM2_HEARTBEAT_INTERRUPT, "Heartbeat");
}



void QrfeProtocolHandlerRFE::blockInterrupts ( bool block )
{
	trc(1, "Blocking interrupts " + QString((block)?"YES":"NO"));
	m_interruptsBlocked = block;
}

bool QrfeProtocolHandlerRFE::interruptsBlocked ( )
{
	return m_interruptsBlocked;
}


void QrfeProtocolHandlerRFE::heartBeatISR(const QByteArray& payload)
{
	if (payload.size() != 1 || payload.at(0) != RFE_RET_SUCCESS)
		return;

	if(!_emitISRsQueued)
		emit heartBeat();
	else
		QMetaObject::invokeMethod(this, "_q_emit_heartBeat", Qt::QueuedConnection);
}

void QrfeProtocolHandlerRFE::cyclicInventoryISR(const QByteArray& payload)
{
    bool ok = false;
    QrfeGlobal::TagEvent event = parseTagEvent(payload, ok);

    if(!ok)
    	return;

	if(!_emitISRsQueued)
		emit cyclicInventory(event);
	else
		QMetaObject::invokeMethod(this, "_q_emit_cyclicInventory", Qt::QueuedConnection, Q_ARG(const QrfeGlobal::TagEvent &, event));
}

void QrfeProtocolHandlerRFE::stateChangedISR(const QByteArray& payload)
{
	if (payload.size() != 1)
		return;

	QrfeGlobal::ReaderState state;
	if ((uchar) payload.at(0) == RFE_STATE_IDLE)
	{
		state = QrfeGlobal::STATE_IDLE;
	}
	else if ((uchar) payload.at(0) == RFE_STATE_SCANNING)
	{
		state = QrfeGlobal::STATE_SCANNING;
	}
	else if ((uchar) payload.at(0) == RFE_STATE_REBOOTING)
	{
		state = QrfeGlobal::STATE_REBOOTING;
	}
	else
		return;

	if(!_emitISRsQueued)
		emit stateChanged(state);
	else
		QMetaObject::invokeMethod(this, "_q_emit_stateChanged", Qt::QueuedConnection, Q_ARG(const int, state));
}

void QrfeProtocolHandlerRFE::statusRegChangedISR ( const QByteArray& payload )
{
	if (payload.size() != 8)
		return;

	qulonglong statusRegister = 0;
	statusRegister |= (((qulonglong) (uchar) payload.at(0)) << 56);
	statusRegister |= (((qulonglong) (uchar) payload.at(1)) << 48);
	statusRegister |= (((qulonglong) (uchar) payload.at(2)) << 40);
	statusRegister |= (((qulonglong) (uchar) payload.at(3)) << 32);
	statusRegister |= (((qulonglong) (uchar) payload.at(4)) << 24);
	statusRegister |= (((qulonglong) (uchar) payload.at(5)) << 16);
	statusRegister |= (((qulonglong) (uchar) payload.at(6)) << 8);
	statusRegister |= (qulonglong) (uchar) payload.at(7);

	if(!_emitISRsQueued)
		emit statusRegisterChanged(statusRegister);
	else
		QMetaObject::invokeMethod(this, "_q_emit_statusRegisterChanged", Qt::QueuedConnection, Q_ARG(const qulonglong, statusRegister));
}

void QrfeProtocolHandlerRFE::bootUpFinishedISR ( const QByteArray& payload )
{
	if (payload.size() != 1)
		return;

	if(!_emitISRsQueued)
		emit bootUpFinished((bool)payload.at(0));
	else
		QMetaObject::invokeMethod(this, "_q_emit_bootUpFinished", Qt::QueuedConnection, Q_ARG(const bool, (bool)payload.at(0)));
}

void QrfeProtocolHandlerRFE::notificationISR ( const QByteArray& payload )
{
	if(!_emitISRsQueued)
		emit notification((uchar)payload.at(0), payload.right(payload.size()-1));
	else
		QMetaObject::invokeMethod(this, "_q_emit_notification", Qt::QueuedConnection, Q_ARG(const uchar, (uchar)payload.at(0)), Q_ARG(const QByteArray&, payload.right(payload.size()-1)));
}

void QrfeProtocolHandlerRFE::applicationISR ( const QByteArray& payload )
{
	if(!_emitISRsQueued)
		emit applicationInterrupt(payload);
	else
		QMetaObject::invokeMethod(this, "_q_emit_applicationInterrupt", Qt::QueuedConnection,Q_ARG(const QByteArray&, payload));
}

void QrfeProtocolHandlerRFE::operationResultISR ( const QByteArray& payload )
{
	trc(1, "Operation Result");

	if (payload.size() < 2)
            return;

	uchar id = (uchar)payload.at(0);
	trc(1, "Operation Result for id " + QString::number(id));

	m_pendingResultsQueue.enqueMessage(id, payload.right(payload.size()-1));
}

void QrfeProtocolHandlerRFE::gpioValuesChangedISR ( const QByteArray& payload )
{
	if (payload.size() != 4)
		return;

	ulong gpioValues = 0;
	gpioValues |= (((ulong) (uchar) payload.at(0)) << 24);
	gpioValues |= (((ulong) (uchar) payload.at(1)) << 16);
	gpioValues |= (((ulong) (uchar) payload.at(2)) << 8);
	gpioValues |= (ulong) (uchar) payload.at(3);

	if(!_emitISRsQueued)
		emit gpioValuesChanged(gpioValues);
	else
		QMetaObject::invokeMethod(this, "_q_emit_gpioValuesChanged", Qt::QueuedConnection, Q_ARG(const ulong, gpioValues));
}

void QrfeProtocolHandlerRFE::licensePassThroughISR ( const QByteArray& payload )
{
	if(!_emitISRsQueued)
		emit licenseDataReceived(payload);
	else
		QMetaObject::invokeMethod(this, "_q_emit_licenseDataReceived", Qt::QueuedConnection, Q_ARG(const QByteArray&, payload));
}

void QrfeProtocolHandlerRFE::licenseResultISR ( const QByteArray& payload )
{
	if (payload.size() != 1)
		return;

	if(!_emitISRsQueued)
		emit licenseResult( (bool) payload.at(0) );
	else
		QMetaObject::invokeMethod(this, "_q_emit_licenseResult", Qt::QueuedConnection, Q_ARG(bool, (bool) payload.at(0)));
}



void QrfeProtocolHandlerRFE::_q_emit_heartBeat()
{
	emit heartBeat();
}

void QrfeProtocolHandlerRFE::_q_emit_cyclicInventory(const QrfeGlobal::TagEvent &tagInfo)
{
	emit cyclicInventory(tagInfo);
}

void QrfeProtocolHandlerRFE::_q_emit_stateChanged(const int newState)
{
	emit stateChanged(newState);
}

void QrfeProtocolHandlerRFE::_q_emit_statusRegisterChanged(const qulonglong statusRegister)
{
	emit statusRegisterChanged(statusRegister);
}

void QrfeProtocolHandlerRFE::_q_emit_bootUpFinished(const bool finished)
{
	emit bootUpFinished(finished);
}

void QrfeProtocolHandlerRFE::_q_emit_notification(const uchar id, const QByteArray& data)
{
	emit notification(id, data);
}

void QrfeProtocolHandlerRFE::_q_emit_applicationInterrupt(const QByteArray& data)
{
	emit applicationInterrupt(data);
}

void QrfeProtocolHandlerRFE::_q_emit_gpioValuesChanged( const ulong gpioValues )
{
	emit gpioValuesChanged(gpioValues);
}


void QrfeProtocolHandlerRFE::_q_emit_licenseDataReceived(const QByteArray& data)
{
	emit licenseDataReceived(data);
}

void QrfeProtocolHandlerRFE::_q_emit_licenseResult ( bool res )
{
	emit licenseResult(res);
}



QrfeGlobal::Result QrfeProtocolHandlerRFE::send2Reader(uchar com1, uchar com2)
{
	return send2Reader(com1, com2, QByteArray());
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::send2Reader(uchar com1, uchar com2, const QByteArray& payload)
{
	if (m_deviceRemoved)
		return QrfeGlobal::RES_COMMERROR;

	m_messageQueue.clearMessage(messageId(com1, com2));

	QByteArray msg;
	msg.resize(8);
	msg[0] = RFE_START_BYTE_1;
	msg[1] = RFE_START_BYTE_2;
	msg[2] = RFE_START_BYTE_3;
	msg[3] = RFE_COMMAND_START_BYTE;
	msg[4] = com1;
	msg[5] = com2;
	msg[6] = RFE_LENGTH_START_BYTE;
	msg[7] = payload.size();

	if (payload.size() > 0)
	{
		msg.append(RFE_PAYLOAD_START_BYTE);
		msg.append(payload);
	}

	msg.append(RFE_CHECKSUM_START_BYTE);
	msg.append(QrfeCRC::calcXORCS(msg));

	m_sentMessageMutex.lock();
	m_lastSentMessage = msg;
	m_sentMessage[messageId(com1, com2)] = msg;
	m_sentMessageMutex.unlock();

	trc(5, "Sending: " + msg.toHex());

	if(!send(msg))
		return QrfeGlobal::RES_ERROR;

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::waitForResponse(uchar com1, uchar com2, uint waitTime, const QString& funcName, QByteArray& response)
{
	// wait for either the flag or a timeout
	bool result = false;
	response = m_messageQueue.waitForMessage(messageId(com1, com2), waitTime, &result);
	if (!result){
		error(funcName + " - NOK - Resp | Sent: " + m_lastSentMessage.toHex());
		return QrfeGlobal::RES_NORESPONSE;
	}

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::waitForPendingMessage(uchar id, uint waitTime, const QString& funcName, QByteArray& response)
{
	// wait for either the flag or a timeout
	bool result = false;
	response = m_pendingResultsQueue.waitForMessage(id, waitTime, &result);
	if (!result){
		error(funcName + " - NOK - Pending Resp | Sent: " + m_lastSentMessage.toHex());
		return QrfeGlobal::RES_NORESPONSE;
	}

	return QrfeGlobal::RES_OK;
}


QrfeGlobal::Result QrfeProtocolHandlerRFE::send2ReaderWaitForResponse(uchar com1, uchar com2, uint waitTime, const QString& funcName, QByteArray& response)
{
	return send2ReaderWaitForResponse(com1, com2, QByteArray(), waitTime, funcName, response);
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::send2ReaderWaitForResponse(uchar com1, uchar com2, const QByteArray& payload, uint waitTime, const QString& funcName, QByteArray& response)
{
	// TODO: Test without mutex lock
	//QrfeMutexLocker locker(&m_mutex, funcName);

	// reset the flag
	m_lastReturnCode = RFE_RET_SUCCESS;

	// send the command
	QrfeGlobal::Result res = send2Reader(com1, com2, payload);
	if (res != QrfeGlobal::RES_OK)
	{
		error(funcName + " - NOK - Send");
		return res;
	}

	// wait for either the flag or a timeout
	bool result = false;
	response = m_messageQueue.waitForMessage(messageId(com1, com2), waitTime, &result);
	if (!result){
		error(funcName + " - NOK - Resp | Sent: " + m_lastSentMessage.toHex());
		return QrfeGlobal::RES_NORESPONSE;
	}

	return QrfeGlobal::RES_OK;
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::send2ReaderWithoutResponse(uchar com1, uchar com2, const QString& funcName)
{
	return send2ReaderWithoutResponse(com1, com2, QByteArray(), funcName);
}

QrfeGlobal::Result QrfeProtocolHandlerRFE::send2ReaderWithoutResponse(uchar com1, uchar com2, const QByteArray& payload, const QString& funcName)
{
	// TODO: Test without mutex lock
	//QrfeMutexLocker locker(&m_mutex, funcName);

	// reset the flag
	m_lastReturnCode = RFE_RET_SUCCESS;

	// send the command
	QrfeGlobal::Result res = send2Reader(com1, com2, payload);
	if (res != QrfeGlobal::RES_OK)
	{
		error(funcName + " - NOK - Send");
		return res;
	}

	return QrfeGlobal::RES_OK;
}

void QrfeProtocolHandlerRFE::deviceWasRemoved()
{
	QrfeProtocolHandler::deviceWasRemoved();
}

/*	void computeData(const QByteArray)
 Receives data and check whether the correct reader has sent. After then
 data have to forwarding to
 */
void QrfeProtocolHandlerRFE::computeData(const QByteArray& data)
{
	if (data.size() <= 0)
		return;

	foreach(uchar c, data)
		{
			switch (m_state)
			{
			case START_BYTE_1:
				if (c == RFE_START_BYTE_1)
				{
					m_state = START_BYTE_2;
					m_singleMsg.clear();
					m_payloadIndex = 0;
					m_payloadLength = 0;
				}
				break;

			case START_BYTE_2:
				if (c == RFE_START_BYTE_2)
					m_state = START_BYTE_3;
				else{
					parserError(m_state, m_singleMsg, m_command1, m_command2);
					m_state = START_BYTE_1;
				}
				break;

			case START_BYTE_3:
				if (c == RFE_START_BYTE_3)
					m_state = COMMAND_START_BYTE;
				else{
					parserError(m_state, m_singleMsg, m_command1, m_command2);
					m_state = START_BYTE_1;
				}
				break;

			case COMMAND_START_BYTE:
				if (c == RFE_COMMAND_START_BYTE)
					m_state = COMMAND_1;
				else{
					parserError(m_state, m_singleMsg, m_command1, m_command2);
					m_state = START_BYTE_1;
				}
				break;

			case COMMAND_1:
				m_command1 = c;
				m_state = COMMAND_2;
				break;

			case COMMAND_2:
				m_command2 = c;
				m_state = LENGTH_START_BYTE;
				break;

			case LENGTH_START_BYTE:
				if (c == RFE_LENGTH_START_BYTE)
					m_state = LENGTH;
				else{
					parserError(m_state, m_singleMsg, m_command1, m_command2);
					m_state = START_BYTE_1;
				}
				break;

			case LENGTH:
				m_payloadLength = c;
				m_payloadIndex = 0;
				if (m_payloadLength == 0)
					m_state = CHECKSUM_START_BYTE;
				else
					m_state = PAYLOAD_START_BYTE;
				break;

			case PAYLOAD_START_BYTE:
				if (c == RFE_PAYLOAD_START_BYTE)
					m_state = PAYLOAD;
				else{
					parserError(m_state, m_singleMsg, m_command1, m_command2);
					m_state = START_BYTE_1;
				}
				break;

			case PAYLOAD:
				if (++m_payloadIndex >= m_payloadLength)
					m_state = CHECKSUM_START_BYTE;

				break;

			case CHECKSUM_START_BYTE:
				if (c == RFE_CHECKSUM_START_BYTE)
					m_state = CHECKSUM;
				else{
					parserError(m_state, m_singleMsg, m_command1, m_command2);
					m_state = START_BYTE_1;
				}
				break;

			case CHECKSUM:
			{
				m_state = START_BYTE_1;
				if (c != QrfeCRC::calcXORCS(m_singleMsg))
				{
					parserError(m_state, m_singleMsg, m_command1, m_command2);
					error("CHECKSUM NOK!!");
					break;
				}

				trc(5, "Received " + m_singleMsg.toHex());

				computeMessage(m_singleMsg);

				break;
			}

			}
			m_singleMsg.append(c);
		}

}

/*	void computeMessage(const QByteArray)
 Processed received data und and check whether the data are correct
 */
void QrfeProtocolHandlerRFE::computeMessage(const QByteArray& msg)
{
	uchar command1 = msg[RFE_COMMAND_INDEX_1];
	uchar command2 = msg[RFE_COMMAND_INDEX_2];

	QByteArray data = msg.mid(RFE_PAYLOAD_INDEX, msg[RFE_LENGTH_INDEX]);

	switch (command1)
	{
	case RFE_COM1_INTERRUPT: // Interrupts
		switch (command2)
		{
		case RFE_COM2_HEARTBEAT_INTERRUPT:
			heartBeatISR(data);
			break;
		case RFE_COM2_INVENTORY_CYCLIC_INTERRUPT:
			if(!m_interruptsBlocked)
				cyclicInventoryISR(data);
			break;
		case RFE_COM2_STATE_CHANGED_INTERRUPT:
			if(!m_interruptsBlocked)
				stateChangedISR(data);
			break;
		case RFE_COM2_STATUS_REG_CHANGED_INTERRUPT:
			if(!m_interruptsBlocked)
				statusRegChangedISR(data);
			break;
		case RFE_COM2_BOOT_UP_FINISHED_INTERRUPT:
			if(!m_interruptsBlocked)
				bootUpFinishedISR(data);
			break;
		case RFE_COM2_NOTIFICATION_INTERRUPT:
			if(!m_interruptsBlocked)
				notificationISR(data);
			break;
		case RFE_COM2_APPLICATION_INTERRUPT:
			if(!m_interruptsBlocked)
				applicationISR(data);
			break;
		case RFE_COM2_OPERATION_RESULT_INTERRUPT:
			operationResultISR(data);
			break;
		case RFE_COM2_GPIO_PINS_CHANGED:
			gpioValuesChangedISR(data);
			break;
		default:
			m_messageQueue.enqueMessage(messageId(command1, command2), data);
			break;
		}
		break;
	case RFE_COM1_LICENSE:
		switch(command2)
		{
		case RFE_COM2_PASS_THROUGH:
			licensePassThroughISR(data);
			break;
		case RFE_COM2_LICENSE_RESULT_INTERRUPT:
			licenseResultISR(data);
			break;
		default:
			m_messageQueue.enqueMessage(messageId(command1, command2), data);
			break;
		}
		break;
	default:
		m_messageQueue.enqueMessage(messageId(command1, command2), data);
		break;
	}
}


QrfeGlobal::TagEvent QrfeProtocolHandlerRFE::parseTagEvent(const QByteArray& payload, bool& ok)
{
	typedef enum
	{
		START,
		TAGID_LENGTH,
		TAGID,
		RSSI,
		MEM_BANK,
		MEM_ADDR1,
		MEM_ADDR2,
		MEM_SIZE,
		MEM_DATA,
		TRIGGER,
		ANTENNA,
		FREQUENCY,
		HANDLE,
		STATE,
		BATTERY,
		PC,
        MESSAGE_ID,
        RN16,
        NXP_BRAND_ID,
        APPLICATION_SIZE,
		APPLICATION_DATA
	} INVENTORY_STATE;

	ok = false;

	INVENTORY_STATE state = START;

	QrfeGlobal::TagEvent 	event;
	event.hasRSSI 			= false;
	event.hasReadFrequency 	= false;
	event.hasMemory 		= false;
	event.hasTrigger 		= false;
	event.hasAntenna		= false;
	event.hasHandle			= false;
	event.hasState			= false;
	event.hasBattery		= false;
	event.hasPC				= false;
    event.hasMessageID		= false;
    event.hasRN16   		= false;
    event.hasNxpBrandId     = false;
    event.hasApplicationInfo= false;

	uchar tagIdLength = 0;
	uchar mem_size = 0;
	QByteArray mem_data;
	QByteArray frequency_data;
	QByteArray state_data;
	uchar applInfoSize = 0;

	for (int i = 0; i < payload.size(); i++)
	{
		uchar c = payload.at(i);
		switch (state)
		{
		case START:
            if (c == RFE_TAG_ID_START_BYTE)
				state = TAGID_LENGTH;
			else if (c == RFE_RSSI_START_BYTE)
				state = RSSI;
			else if (c == RFE_USERMEM_START_BYTE)
				state = MEM_BANK;
			else if (c == RFE_TRIGGER_START_BYTE)
				state = TRIGGER;
			else if (c == RFE_ANTENNA_ID_START_BYTE)
				state = ANTENNA;
			else if (c == RFE_READ_FREQU_START_BYTE)
				state = FREQUENCY;
			else if (c == RFE_GEN2_HANDLE_START_BYTE)
				state = HANDLE;
			else if (c == RFE_STATE_START_BYTE)
				state = STATE;
			else if (c == RFE_BATTERY_START_BYTE)
				state = BATTERY;
            else if (c == RFE_GEN2_PC_START_BYTE)
                state = PC;
            else if (c == RFE_GEN2_RN16_START_BYTE)
                state = RN16;
            else if (c == RFE_MESSAGE_ID_START_BYTE)
				state = MESSAGE_ID;
            else if (c == RFE_NXP_BRAND_ID_START_BYTE)
                state = NXP_BRAND_ID;
            else if (c == RFE_APPLICATION_START_BYTE)
					state = APPLICATION_SIZE;
			else
				state = START;
			break;

		case TAGID_LENGTH:
			tagIdLength = c;
			if(c == 0)
				state = START;
			else
				state = TAGID;
			break;

		case TAGID:
			event.tagId.append(c);
			if (event.tagId.size() == tagIdLength)
				state = START;
			break;

		case RSSI:
			event.rssi.append(c);
			if (event.rssi.size() == 2){
				state = START;
				event.hasRSSI = true;
			}
			break;

		case MEM_BANK:
			event.memBank = c;
			state = MEM_ADDR1;
			break;

		case MEM_ADDR1:
			event.memAddr = 0;
			event.memAddr += ((ushort) c) << 8;
			state = MEM_ADDR2;
			break;

		case MEM_ADDR2:
			event.memAddr += c;
			state = MEM_SIZE;
			break;

		case MEM_SIZE:
			mem_size = c;
			state = MEM_DATA;
			break;

		case MEM_DATA:
			event.memData.append(c);
			if (event.memData.size() == mem_size){
				state = START;
				event.hasMemory = true;
			}
			break;

		case TRIGGER:
			event.trigger = (eRFE_TRIGGER_SOURCE) c;
			event.hasTrigger = true;
			state = START;
			break;

		case ANTENNA:
			event.antennaId = c;
			event.hasAntenna = true;
			state = START;
			break;

		case FREQUENCY:
			frequency_data.append(c);
			if (frequency_data.size() == 3){
				event.readFrequency = 0;
				event.readFrequency |= (((ulong) (uchar) frequency_data.at(0)) << 16);
				event.readFrequency |= (((ulong) (uchar) frequency_data.at(1)) << 8);
				event.readFrequency |=   (ulong) (uchar) frequency_data.at(2);
				event.hasReadFrequency = true;
				state = START;
			}
			break;

		case HANDLE:
			event.handle.append(c);
			if (event.handle.size() == 2){
				state = START;
				event.hasHandle = true;
			}
			break;

		case STATE:
			state_data.append(c);
			if (state_data.size() == 2){
				event.state = 0;
				event.state |= (((ushort) (uchar) state_data.at(0)) << 8);
				event.state |=   (ushort) (uchar) state_data.at(1);
				state = START;
				event.hasState = true;
			}
			break;

		case BATTERY:
			event.battery = c;
			event.hasBattery = true;
			state = START;
			break;

		case PC:
			event.pc.append(c);
			if (event.pc.size() == 2){
				state = START;
				event.hasPC = true;
			}
			break;

		case MESSAGE_ID:
			event.messageID = c;
			event.hasMessageID = true;
			state = START;
			break;

        case RN16:
            event.rn16.append(c);
            if (event.rn16.size() == 2){
                state = START;
                event.hasRN16 = true;
            }
            break;

        case NXP_BRAND_ID:
            event.nxpBrandId.append(c);
            if (event.nxpBrandId.size() == 2){
                state = START;
                event.hasNxpBrandId = true;
            }
            break;

		case APPLICATION_SIZE:
			event.hasApplicationInfo = true;
			applInfoSize = c;
			state = APPLICATION_DATA;
			break;

		case APPLICATION_DATA:
			event.applicationInfo.append(c);
			if(event.applicationInfo.size() == applInfoSize)
			{
				event.hasApplicationInfo = true;
				state = START;
			}
			state = APPLICATION_DATA;
			break;

		}

	}

    if (event.tagId.size() != tagIdLength)
        return event;

    ok = true;

    return event;
}

int QrfeProtocolHandlerRFE::messageId(uchar command1, uchar command2)
{
	return (((ushort)command1) << 8) | command2;
}

void QrfeProtocolHandlerRFE::parserError ( eMessageState state, QByteArray msg, uchar command1, uchar command2 )
{
	error("Got a parser error in state " + state2String(state) + " MSG: (" + QString::number(msg.size()) + ")  " + msg.toHex());
	if(state > LENGTH_START_BYTE)
	{
		if(m_sentMessage.contains(messageId(command1, command2)))
		{
			m_sentMessageMutex.lock();
			QByteArray msg = m_sentMessage.value(messageId(command1, command2));
			m_sentMessage.remove(messageId(command1, command2));
			m_sentMessageMutex.unlock();
			warning("Trying to resend the last message of type " + QString("%1-%2").arg(command1, 2, 16, QChar('0')).arg(command2, 2, 16, QChar('0')) + "  " + msg.toHex());
			send(msg);
		}
	}
}

QString QrfeProtocolHandlerRFE::state2String( eMessageState state )
{
	switch (state)
	{
	case START_BYTE_1:
		return "START_BYTE_1";
	case START_BYTE_2:
		return "START_BYTE_2";
	case START_BYTE_3:
		return "START_BYTE_3";
	case COMMAND_START_BYTE:
		return "COMMAND_START_BYTE";
	case COMMAND_1:
		return "COMMAND_1";
	case COMMAND_2:
		return "COMMAND_2";
	case LENGTH_START_BYTE:
		return "LENGTH_START_BYTE";
	case LENGTH:
		return "LENGTH";
	case PAYLOAD_START_BYTE:
		return "PAYLOAD_START_BYTE";
	case PAYLOAD:
		return "PAYLOAD";
	case CHECKSUM_START_BYTE:
		return "CHECKSUM_START_BYTE";
	case CHECKSUM:
		return "CHECKSUM";
	default:
		return "UNKNOWN";
	}
}
