mercury-api-0.1.0.0: cbits/api/serial_reader_l3.c
/**
* @file serial_reader_l3.c
* @brief Mercury API - serial reader low level implementation
* @author Nathan Williams
* @date 11/2/2009
*/
/*
* Copyright (c) 2009 ThingMagic, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tm_reader.h"
#include "serial_reader_imp.h"
#include "tmr_utils.h"
#ifndef BARE_METAL
bool isSecureAccessEnabled;
#endif
void
notify_read_listeners(TMR_Reader *reader, TMR_TagReadData *trd);
#ifdef TMR_ENABLE_SERIAL_READER
static TMR_Status filterbytes(TMR_TagProtocol protocol,
const TMR_TagFilter *filter,
uint8_t *option, uint8_t *i, uint8_t *msg,
uint32_t accessPassword, bool usePassword);
TMR_Status
TMR_SR_sendBytes(TMR_Reader *reader, uint8_t len, uint8_t *data, uint32_t timeoutMs);
/*
* ThingMagic-mutated CRC used for messages.
* Notably, not a CCITT CRC-16, though it looks close.
*/
static uint16_t crctable[] =
{
0x0000, 0x1021, 0x2042, 0x3063,
0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b,
0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
};
static uint16_t
tm_crc(uint8_t *u8Buf, uint8_t len)
{
uint16_t crc;
int i;
crc = 0xffff;
for (i = 0; i < len ; i++)
{
crc = ((crc << 4) | (u8Buf[i] >> 4)) ^ crctable[crc >> 12];
crc = ((crc << 4) | (u8Buf[i] & 0xf)) ^ crctable[crc >> 12];
}
return crc;
}
/**
* Send a byte string
*
* @param reader The reader
* @param[in] len Number of bytes to send
* @param[in] data Bytes to send, with length in byte 1. Byte 0 is reserved for the SOF character, and two characters at the end are reserved for the CRC.
* @param timeoutMs Timeout value.
*/
TMR_Status
TMR_SR_sendBytes(TMR_Reader *reader, uint8_t len, uint8_t *data, uint32_t timeoutMs)
{
TMR_SR_SerialTransport *transport;
TMR_Status ret;
transport = &reader->u.serialReader.transport;
if (NULL != reader->transportListeners)
{
TMR__notifyTransportListeners(reader, true, len, data, timeoutMs);
}
ret = transport->sendBytes(transport, len, data, timeoutMs);
return ret;
}
/**
* Send a message to the reader
*
* @param reader The reader
* @param[in] data Message to send, with length in byte 1. Byte 0 is reserved for the SOF character, and two characters at the end are reserved for the CRC.
* @param[out] opcode Opcode sent with message (pass this value to receiveMessage to match against response)
* @param timeoutMs Timeout value.
*/
TMR_Status
TMR_SR_sendMessage(TMR_Reader *reader, uint8_t *data, uint8_t *opcode, uint32_t timeoutMs)
{
TMR_SR_SerialReader *sr;
TMR_Status ret;
uint16_t crc;
uint8_t len;
uint8_t j;
//uint8_t byteLen;
sr = &reader->u.serialReader;
timeoutMs += sr->transportTimeout;
/* if (reader->u.serialReader.crcEnabled)
{
byteLen = 5;
}
else
{
byteLen = 3;
}*/
/* Wake up processor from deep sleep. Tickle the RS-232 line, then
* wait a fixed delay while the processor spins up communications again. */
if (sr->supportsPreamble && ((sr->powerMode == TMR_SR_POWER_MODE_INVALID) ||
(sr->powerMode == TMR_SR_POWER_MODE_SLEEP)) )
{
uint8_t flushBytes[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};
TMR_SR_sendBytes(reader, sizeof(flushBytes)/sizeof(uint8_t), flushBytes, timeoutMs);
{
uint32_t bytesper100ms;
uint32_t bytesSent;
/* Calculate fixed delay in terms of byte-lengths at current speed */
/* @todo Optimize delay length. This value (100 bytes at 9600bps) is taken
* directly from arbser, which was itself using a hastily-chosen value. */
bytesper100ms = sr->baudRate / 50;
for (bytesSent=0; bytesSent<bytesper100ms;
bytesSent += (sizeof(flushBytes)/sizeof(uint8_t)))
{
TMR_SR_sendBytes(reader, sizeof(flushBytes)/sizeof(uint8_t), flushBytes, timeoutMs);
}
}
}
/* Layout of message in data array:
* [0] [1] [2] [3] [4] ... [LEN+2] [LEN+3] [LEN+4]
* FF LEN OP xx xx ... xx CRCHI CRCLO
*/
data[0] = 0xff;
len = data[1];
*opcode = data[2];
if (isContinuousReadParamSupported(reader))
{
for (j = 0; j <= len; j++)
{
reader->paramMessage[j] = data[2 + j];
}
data[1] = 5 + len;
data[2] = 0x2f;
data[3] = 0x00;
data[4] = 0x00;
data[5] = 0x04;
data[6] = len;
for (j = 0; j <= len ; j++)
{
data[7 + j] = reader->paramMessage[j];
}
len = data[1];
reader->paramWait = true;
}
// if (reader->u.serialReader.crcEnabled)
{
crc = tm_crc(&data[1], len + 2);
data[len + 3] = crc >> 8;
data[len + 4] = crc & 0xff;
}
ret = TMR_SR_sendBytes(reader, len+5, data, timeoutMs);
return ret;
}
bool
isContinuousReadParamSupported(TMR_Reader *reader)
{
uint16_t i;
uint8_t *readerVersion = reader->u.serialReader.versionInfo.fwVersion ;
uint8_t checkVersion[4];
if (reader->hasContinuousReadStarted == false || reader->continuousReading == false)
return false;
switch (reader->u.serialReader.versionInfo.hardware[0])
{
case TMR_SR_MODEL_M6E:
case TMR_SR_MODEL_M6E_I:
checkVersion[0] = 0x01; checkVersion[1] = 0x21; checkVersion[2] = 0x01; checkVersion[3] = 0x19;
break;
case TMR_SR_MODEL_MICRO:
checkVersion[0] = 0x01; checkVersion[1] = 0x09; checkVersion[2] = 0x00; checkVersion[3] = 0x14;
break;
case TMR_SR_MODEL_M6E_NANO:
checkVersion[0] = 0x01; checkVersion[1] = 0x07; checkVersion[2] = 0x00; checkVersion[3] = 0x0E;
break;
default:
checkVersion[0] = 0xFF; checkVersion[1] = 0xFF; checkVersion[2] = 0xFF; checkVersion[3] = 0xFF;
}
for (i = 0; i < 4; i++)
{
if (readerVersion[i] < checkVersion[i])
{
return false;
}
}
return true;
}
/**
* Receive a response.
*
* @param reader The reader
* @param[in] data Message to send, with length in byte 1. Byte 0 is reserved for the SOF character, and two characters at the end are reserved for the CRC.
* @param[out] data Message received.
* @param opcode Opcode that was sent with message that elicited this response, to be matched against incoming response opcode.
* @param timeoutMs Timeout value.
*/
TMR_Status
TMR_SR_receiveMessage(TMR_Reader *reader, uint8_t *data, uint8_t opcode, uint32_t timeoutMs)
{
TMR_Status ret;
uint16_t crc, status;
uint8_t len,headerOffset;
uint8_t receiveBytesLen;
uint32_t inlen;
int i;
TMR_SR_SerialTransport *transport;
uint8_t retryCount = 0;
transport = &reader->u.serialReader.transport;
timeoutMs += reader->u.serialReader.transportTimeout;
/**
* Initialize the receive bytes length based on
* sr->expectCRC option
**/
if (reader->u.serialReader.crcEnabled)
{
receiveBytesLen = 7;
}
else
{
receiveBytesLen = 5;
}
headerOffset = 0;
retryHeader:
inlen = 0;
retryCount++;
ret = transport->receiveBytes(transport, receiveBytesLen - headerOffset, &inlen, data + headerOffset, timeoutMs);
if (TMR_SUCCESS != ret)
{
/* @todo Figure out how many bytes were actually obtained in a failed receive */
TMR__notifyTransportListeners(reader, false, inlen, data, timeoutMs);
return ret;
}
if (data[0] != (uint8_t)0xFF)
{
for (i = 1; i < receiveBytesLen; i++)
{
if (data[i] == 0xFF)
{
/* An SOH has been found, so we won't enter the "NO SOH" section of code again */
headerOffset = receiveBytesLen - i;
memmove(data, data + i, headerOffset);
goto retryHeader;
}
}
if (retryCount < 20)
{
/* Retry to get SOH */
goto retryHeader;
}
return TMR_ERROR_TIMEOUT;
}
/* After this point, we have the the bare minimum (5 or 7) of bytes in the buffer */
/* Layout of response in data array:
* [0] [1] [2] [3] [4] [5] [6] ... [LEN+4] [LEN+5] [LEN+6]
* FF LEN OP STATUSHI STATUSLO xx xx ... xx CRCHI CRCLO
*/
len = data[1];
if (0 == len)
{
inlen = 0;
}
else if ((TMR_SR_MAX_PACKET_SIZE - receiveBytesLen) < len)
{
/**
* packet data size is overflowing the buffer size. This could be a
* corrupted packet. Discard it and move on. Return back with TMR_ERROR_TOO_BIG
* error.
**/
return TMR_ERROR_TOO_BIG;
}
else
{
ret = transport->receiveBytes(transport, len, &inlen, data + receiveBytesLen, timeoutMs);
}
if (NULL != reader->transportListeners)
{
TMR__notifyTransportListeners(reader, false, inlen + receiveBytesLen, data, timeoutMs);
}
if (TMR_SUCCESS != ret)
{
/* before we can actually process the message, we have to properly receive the message */
return ret;
}
/**
* Calculate the CRC only if expectCRC option
* is enabled
**/
if (reader->u.serialReader.crcEnabled)
{
crc = tm_crc(&data[1], len + 4);
if ((data[len + 5] != (crc >> 8)) ||
(data[len + 6] != (crc & 0xff)))
{
return TMR_ERROR_CRC_ERROR;
}
}
if ((data[2] != opcode) && ((data[2] != 0x2F) || (!reader->continuousReading)))
{
if(data[2] == 0x9D)
{
return TMR_ERROR_AUTOREAD_ENABLED;
}
/* We got a response for a different command than the one we
* sent. This usually means we received the boot-time message from
* a M6e, and thus that the device was rebooted somewhere between
* the previous command and this one. Report this as a problem.
*/
return TMR_ERROR_DEVICE_RESET;
}
status = GETU16AT(data, 3);
if (status != 0)
{
ret = TMR_ERROR_CODE(status);
if (ret == TMR_ERROR_TM_ASSERT_FAILED)
{
uint32_t line;
uint8_t *assert = (uint8_t *) (data + 5);
memset(reader->u.serialReader.errMsg, 0 ,TMR_SR_MAX_PACKET_SIZE);
line = GETU32AT(assert, 0);
sprintf(reader->u.serialReader.errMsg, "Assertion failed at line %"PRId32" in file ", line);
memcpy(reader->u.serialReader.errMsg + strlen(reader->u.serialReader.errMsg), assert + 4, len - 4);
}
}
return ret;
}
/**
* Send a message and receive a response.
*
* @param reader The reader
* @param[in] data Message to send, with length in byte 1. Byte 0 is reserved for the SOF character, and two characters at the end are reserved for the CRC.
* @param[out] data Message received.
* @param timeoutMs Timeout value.
*/
TMR_Status
TMR_SR_sendTimeout(TMR_Reader *reader, uint8_t *data, uint32_t timeoutMs)
{
TMR_Status ret;
uint8_t opcode;
ret = TMR_SR_sendMessage(reader, data, &opcode, timeoutMs);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (isContinuousReadParamSupported(reader))
{
while(reader->paramWait)
{
#ifdef SINGLE_THREAD_ASYNC_READ
TMR_TagReadData trd;
ret = TMR_hasMoreTags(reader);
if (TMR_SUCCESS == ret)
{
TMR_getNextTag(reader, &trd);
notify_read_listeners(reader, &trd);
}
#endif
}
reader->paramWait = false;
memcpy(data , &reader->paramMessage[5], reader->paramMessage[1] * sizeof(uint8_t));
data[0] = 0xFF;
ret = (TMR_Status) GETU16AT(&reader->paramMessage[0], 3);
if (TMR_SUCCESS != ret)
{
return TMR_ERROR_CODE(ret);
}
ret = (TMR_Status) GETU16AT(data, 3);
if (TMR_SUCCESS != ret)
{
return TMR_ERROR_CODE(ret);
}
}
else
{
ret = TMR_SR_receiveMessage(reader, data, opcode, timeoutMs);
if (TMR_SUCCESS != ret)
{
return ret;
}
}
return ret;
}
TMR_Status
TMR_SR_send(TMR_Reader *reader, uint8_t *data)
{
return TMR_SR_sendTimeout(reader, data,
reader->u.serialReader.commandTimeout);
}
/**
* Set the operating frequency of the device.
* Testing command.
*
* @param reader The reader
* @param frequency the frequency to set, in kHz
*/
TMR_Status
TMR_SR_cmdTestSetFrequency(TMR_Reader *reader, uint32_t frequency)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i,TMR_SR_OPCODE_SET_OPERATING_FREQ);
SETU32(msg, i, frequency);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
/**
* Turn CW transmission on or off.
* Testing command.
*
* @param reader The reader
* @param on whether to turn CW on or off
*/
TMR_Status
TMR_SR_cmdTestSendCw(TMR_Reader *reader, bool on)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i,TMR_SR_OPCODE_TX_CW_SIGNAL);
if(on)
SETU8(msg, i,1);
else
SETU8(msg, i,0);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
/**
* Turn on pseudo-random bit stream transmission for a particular
* duration.
* Testing command.
*
* @param reader The reader
* @param duration the duration to transmit the PRBS signal.
*/
TMR_Status
TMR_SR_cmdTestSendPrbs(TMR_Reader *reader, uint16_t duration)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i,TMR_SR_OPCODE_TX_CW_SIGNAL);
SETU8(msg, i,2);
SETU16(msg, i,duration);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
/**
* Setting user profile on the basis of operation, category and type parameter
*
* @param reader The reader
* @param op operation to be performed on configuration (Save,restore,verify and reset)
* @param category Which category of configuration to operate on -- only TMR_SR_ALL is currently supported
* @param type Type of configuration value to use (default, custom...)
*/
TMR_Status
TMR_SR_cmdSetUserProfile(TMR_Reader *reader,TMR_SR_UserConfigOperation op,TMR_SR_UserConfigCategory category, TMR_SR_UserConfigType type)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
TMR_Status ret;
TMR_Status ret1;
uint16_t readTime = 250;
TMR_SR_SerialReader *sr;
TMR_SR_SerialTransport *transport;
sr = &reader->u.serialReader;
transport = &reader->u.serialReader.transport;
i = 2;
SETU8(msg,i,TMR_SR_OPCODE_SET_USER_PROFILE);
SETU8(msg,i,op);
SETU8(msg,i,category);
SETU8(msg,i,type);
#ifdef TMR_ENABLE_BACKGROUND_READS
readTime = (uint16_t)reader->readParams.asyncOnTime;
#endif
if (op == TMR_USERCONFIG_CLEAR)
{
/* Resrt the Autonomous option if enabled */
sr->enableAutonomousRead = false;
}
if (op == TMR_USERCONFIG_SAVE_WITH_READPLAN)
{
/**
* extract the read plan configuration form API read plan object, frame
* the serial command for read by using existing parser methods in read
* operation and append that to save configuration command.
**/
TMR_uint8List *antennaList = NULL;
TMR_ReadPlan *rp;
uint8_t tempMsg[TMR_SR_MAX_PACKET_SIZE];
rp = reader->readParams.readPlan;
/**
* Currently Mercury API supports only true continuous read as a part of
* save configuration with read plan.
* TODO: Add support for other read types as well if needed in future.
**/
/* Add the Autonomous read option */
sr->enableAutonomousRead = rp->enableAutonomousRead;
SETU8(msg,i,rp->enableAutonomousRead);
if (TMR_READ_PLAN_TYPE_MULTI == rp->type)
{
/* The Multi read plan */
uint8_t i;
TMR_TagProtocolList p;
TMR_TagProtocolList *protocolList = &p;
TMR_TagFilter *filters[TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH];
TMR_TagProtocol protocols[TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH];
if (TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH < rp->u.multi.planCount)
{
return TMR_ERROR_TOO_BIG ;
}
protocolList->len = rp->u.multi.planCount;
protocolList->max = rp->u.multi.planCount;
protocolList->list = protocols;
for (i = 0; i < rp->u.multi.planCount; i++)
{
protocolList->list[i] = rp->u.multi.plans[i]->u.simple.protocol;
filters[i]= rp->u.multi.plans[i]->u.simple.filter;
}
if ((0 < rp->u.multi.planCount) &&
(rp->u.multi.plans[0]->type == TMR_READ_PLAN_TYPE_SIMPLE) &&
(compareAntennas(&rp->u.multi)))
{
TMR_SR_SearchFlag antennas = TMR_SR_SEARCH_FLAG_CONFIGURED_LIST;
reader->continuousReading = true;
antennas |= ((reader->continuousReading)? TMR_SR_SEARCH_FLAG_TAG_STREAMING : 0);
antennaList = &(rp->u.multi.plans[0]->u.simple.antennas);
ret = prepForSearch(reader, antennaList);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (reader->continuousReading)
{
bool value = false;
ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &value);
if (TMR_SUCCESS != ret)
{
return ret;
}
}
/* Call the helper function to frame the multi protocol read command */
ret = TMR_SR_msgSetupMultipleProtocolSearch(reader, tempMsg, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE, protocolList,
reader->userMetadataFlag, antennas, filters, (uint16_t)readTime);
if (TMR_SUCCESS != ret)
{
return ret;
}
}
else
{
/**
* Coming here means the requested read plan is not for true continuous read.
* Throw error back to user.
* TODO:Remove this validation, if we need to support for other type of read
* operation in future.
*/
return TMR_ERROR_UNSUPPORTED;
}
}
else
{
/* The Simple Read Plan */
TMR_TagProtocolList p;
TMR_TagProtocolList *protocolList = &p;
TMR_TagFilter *filters[TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH];
TMR_TagProtocol protocols[TMR_MAX_SERIAL_MULTIPROTOCOL_LENGTH];
TMR_SR_SearchFlag antennas;
antennaList = &rp->u.simple.antennas;
reader->continuousReading = true;
reader->fastSearch = rp->u.simple.useFastSearch;
reader->triggerRead = rp->u.simple.triggerRead.enable;
protocolList->len = 1;
protocolList->max = 1;
protocolList->list = protocols;
ret = prepForSearch(reader, antennaList);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (reader->continuousReading)
{
bool value = false;
ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &value);
if (TMR_SUCCESS != ret)
{
return ret;
}
}
protocolList->list[0] = rp->u.simple.protocol;
filters[0]= rp->u.simple.filter;
antennas = TMR_SR_SEARCH_FLAG_CONFIGURED_LIST;
antennas |= ((reader->continuousReading)? TMR_SR_SEARCH_FLAG_TAG_STREAMING : 0);
antennaList = &(rp->u.simple.antennas);
ret = TMR_SR_msgSetupMultipleProtocolSearch(reader, tempMsg, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE, protocolList,
reader->userMetadataFlag, antennas, filters, (uint16_t)readTime);
if (TMR_SUCCESS != ret)
{
return ret;
}
}
/* Append the serial read command to save configuration command */
memcpy((msg + i), tempMsg+1, tempMsg[1]+2);
/* Add two bytes for Opcode and header */
i = (i + tempMsg[1] + 2);
reader->continuousReading = false;
}
msg[1] = i - 3; /* Install length */
ret1 = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret1)
{
return ret1;
}
/* If Autonomous read is enabled skip this */
if (!sr->enableAutonomousRead)
{
if ((op == TMR_USERCONFIG_RESTORE)||(op == TMR_USERCONFIG_CLEAR)) //reprobe the baudrate
{
uint32_t rate;
if (reader->connected == false)
{
ret = transport->open(transport);
if (TMR_SUCCESS != ret)
{
return ret;
}
}
ret = TMR_SR_cmdProbeBaudRate(reader, &rate);
if (TMR_SUCCESS != ret)
{
return ret;
}
reader->connected = true;
}
/* Restore the region and protocol*/
if ((op == TMR_USERCONFIG_RESTORE) || (op == TMR_USERCONFIG_CLEAR))
{
ret = TMR_SR_cmdGetRegion(reader, &sr->regionId);
if (TMR_SUCCESS != ret)
{
return ret;
}
ret = TMR_SR_cmdGetCurrentProtocol(reader, &reader->tagOpParams.protocol);
if (TMR_SUCCESS != ret)
{
return ret;
}
sr->currentProtocol = reader->tagOpParams.protocol;
}
}
return ret1;
}
/**
* Get Save/Restore Configuration
*
* @param reader The reader
* @param byte array consists of a opcode option(s)
* @param length Length of byte array
* @param response Response of the operation
* @param response_length Length of response array
*/
TMR_Status TMR_SR_cmdGetUserProfile(TMR_Reader *reader, uint8_t byte[], uint8_t length, uint8_t response[], uint8_t* response_length)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i,j;
i = 2;
SETU8(msg,i,TMR_SR_OPCODE_GET_USER_PROFILE);
for(j=0;j<length;j++)
{
SETU8(msg,i,byte[j]);
}
msg[1] = i - 3;
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
for(j=0;j<msg[1];j++)
{
response[j]=msg[5+j];
}
*response_length=msg[1];
return ret;
}
TMR_Status TMR_SR_cmdBlockWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Bank bank, uint32_t wordPtr,
uint32_t wordCount, const uint16_t* data, uint32_t accessPassword, const TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, option=0,rec;
i = 2;
SETU8(msg,i,TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, i,timeout);
SETU8(msg,i,0x00);//chip type
rec=i;
SETU8(msg,i,0x40);//option
SETU8(msg,i,0x00);
SETU8(msg,i,0xC7);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, &i, msg,accessPassword,true);
msg[rec]=msg[rec]|option;
SETU8(msg,i,0x00);
SETU8(msg,i,bank);
SETU32(msg,i,wordPtr);
SETU8(msg,i,(uint8_t)wordCount);
{
uint32_t iWord;
for (iWord = 0; iWord < wordCount; iWord++)
{
SETU8(msg, i, ((data[iWord]>>8)&0xFF));
SETU8(msg, i, ((data[iWord]>>0)&0xFF));
}
}
msg[1] = i - 3;
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdBlockErase(TMR_Reader *reader, uint16_t timeout,
TMR_GEN2_Bank bank, uint32_t wordPtr,
uint8_t wordCount, uint32_t accessPassword,
TMR_TagFilter *target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddGEN2BlockErase(msg, &i, timeout, wordPtr, bank, wordCount, accessPassword, target);
msg[1] = i - 3;
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdBlockPermaLock(TMR_Reader *reader, uint16_t timeout,uint32_t readLock, TMR_GEN2_Bank bank, uint32_t blockPtr, uint32_t blockRange, uint16_t* mask, uint32_t accessPassword, TMR_TagFilter* target, TMR_uint8List* data)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, option=0,rec;
unsigned int j;
i = 2;
SETU8(msg,i,TMR_SR_OPCODE_ERASE_BLOCK_TAG_SPECIFIC);
SETU16(msg,i,timeout);
SETU8(msg,i,0x00);
rec=i;
SETU8(msg,i,0x40);
SETU8(msg,i,0x01);
filterbytes(TMR_TAG_PROTOCOL_GEN2,target, &option, &i, msg,accessPassword,true);
msg[rec]=msg[rec]|option;
SETU8(msg,i,0x00);
SETU8(msg,i,(uint8_t)readLock);
SETU8(msg,i,bank);
SETU32(msg,i,blockPtr);
SETU8(msg,i,(uint8_t)blockRange);
if (readLock==0x01)
{
for(j=0;j<blockRange;j++)
{
SETU8(msg,i,(mask[j]>>8)&(0xff));
SETU8(msg,i,(mask[j]>>0) & (0xff));
}
}
msg[1] = i - 3;
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
if ((0 == readLock) && (NULL != data))
{
data->len = msg[1]-2;
if (data->len > data->max)
{
data->len = data->max;
}
memcpy(data->list, msg+7, data->len);
}
return ret;
}
TMR_Status
TMR_SR_cmdVersion(TMR_Reader *reader, TMR_SR_VersionInfo *info)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, j;
uint32_t tTimeout = 0;
tTimeout = reader->u.serialReader.transportTimeout;
/**
* If user not set any trasportTimeout value.
* Use the default value.
*/
if (false == reader->u.serialReader.usrTimeoutEnable)
{
reader->u.serialReader.transportTimeout = 100;
}
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_VERSION);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, 0);
if (TMR_SUCCESS != ret)
{
reader->u.serialReader.transportTimeout = tTimeout;
return ret;
}
if (NULL != info)
{
i = 5;
for (j = 0; j < 4 ; j++)
{
info->bootloader[j] = GETU8(msg, i);
}
for (j = 0; j < 4 ; j++)
{
info->hardware[j] = GETU8(msg, i);
}
for (j = 0; j < 4 ; j++)
{
info->fwDate[j] = GETU8(msg, i);
}
for (j = 0; j < 4 ; j++)
{
info->fwVersion[j] = GETU8(msg, i);
}
info->protocols = GETU32(msg, i);
}
reader->u.serialReader.transportTimeout = tTimeout;
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdBootFirmware(TMR_Reader *reader)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, j;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_BOOT_FIRMWARE);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, 1000);
if (TMR_SUCCESS != ret)
{
return ret;
}
i = 5;
for (j = 0; j < 4 ; j++)
{
reader->u.serialReader.versionInfo.bootloader[j] = GETU8(msg, i);
}
for (j = 0; j < 4 ; j++)
{
reader->u.serialReader.versionInfo.hardware[j] = GETU8(msg, i);
}
for (j = 0; j < 4 ; j++)
{
reader->u.serialReader.versionInfo.fwDate[j] = GETU8(msg, i);
}
for (j = 0; j < 4 ; j++)
{
reader->u.serialReader.versionInfo.fwVersion[j] = GETU8(msg, i);
}
reader->u.serialReader.versionInfo.protocols = GETU32(msg, i);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdSetBaudRate(TMR_Reader *reader, uint32_t rate)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_BAUD_RATE);
SETU32(msg, i, rate);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdEraseFlash(TMR_Reader *reader, uint8_t sector, uint32_t password)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_ERASE_FLASH);
SETU32(msg, i, password);
SETU8(msg, i, sector);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, 30000);
}
TMR_Status
TMR_SR_cmdWriteFlashSector(TMR_Reader *reader, uint8_t sector, uint32_t address,
uint32_t password, uint8_t length, const uint8_t data[],
uint32_t offset)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_WRITE_FLASH_SECTOR);
SETU32(msg, i, password);
SETU32(msg, i, address);
SETU8(msg, i, sector);
memcpy(&msg[i], data + offset, length);
i += length;
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, 3000);
}
TMR_Status
TMR_SR_cmdModifyFlashSector(TMR_Reader *reader, uint8_t sector, uint32_t address,
uint32_t password, uint8_t length, const uint8_t data[],
uint32_t offset)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_MODIFY_FLASH_SECTOR);
SETU32(msg, i, password);
SETU32(msg, i, address);
SETU8(msg, i, sector);
memcpy(&msg[i], data + offset, length);
i += length;
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, 3000);
}
TMR_Status
TMR_SR_cmdBootBootloader(TMR_Reader *reader)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_BOOT_BOOTLOADER);
msg[1] = i - 3; /* Install length */
reader->u.serialReader.crcEnabled = true;
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdGetHardwareVersion(TMR_Reader *reader, uint8_t option, uint8_t flags,
uint8_t* count, uint8_t data[])
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_HW_VERSION);
SETU8(msg, i, option);
SETU8(msg, i, flags);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
for (i = 0 ; i < msg[1] && i < *count; i++)
{
data[i] = msg[5 + i];
}
*count = msg[1];
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetCurrentProgram(TMR_Reader *reader, uint8_t *program)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_CURRENT_PROGRAM);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
*program = msg[5];
return ret;
}
TMR_Status TMR_SR_msgSetupReadTagSingle(uint8_t *msg, uint8_t *i, TMR_TagProtocol protocol,TMR_TRD_MetadataFlag metadataFlags, const TMR_TagFilter *filter,uint16_t timeout)
{
uint8_t optbyte;
SETU8(msg, *i, TMR_SR_OPCODE_READ_TAG_ID_SINGLE);
SETU16(msg, *i, timeout);
optbyte = *i;
SETU8(msg, *i, 0); /* Initialize option byte */
msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA;
SETU16(msg,*i, metadataFlags);
filterbytes(protocol, filter, &msg[optbyte], i, msg,0, true);
msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA;
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_msgSetupReadTagMultiple(TMR_Reader *reader, uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_SearchFlag searchFlag,
const TMR_TagFilter *filter,
TMR_TagProtocol protocol,
TMR_GEN2_Password accessPassword)
{
return TMR_SR_msgSetupReadTagMultipleWithMetadata(reader, msg, i, timeout,
searchFlag, reader->userMetadataFlag, filter, protocol,accessPassword);
}
TMR_Status
TMR_SR_msgSetupReadTagMultipleWithMetadata(TMR_Reader *reader, uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_SearchFlag searchFlag,
TMR_TRD_MetadataFlag metadataFlag,
const TMR_TagFilter *filter,
TMR_TagProtocol protocol,
TMR_GEN2_Password accessPassword)
{
TMR_Status ret;
TMR_SR_SerialReader *sr;
uint8_t optbyte;
sr = &reader->u.serialReader;
sr->opCode = TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE;
ret = TMR_SUCCESS;
SETU8(msg, *i, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE);
/**
* we need to add the option for bap parameters if enabled
*
* for adding the bap parameter option, and EBV technique is used
* raising the lowest order bit of the high opder byte signals the
* use of new Gen2 Bap support parameters.
**/
if (sr->isBapEnabled)
{
SETU8(msg,*i,0x81);
}
optbyte = *i;
SETU8(msg, *i, 0); /* Initialize option byte */
/* add the large tag population support */
searchFlag= (TMR_SR_SearchFlag)(searchFlag | TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT);
if (reader->continuousReading)
{
msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA;
searchFlag = (TMR_SR_SearchFlag)(searchFlag
| TMR_SR_SEARCH_FLAG_TAG_STREAMING);
/**
* We need to send a different flag for the new reader stats,
* Both these options are mutually exclusive in nature,
* Hence can not be raised at once.
**/
if (TMR_SR_STATUS_NONE != reader->streamStats)
{
searchFlag |= TMR_SR_SEARCH_FLAG_STATUS_REPORT_STREAMING;
}
else
{
if (TMR_READER_STATS_FLAG_NONE != reader->statsFlag)
{
searchFlag |= TMR_SR_SEARCH_FLAG_STATS_REPORT_STREAMING;
}
}
}
/**
* Add the fast search flag depending on the user choice
*/
if (reader->fastSearch)
{
searchFlag = (TMR_SR_SearchFlag)(searchFlag
|TMR_SR_SEARCH_FLAG_READ_MULTIPLE_FAST_SEARCH);
reader->fastSearch = false;
}
/**
* Add the trigger read flag depending on the user choice
*/
if (reader->triggerRead)
{
searchFlag = (TMR_SR_SearchFlag)(searchFlag
|TMR_SR_SEARCH_FLAG_GPI_TRIGGER_READ);
reader->triggerRead = false;
}
/**
* Add the duty cycle flag depending on the user choice
*/
if (reader->dutyCycle)
{
searchFlag = (TMR_SR_SearchFlag)(searchFlag
|TMR_SR_SEARCH_FLAG_DUTY_CYCLE_CONTROL);
}
if (reader->isStopNTags && !reader->continuousReading)
{
/**
* Currently stop N Trigger is only supported for
* sync read.
**/
searchFlag = (TMR_SR_SearchFlag)(searchFlag
|TMR_SR_SEARCH_FLAG_RETURN_ON_N_TAGS);
}
SETU16(msg, *i, searchFlag);
SETU16(msg, *i, timeout);
if(reader->dutyCycle)
{
uint32_t offtime;
ret = TMR_paramGet(reader,TMR_PARAM_READ_ASYNCOFFTIME,&offtime);
SETU16(msg, *i, (uint16_t)offtime);
}
reader->dutyCycle = false;
if (reader->continuousReading)
{
SETU16(msg, *i, metadataFlag);
if (TMR_READER_STATS_FLAG_NONE != reader->statsFlag)
{
/**
* To extend the flag byte, an EBV technique is to be used.
* When the highest order bit of the flag byte is used,
* it signals the reader’s parser, that another flag byte is to follow
*/
if ((0x80) > reader->statsFlag)
{
SETU16(msg, *i, (uint16_t)reader->statsFlag);
}
else
{
SETU16(msg, *i, ((uint16_t)reader->statsFlag));
}
}
else
{
if (TMR_SR_STATUS_NONE != reader->streamStats)
{
/* Add status report flags, so that the status stream responses are received */
SETU16(msg, *i, (uint16_t)reader->streamStats);
}
}
}
/**
* Add the no of tags to be read requested by user
* in stop N tag reads.Currently only supported for
* sync read.
**/
if (reader->isStopNTags && !reader->continuousReading)
{
SETU32(msg ,*i, (uint32_t)reader->numberOfTagsToRead);
}
/*
* Earlier, this filter bytes were skipped for a null filter and gen2 0 access password.
* as the filterbytes it self has the checks internally, these were removed.
* for some protocols (such as ISO180006B) the "null" filter is not zero-length, but we don't need to send
* that with this command.
*/
if (TMR_TAG_PROTOCOL_ISO180006B == protocol && NULL == filter)
{
/* ISO18000-6B should not include any filter arg bytes if null */
}
else
{
ret = filterbytes(protocol, filter, &msg[optbyte], i, msg,
accessPassword, true);
}
if (reader->continuousReading)
{
msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_FLAG_METADATA;
}
if (isSecureAccessEnabled)
{
msg[optbyte] |= TMR_SR_GEN2_SINGULATION_OPTION_SECURE_READ_DATA;
}
return ret;
}
TMR_Status
TMR_SR_cmdReadTagMultiple(TMR_Reader *reader, uint16_t timeout,
TMR_SR_SearchFlag searchFlag,
const TMR_TagFilter *filter, TMR_TagProtocol protocol,
uint32_t *tagCount)
{
TMR_Status ret;
TMR_SR_SerialReader *sr;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
ret = TMR_SR_msgSetupReadTagMultiple(reader, msg, &i, timeout, searchFlag,
filter, protocol, 0);
if (TMR_SUCCESS != ret)
{
return ret;
}
msg[1] = i - 3; /* Install length */
sr = &reader->u.serialReader;
sr->opCode = TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE;
if (reader->continuousReading)
{
uint8_t opcode;
ret = TMR_SR_sendMessage(reader, msg, &opcode, timeout);
*tagCount = (uint32_t)0;
return ret;
}
else
{
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (NULL != tagCount)
{
if (4 == msg[1])
{
/* Plain 1-byte count: Reader without large-tag-population support */
*tagCount = GETU8AT(msg, 8);
}
else if (5 == msg[1])
{
/* Later 1-byte count: ISO18k select option included in reply */
*tagCount = GETU8AT(msg, 9);
}
else if (7 == msg[1])
{
/* Plain 4-byte count: Reader with large-tag-population support */
*tagCount = GETU32AT(msg, 8);
}
else if (8 == msg[1])
{
/* Later 4-byte count: Large-tag-population support and ISO18k
* select option included in reply.
*/
*tagCount = GETU32AT(msg, 9);
}
else
{
return TMR_ERROR_PARSE;
}
}
return TMR_SUCCESS;
}
}
TMR_Status
TMR_SR_executeEmbeddedRead(TMR_Reader *reader, uint8_t *msg, uint16_t timeout,
TMR_SR_MultipleStatus *status)
{
TMR_Status ret;
uint8_t i, len, index;
uint8_t newMsg[TMR_SR_MAX_PACKET_SIZE];
if (reader->continuousReading)
{
uint8_t opcode = TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP;
i = 2;
SETU8(newMsg, i, opcode); /* Opcode */
/* Timeout should be zero for true continuous reading */
SETU16(newMsg, i, 0);
SETU8(newMsg, i, (uint8_t)0x1); /* TM Option 1, for continuous reading */
SETU8(newMsg, i, (uint8_t)TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE); /* sub command opcode */
SETU16(newMsg, i, (uint16_t)0x0000); /* search flags, only 0x0001 is supported */
SETU8(newMsg, i, (uint8_t)TMR_TAG_PROTOCOL_GEN2); /* protocol ID */
len = msg[1];
index = i;
SETU8(newMsg, i, 0); /* Protocol command length (initialize to 0)*/
/* Copy the protocol command including the command opcode (len + 1)*/
memcpy(&newMsg[i], &msg[2], (size_t)(len + 1));
i += len + 1;
/* Insert the exact protocol command length */
newMsg[index] = i - index - 2;
/* Install the total packet length*/
newMsg[1]=i - 3;
ret = TMR_SR_sendMessage(reader, newMsg, &opcode, timeout);
status->tagsFound = status->successCount = status->failureCount = 0;
return ret;
}
else
{
uint16_t searchFlags = GETU16AT(msg, 4);
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (NULL != status)
{
int readIdx = 8;
if ((TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT & searchFlags) &&
((TMR_SR_MODEL_M6E == reader->u.serialReader.versionInfo.hardware[0]) ||
(TMR_SR_MODEL_M6E_I == reader->u.serialReader.versionInfo.hardware[0]) ||
(TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0]) ||
(TMR_SR_MODEL_MICRO == reader->u.serialReader.versionInfo.hardware[0])))
{
/* Only in case of M6e, the tag length will be 4 bytes */
status->tagsFound = (uint16_t)GETU32AT(msg, readIdx);
readIdx += 4;
}
else
{
status->tagsFound = GETU8AT(msg, readIdx);
readIdx += 1;
}
readIdx += 2;
status->successCount = GETU16AT(msg, readIdx);
readIdx += 2;
status->failureCount = GETU16AT(msg, readIdx);
readIdx += 2;
}
}
return TMR_SUCCESS;
}
void
TMR_SR_msgAddGEN2WriteTagEPC(uint8_t *msg, uint8_t *i, uint16_t timeout, uint8_t *epc, uint8_t count)
{
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_ID);
SETU16(msg, *i, timeout); /* timeout */
SETU16(msg, *i, 0); /* RFU 2 bytes */
memcpy(&msg[*i], epc, count);
*i += count;
}
void
TMR_SR_msgAddGEN2DataRead(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_GEN2_Bank bank, uint32_t wordAddress, uint8_t len, uint8_t option, bool withMetaData)
{
SETU8(msg, *i, TMR_SR_OPCODE_READ_TAG_DATA);
SETU16(msg, *i, timeout);
SETU8(msg, *i, option); /* Options - initialize */
if (withMetaData)
{
SETU16(msg, *i, 0x0000); /* metadata flags - initialize */
}
SETU8(msg, *i, bank);
SETU32(msg, *i, wordAddress);
SETU8(msg, *i, len);
}
void
TMR_SR_msgAddGEN2DataWrite(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_GEN2_Bank bank, uint32_t address)
{
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_DATA);
SETU16(msg, *i, timeout);
SETU8(msg, *i, 0); /* Option - initialize */
SETU32(msg, *i, address);
SETU8(msg, *i, bank);
}
void
TMR_SR_msgAddGEN2LockTag(uint8_t *msg, uint8_t *i, uint16_t timeout, uint16_t mask,
uint16_t action, TMR_GEN2_Password accessPassword)
{
SETU8(msg, *i, TMR_SR_OPCODE_LOCK_TAG);
SETU16(msg, *i, timeout);
SETU8(msg, *i, 0); /* Option - initialize */
SETU32(msg, *i, accessPassword);
SETU16(msg, *i, mask);
SETU16(msg, *i, action);
}
void
TMR_SR_msgAddGEN2KillTag(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_GEN2_Password password)
{
SETU8(msg, *i, TMR_SR_OPCODE_KILL_TAG);
SETU16(msg, *i, timeout);
SETU8(msg, *i, 0); /* Option - initialize */
SETU32(msg, *i, password);
SETU8(msg, *i, 0); /* RFU */
}
void
TMR_SR_msgAddGEN2BlockWrite(uint8_t *msg, uint8_t *i, uint16_t timeout,TMR_GEN2_Bank bank, uint32_t wordPtr, uint32_t wordCount, uint16_t* data, uint32_t accessPassword, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg,*i,TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i,timeout);
SETU8(msg,*i,0x00);//chip type
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg,*i,0x00);
SETU8(msg,*i,0xC7);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg,accessPassword,true);
msg[rec]=msg[rec]|option;
SETU8(msg,*i,0x00);
SETU8(msg,*i,bank);
SETU32(msg,*i,wordPtr);
SETU8(msg,*i,(uint8_t)wordCount);
{
uint32_t iWord;
for (iWord=0; iWord<wordCount; iWord++)
{
SETU8(msg, *i, ((data[iWord]>>8)&0xFF));
SETU8(msg, *i, ((data[iWord]>>0)&0xFF));
}
}
}
void
TMR_SR_msgAddGEN2BlockPermaLock(uint8_t *msg, uint8_t *i, uint16_t timeout, uint32_t readLock, TMR_GEN2_Bank bank, uint32_t blockPtr, uint32_t blockRange, uint16_t* mask, uint32_t accessPassword,TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg,*i,TMR_SR_OPCODE_ERASE_BLOCK_TAG_SPECIFIC);
SETU16(msg,*i,timeout);
SETU8(msg,*i,0x00);
rec=*i;
SETU8(msg,*i,0x40);
SETU8(msg,*i,0x01);
filterbytes(TMR_TAG_PROTOCOL_GEN2,target, &option, i, msg,accessPassword,true);
msg[rec]=msg[rec]|option;
SETU8(msg,*i,0x00);
SETU8(msg,*i,(uint8_t)readLock);
SETU8(msg,*i,bank);
SETU32(msg,*i,blockPtr);
SETU8(msg,*i,(uint8_t)blockRange);
if (readLock==0x01)
{
SETU16(msg, *i, *mask);
}
}
void
TMR_SR_msgAddGEN2BlockErase(uint8_t *msg, uint8_t *i, uint16_t timeout,
uint32_t wordPtr, TMR_GEN2_Bank bank, uint8_t wordCount,
uint32_t accessPassword, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_ERASE_BLOCK_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, 0x00);
rec = *i;
SETU8(msg, *i, 0x40);
SETU8(msg, *i, 0x00); /* Block erase */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec] = msg[rec] | option;
SETU32(msg, *i, wordPtr);
SETU8(msg, *i, bank);
SETU8(msg,*i, wordCount);
}
TMR_Status
TMR_SR_cmdWriteGen2TagEpc(TMR_Reader *reader, const TMR_TagFilter *filter, TMR_GEN2_Password accessPassword,
uint16_t timeout, uint8_t count, const uint8_t *id, bool lock)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, optbyte;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_WRITE_TAG_ID);
SETU16(msg, i, timeout);
optbyte = i;
SETU8(msg, i, 0);
ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg,
accessPassword, true);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (0 == msg[optbyte])
{
SETU8(msg, i, 0); // Initialize second RFU byte to zero
}
if (i + count + 1 > TMR_SR_MAX_PACKET_SIZE)
{
return TMR_ERROR_TOO_BIG;
}
memcpy(&msg[i], id, count);
i += count;
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
TMR_Status
TMR_SR_cmdClearTagBuffer(TMR_Reader *reader)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_CLEAR_TAG_ID_BUFFER);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status TMR_SR_cmdGetTagsRemaining(TMR_Reader *reader, uint16_t *tagCount)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
TMR_Status ret;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_TAG_ID_BUFFER);
msg[1] = i-3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*tagCount = GETU16AT(msg, 7) - GETU16AT(msg, 5);
return TMR_SUCCESS;
}
void
TMR_SR_parseMetadataFromMessage(TMR_Reader *reader, TMR_TagReadData *read, uint16_t flags,
uint8_t *i, uint8_t msg[])
{
int msgEpcLen;
read->metadataFlags = flags;
read->tag.protocol = TMR_TAG_PROTOCOL_NONE;
read->readCount = 0;
read->rssi = 0;
read->antenna = 0;
read->phase = 0;
read->frequency = 0;
read->dspMicros = 0;
read->timestampLow = 0;
read->timestampHigh = 0;
read->isAsyncRead = false;
switch(reader->u.serialReader.versionInfo.hardware[0])
{
case TMR_SR_MODEL_M5E:
read->gpioCount = 2;
break;
case TMR_SR_MODEL_M6E:
read->gpioCount = 4;
break;
default:
read->gpioCount = 4;
break;
}
/* Fill in tag data from response */
if (flags & TMR_TRD_METADATA_FLAG_READCOUNT)
{
read->readCount = GETU8(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_RSSI)
{
read->rssi = (int8_t)GETU8(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_ANTENNAID)
{
read->antenna = GETU8(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_FREQUENCY)
{
read->frequency = GETU24(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_TIMESTAMP)
{
read->dspMicros = GETU32(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_PHASE)
{
read->phase = GETU16(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_PROTOCOL)
{
read->tag.protocol = (TMR_TagProtocol)GETU8(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_DATA)
{
int msgDataLen, copyLen;
msgDataLen = tm_u8s_per_bits(GETU16(msg, *i));
read->data.len = msgDataLen;
copyLen = msgDataLen;
if (copyLen > read->data.max)
{
copyLen = read->data.max;
}
if (NULL != read->data.list)
{
memcpy(read->data.list, &msg[*i], copyLen);
}
/**
* if the gen2AllMemoryBankEnabled is enabled,
* extract the values
**/
if (reader->u.serialReader.gen2AllMemoryBankEnabled)
{
uint16_t dataLength = read->data.len;
uint8_t readOffSet = 0;
uint8_t bank;
uint16_t epcDataLength;
while (dataLength != 0)
{
if (readOffSet >= dataLength)
break;
bank = ((read->data.list[readOffSet] >> 4) & 0x1F);
epcDataLength = (read->data.list[readOffSet + 1] * 2);
switch (bank)
{
case TMR_GEN2_BANK_EPC:
{
read->epcMemData.len = epcDataLength;
if (epcDataLength > read->epcMemData.max)
{
epcDataLength = read->epcMemData.max;
}
if (NULL != read->epcMemData.list)
{
memcpy(read->epcMemData.list, (read->data.list + readOffSet + 2), epcDataLength);
}
readOffSet += (epcDataLength + 2);
break;
}
case TMR_GEN2_BANK_RESERVED:
{
read->reservedMemData.len = epcDataLength;
if (epcDataLength > read->epcMemData.max)
{
epcDataLength = read->reservedMemData.max;
}
if (NULL != read->reservedMemData.list)
{
memcpy(read->reservedMemData.list, (read->data.list + readOffSet + 2), epcDataLength);
}
readOffSet += (epcDataLength + 2);
break;
}
case TMR_GEN2_BANK_TID:
{
read->tidMemData.len = epcDataLength;
if (epcDataLength > read->tidMemData.max)
{
epcDataLength = read->tidMemData.max;
}
if (NULL != read->tidMemData.list)
{
memcpy(read->tidMemData.list, (read->data.list + readOffSet + 2), epcDataLength);
}
readOffSet += (epcDataLength + 2);
break;
}
case TMR_GEN2_BANK_USER:
{
read->userMemData.len = epcDataLength;
if (epcDataLength > read->userMemData.max)
{
epcDataLength = read->userMemData.max;
}
if (NULL != read->userMemData.list)
{
memcpy(read->userMemData.list, (read->data.list + readOffSet + 2), epcDataLength);
}
readOffSet += (epcDataLength + 2);
break;
}
default:
break;
}
}
}
/**
* Now, we extracted all the values,
* Disable the gen2AllMemoryBankEnabled option.
**/
reader->u.serialReader.gen2AllMemoryBankEnabled = false;
*i += msgDataLen;
}
if (flags & TMR_TRD_METADATA_FLAG_GPIO_STATUS)
{
int j;
uint8_t gpioByte=GETU8(msg, *i);
for (j=0;j<read->gpioCount;j++)
{
read->gpio[j].id = j+1;
read->gpio[j].high = (((gpioByte >> j)&0x1)== 1);
}
}
msgEpcLen = tm_u8s_per_bits(GETU16(msg, *i));
if (TMR_TAG_PROTOCOL_ATA != read->tag.protocol)
{
/* ATA protocol does not have TAG CRC */
msgEpcLen -= 2; /* Remove 2 bytes CRC*/
}
if (TMR_TAG_PROTOCOL_GEN2 == read->tag.protocol)
{
read->tag.u.gen2.pc[0] = GETU8(msg, *i);
read->tag.u.gen2.pc[1] = GETU8(msg, *i);
msgEpcLen -= 2;
read->tag.u.gen2.pcByteCount = 2;
/* Add support for XPC bits
* XPC_W1 is present, when the 6th most significant bit of PC word is set
*/
if ((read->tag.u.gen2.pc[0] & 0x02) == 0x02)
{
/* When this bit is set, the XPC_W1 word will follow the PC word
* Our TMR_Gen2_TagData::pc has enough space, so copying to the same.
*/
read->tag.u.gen2.pc[2] = GETU8(msg, *i);
read->tag.u.gen2.pc[3] = GETU8(msg, *i);
msgEpcLen -= 2; /* EPC length will be length - 4(PC + XPC_W1)*/
read->tag.u.gen2.pcByteCount += 2; /* PC bytes are now 4*/
if ((read->tag.u.gen2.pc[2] & 0x80) == 0x80)
{
/*
* If the most siginificant bit of XPC_W1 is set, then there exists
* XPC_W2. A total of 6 (PC + XPC_W1 + XPC_W2 bytes)
*/
read->tag.u.gen2.pc[4] = GETU8(msg, *i);
read->tag.u.gen2.pc[5] = GETU8(msg, *i);
msgEpcLen -= 2; /* EPC length will be length - 6 (PC + XPC_W1 + XPC_W2)*/
read->tag.u.gen2.pcByteCount += 2; /* PC bytes are now 6 */
}
}
}
read->tag.epcByteCount = msgEpcLen;
if (read->tag.epcByteCount > TMR_MAX_EPC_BYTE_COUNT)
{
read->tag.epcByteCount = TMR_MAX_EPC_BYTE_COUNT;
}
memcpy(read->tag.epc, &msg[*i], read->tag.epcByteCount);
*i += msgEpcLen;
if (TMR_TAG_PROTOCOL_ATA != read->tag.protocol)
{
read->tag.crc = GETU16(msg, *i);
}
else
{
read->tag.crc = 0xffff;
}
if(reader->continuousReading)
{
read->isAsyncRead = true;
}
else
{
read->isAsyncRead = false;
}
}
void
TMR_SR_parseMetadataOnly(TMR_Reader *reader, TMR_TagReadData *read, uint16_t flags,
uint8_t *i, uint8_t msg[])
{
read->metadataFlags = flags;
read->tag.protocol = TMR_TAG_PROTOCOL_NONE;
read->readCount = 0;
read->rssi = 0;
read->antenna = 0;
read->phase = 0;
read->frequency = 0;
read->dspMicros = 0;
read->timestampLow = 0;
read->timestampHigh = 0;
read->isAsyncRead = false;
switch(reader->u.serialReader.versionInfo.hardware[0])
{
case TMR_SR_MODEL_M5E:
read->gpioCount = 2;
break;
case TMR_SR_MODEL_M6E:
read->gpioCount = 4;
break;
default:
read->gpioCount = 4;
break;
}
/* Fill in tag data from response */
if (flags & TMR_TRD_METADATA_FLAG_READCOUNT)
{
read->readCount = GETU8(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_RSSI)
{
read->rssi = GETU8(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_ANTENNAID)
{
read->antenna = GETU8(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_FREQUENCY)
{
read->frequency = GETU24(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_TIMESTAMP)
{
read->dspMicros = GETU32(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_PHASE)
{
read->phase = GETU16(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_PROTOCOL)
{
read->tag.protocol = (TMR_TagProtocol)GETU8(msg, *i);
}
if (flags & TMR_TRD_METADATA_FLAG_DATA)
{
int msgDataLen, copyLen;
msgDataLen = tm_u8s_per_bits(GETU16(msg, *i));
read->data.len = msgDataLen;
copyLen = msgDataLen;
if (copyLen > read->data.max)
{
copyLen = read->data.max;
}
memcpy(read->data.list, &msg[*i], copyLen);
*i += msgDataLen;
}
if (flags & TMR_TRD_METADATA_FLAG_GPIO_STATUS)
{
int j;
uint8_t gpioByte=GETU8(msg, *i);
for (j=0;j<read->gpioCount ;j++)
{
read->gpio[j].id = j+1;
read->gpio[j].high = (((gpioByte >> j)&0x1)== 1);
}
}
}
void
TMR_SR_postprocessReaderSpecificMetadata(TMR_TagReadData *read, TMR_SR_SerialReader *sr)
{
uint16_t j;
uint32_t timestampLow;
uint64_t currTime64, lastSentTagTime64; /*for comparison*/
int32_t tempDiff;
timestampLow = sr->readTimeLow;
read->timestampHigh = sr->readTimeHigh;
timestampLow = timestampLow + read->dspMicros;
currTime64 = ((uint64_t)read->timestampHigh << 32) | timestampLow;
lastSentTagTime64 = ((uint64_t)sr->lastSentTagTimestampHigh << 32) | sr->lastSentTagTimestampLow;
if (lastSentTagTime64 >= currTime64)
{
tempDiff = (int32_t)(currTime64 - lastSentTagTime64);
timestampLow = timestampLow - tempDiff + 1;
if (timestampLow < sr->lastSentTagTimestampLow) /*account for overflow*/
{
read->timestampHigh++;
}
}
if (timestampLow < sr->readTimeLow) /* Overflow */
{
read->timestampHigh++;
}
read->timestampLow = timestampLow;
sr->lastSentTagTimestampHigh = read->timestampHigh;
sr->lastSentTagTimestampLow = read->timestampLow;
{
uint8_t tx;
uint8_t rx;
tx = (read->antenna >> 4) & 0xF;
rx = (read->antenna >> 0) & 0xF;
// Due to limited space, Antenna 16 wraps around to 0
if (0 == tx) { tx = 16; }
if (0 == rx) { rx = 16; }
for (j = 0; j < sr->txRxMap->len; j++)
{
if (rx == sr->txRxMap->list[j].rxPort &&
tx == sr->txRxMap->list[j].txPort)
{
read->antenna = sr->txRxMap->list[j].antenna;
if (read->gpioCount > 2)
{
if (read->gpio[2].high)
read->antenna += 16;
}
break;
}
}
}
}
#ifdef TMR_ENABLE_ISO180006B
TMR_Status
TMR_SR_cmdISO180006BReadTagData(TMR_Reader *reader,
uint16_t timeout, uint8_t address,
uint8_t length, const TMR_TagFilter *filter,
TMR_TagReadData *read)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t copylen, i;
if (length > 8
|| filter == NULL
|| TMR_FILTER_TYPE_TAG_DATA != filter->type
|| filter->u.tagData.epcByteCount != 8)
{
return TMR_ERROR_INVALID;
}
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_READ_TAG_DATA);
SETU16(msg, i, timeout);
SETU8(msg, i, 0x01); /* Standard read operations */
SETU8(msg, i, TMR_SR_ISO180006B_COMMAND_READ);
SETU8(msg, i, 0x00); /* RFU */
SETU8(msg, i, length);
SETU8(msg, i, address);
memcpy(&msg[i], filter->u.tagData.epc, 8);
i += 8;
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
read->metadataFlags = TMR_TRD_METADATA_FLAG_DATA;
read->tag.protocol = TMR_TAG_PROTOCOL_ISO180006B;
read->tag.epcByteCount = 0;
read->data.len = msg[1];
copylen = (uint8_t)read->data.len;
if (copylen > read->data.max)
{
copylen = (uint8_t)read->data.max;
}
if (NULL != read->data.list)
{
memcpy(read->data.list, &msg[5], copylen);
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdISO180006BWriteTagData(TMR_Reader *reader,
uint16_t timeout, uint8_t address,
uint8_t count, const uint8_t data[],
const TMR_TagFilter *filter)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_WRITE_TAG_DATA);
SETU16(msg, i, timeout);
if (NULL != filter
&& TMR_FILTER_TYPE_TAG_DATA == filter->type
&& filter->u.tagData.epcByteCount == 8)
{
SETU8(msg, i,
TMR_SR_ISO180006B_WRITE_OPTION_READ_VERIFY_AFTER
| TMR_SR_ISO180006B_WRITE_OPTION_COUNT_PROVIDED);
SETU8(msg, i, TMR_SR_ISO180006B_COMMAND_WRITE4BYTE);
SETU8(msg, i, TMR_SR_ISO180006B_WRITE_LOCK_NO);
SETU8(msg, i, address);
memcpy(&msg[i], filter->u.tagData.epc, 8);
i += 8;
}
else
{
SETU8(msg, i, TMR_SR_ISO180006B_WRITE_OPTION_GROUP_SELECT
| TMR_SR_ISO180006B_WRITE_OPTION_COUNT_PROVIDED);
SETU8(msg, i, TMR_SR_ISO180006B_COMMAND_WRITE4BYTE_MULTIPLE);
SETU8(msg, i, TMR_SR_ISO180006B_WRITE_LOCK_NO);
SETU8(msg, i, address);
/*
* Actually, we don't use password in case of iso.
* passing 1, instead of '0' fixes the crash.
*/
ret = filterbytes(TMR_TAG_PROTOCOL_ISO180006B, filter, NULL,
&i, msg, 1, false);
if (TMR_SUCCESS != ret)
{
return ret;
}
}
SETU16(msg, i, count);
memcpy(&msg[i], data, count);
i += count;
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
TMR_Status
TMR_SR_cmdISO180006BLockTag(TMR_Reader *reader, uint16_t timeout,
uint8_t address, const TMR_TagFilter *filter)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
if (filter == NULL
|| TMR_FILTER_TYPE_TAG_DATA != filter->type
|| filter->u.tagData.epcByteCount != 8)
{
return TMR_ERROR_INVALID;
}
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_LOCK_TAG);
SETU16(msg, i, timeout);
SETU8(msg, i, TMR_SR_ISO180006B_LOCK_OPTION_TYPE_FOLLOWS);
SETU8(msg, i, TMR_SR_ISO180006B_LOCK_TYPE_QUERYLOCK_THEN_LOCK);
SETU8(msg, i, address);
memcpy(&msg[i], filter->u.tagData.epc, 8);
i += 8;
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
#endif /* TMR_ENABLE_ISO180006B */
TMR_Status
TMR_SR_cmdGEN2WriteTagData(TMR_Reader *reader,
uint16_t timeout, TMR_GEN2_Bank bank,
uint32_t address, uint8_t count,
const uint8_t data[],
TMR_GEN2_Password accessPassword,
const TMR_TagFilter *filter)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t optbyte, i;
i = 2;
TMR_SR_msgAddGEN2DataWrite(msg, &i, timeout, bank, address);
optbyte = 5;
ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg,
accessPassword, true);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (i + count + 1 > TMR_SR_MAX_PACKET_SIZE)
{
return TMR_ERROR_TOO_BIG;
}
memcpy(&msg[i], data, count);
i += count;
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
TMR_Status
TMR_SR_cmdGEN2LockTag(TMR_Reader *reader, uint16_t timeout,
uint16_t mask, uint16_t action,
TMR_GEN2_Password accessPassword,
const TMR_TagFilter *filter)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t optbyte, i;
i = 2;
TMR_SR_msgAddGEN2LockTag(msg, &i, timeout, mask, action, accessPassword);
optbyte = 5;
ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg,
0, false);
if (TMR_SUCCESS != ret)
{
return ret;
}
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
TMR_Status
TMR_SR_cmdrebootReader(TMR_Reader *reader)
{
TMR_Status ret;
TMR_SR_SerialReader *sr;
TMR_SR_SerialTransport *transport;
sr = &reader->u.serialReader;
transport = &sr->transport;
/*
* Drop baud to 9600 so we know for sure what it will be after going
* back to the bootloader. (Older firmwares always revert to 9600.
* Newer ones keep the current baud rate.)
*/
if (NULL != transport->setBaudRate)
{
/**
* some transport layer does not support baud rate settings.
* for ex: TCP transport. In that case skip the baud rate
* settings.
*/
ret = TMR_SR_cmdSetBaudRate(reader, 9600);
if (TMR_SUCCESS != ret)
{
return ret;
}
ret = transport->setBaudRate(transport, 9600);
if (TMR_SUCCESS != ret)
{
return ret;
}
}
ret = TMR_SR_cmdBootBootloader(reader);
if ((TMR_SUCCESS != ret)
/* Invalid Opcode okay -- means "already in bootloader" */
&& (TMR_ERROR_INVALID_OPCODE != ret))
{
return ret;
}
/*
* Wait for the bootloader to be entered. 200ms is enough.
*/
tmr_sleep(200);
return ret;
}
TMR_Status
TMR_SR_cmdKillTag(TMR_Reader *reader, uint16_t timeout,
TMR_GEN2_Password killPassword,
const TMR_TagFilter *filter)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t optbyte, i;
i = 2;
TMR_SR_msgAddGEN2KillTag(msg, &i, timeout, killPassword);
optbyte = 5;
ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg,
0, false);
if (TMR_SUCCESS != ret)
{
return ret;
}
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
TMR_Status
TMR_SR_cmdGEN2ReadTagData(TMR_Reader *reader,
uint16_t timeout, TMR_GEN2_Bank bank,
uint32_t address, uint8_t length,
uint32_t accessPassword, const TMR_TagFilter *filter,
TMR_TagReadData *read)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t optbyte, i, mdfbyte;
uint32_t starttimeHigh, starttimeLow;
i = 2;
TMR_SR_msgAddGEN2DataRead(msg, &i, timeout, bank, address, length, 0x00, true);
optbyte = 5;
ret = filterbytes(TMR_TAG_PROTOCOL_GEN2, filter, &msg[optbyte], &i, msg,
accessPassword, true);
msg[optbyte] |= 0x10;
mdfbyte = 6;
read->metadataFlags |= TMR_TRD_METADATA_FLAG_DATA | TMR_TRD_METADATA_FLAG_PROTOCOL;
SETU16(msg, mdfbyte, read->metadataFlags);
if (TMR_SUCCESS != ret)
{
return ret;
}
msg[1] = i - 3; /* Install length */
/* Cache the read time so it can be put in tag read data later */
tm_gettime_consistent(&starttimeHigh, &starttimeLow);
reader->u.serialReader.readTimeHigh = starttimeHigh;
reader->u.serialReader.readTimeLow = starttimeLow;
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (NULL != read->data.list)
{
i = 8;
TMR_SR_parseMetadataOnly(reader, read, read->metadataFlags , &i, msg);
TMR_SR_postprocessReaderSpecificMetadata(read, &reader->u.serialReader);
/* Read Tag Data doesn't put actual tag data inside the metadata fields.
* Read the actual data here (remainder of response.) */
{
uint16_t dataLength;
uint16_t copyLength;
copyLength = dataLength = msg[1] + 5 - i;
if (copyLength > read->data.max)
{
copyLength = read->data.max;
}
read->data.len = copyLength;
memcpy(read->data.list, &msg[i], copyLength);
i += dataLength;
}
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdSetTxRxPorts(TMR_Reader *reader, uint8_t txPort, uint8_t rxPort)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_ANTENNA_PORT);
SETU8(msg, i, txPort);
SETU8(msg, i, rxPort);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetAntennaSearchList(TMR_Reader *reader, uint8_t count,
const TMR_SR_PortPair *ports)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
uint8_t j;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_ANTENNA_PORT);
SETU8(msg, i, 2); /* logical antenna list option */
for (j = 0; j < count ; j++)
{
SETU8(msg, i, ports[j].txPort);
SETU8(msg, i, ports[j].rxPort);
}
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetAntennaPortPowersAndSettlingTime(
TMR_Reader *reader, uint8_t count, const TMR_SR_PortPowerAndSettlingTime *ports)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t j, i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_ANTENNA_PORT);
SETU8(msg, i, 4); /* power and settling time option */
for (j = 0; j < count; j++)
{
SETU8(msg, i, ports[j].port);
SETS16(msg, i, (int16_t) ports[j].readPower);
SETS16(msg, i, (int16_t)ports[j].writePower);
SETU16(msg, i, ports[j].settlingTime);
}
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetReadTxPower(TMR_Reader *reader, int32_t power)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_READ_TX_POWER);
/** The read power should always be a 16 bit value */
if (power > 32767 || power < -32768)
{
return TMR_ERROR_ILLEGAL_VALUE;
}
SETS16(msg,i, (int16_t)power);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetProtocol(TMR_Reader *reader, TMR_TagProtocol protocol)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_TAG_PROTOCOL);
SETU16(msg, i, protocol);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetWriteTxPower(TMR_Reader *reader, int32_t power)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_WRITE_TX_POWER);
/** The write power should always be a 16 bit value */
if (power > 32767 || power < -32768)
{
return TMR_ERROR_ILLEGAL_VALUE;
}
SETS16(msg, i, (int16_t)power);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetFrequencyHopTable(TMR_Reader *reader, uint8_t count,
const uint32_t *table)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, j;
i = 2;
if (count > 62)
{
return TMR_ERROR_TOO_BIG;
}
SETU8(msg, i, TMR_SR_OPCODE_SET_FREQ_HOP_TABLE);
for (j = 0; j < count; j++)
{
SETU32(msg, i, table[j]);
}
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetFrequencyHopTime(TMR_Reader *reader, uint32_t hopTime)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_FREQ_HOP_TABLE);
SETU8(msg, i, 1); /* hop time option */
SETU32(msg, i, hopTime);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetGPIO(TMR_Reader *reader, uint8_t gpio, bool high)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_USER_GPIO_OUTPUTS);
SETU8(msg, i, gpio);
SETU8(msg, i, (high == true));
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetRegion(TMR_Reader *reader, TMR_Region region)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_REGION);
SETU8(msg, i, region);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetRegionLbt(TMR_Reader *reader, TMR_Region region, bool lbt)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_REGION);
SETU8(msg, i, region);
SETU8(msg, i, lbt ? 1 : 0);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetPowerMode(TMR_Reader *reader, TMR_SR_PowerMode mode)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_POWER_MODE);
SETU8(msg, i, mode);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetUserMode(TMR_Reader *reader, TMR_SR_UserMode mode)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_USER_MODE);
SETU8(msg, i, mode);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdSetReaderConfiguration(TMR_Reader *reader, TMR_SR_Configuration key,
const void *value)
{
TMR_SR_SerialReader *sr = &reader->u.serialReader;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_READER_OPTIONAL_PARAMS);
SETU8(msg, i, 1); /* key-value form of command */
SETU8(msg, i, key);
switch (key)
{
case TMR_SR_CONFIGURATION_ANTENNA_CONTROL_GPIO:
SETU8(msg, i, *(uint8_t *)value);
break;
case TMR_SR_CONFIGURATION_TRIGGER_READ_GPIO:
SETU8(msg, i, *(uint8_t *)value);
break;
case TMR_SR_CONFIGURATION_UNIQUE_BY_ANTENNA:
case TMR_SR_CONFIGURATION_UNIQUE_BY_DATA:
case TMR_SR_CONFIGURATION_UNIQUE_BY_PROTOCOL:
SETU8(msg, i, *(bool *)value ? 0 : 1);
break;
case TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE:
if(TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0])
{
// Open loop power calibration
SETU8(msg, i, *(bool *)value ? 2 : 1);
}
else
{
// Closed loop power calibration
SETU8(msg, i, *(bool *)value ? 1 : 0);
}
break;
case TMR_SR_CONFIGURATION_EXTENDED_EPC:
case TMR_SR_CONFIGURATION_SAFETY_ANTENNA_CHECK:
case TMR_SR_CONFIGURATION_SAFETY_TEMPERATURE_CHECK:
case TMR_SR_CONFIGURATION_RECORD_HIGHEST_RSSI:
case TMR_SR_CONFIGURATION_RSSI_IN_DBM:
case TMR_SR_CONFIGURATION_SELF_JAMMER_CANCELLATION:
case TMR_SR_CONFIGURATION_ENABLE_READ_FILTER:
case TMR_SR_CONFIGURATION_SEND_CRC:
SETU8(msg, i, *(bool *)value ? 1 : 0);
break;
case TMR_SR_CONFIGURATION_READ_FILTER_TIMEOUT:
SETS32(msg, i, *(int32_t *)value);
break;
default:
return TMR_ERROR_NOT_FOUND;
}
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
/**
* Handles license key to enable protocol
*
* @param reader The reader
* @param option Option to set or erase the license key
* @param key license key
* @param key_len Length of license key or the key array
* @param retData The response data
*/
TMR_Status TMR_SR_cmdSetProtocolLicenseKey(TMR_Reader *reader,
TMR_SR_SetProtocolLicenseOption option,
uint8_t key[], int key_len,uint32_t *retData)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
TMR_Status ret;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_PROTOCOL_LICENSEKEY);
SETU8(msg, i, option);
if(TMR_SR_SET_LICENSE_KEY == option)
{
memcpy(msg+i, key, key_len);
i+= key_len;
}
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (ret != TMR_SUCCESS)
{
return ret;
}
reader->u.serialReader.versionInfo.protocols = 0x00;
for (i = 0; i < msg[1] - 2 ; i += 2)
{
reader->u.serialReader.versionInfo.protocols |= (1 << (GETU8AT(msg, 7 + i) - 1));
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdSetProtocolConfiguration(TMR_Reader *reader, TMR_TagProtocol protocol,
TMR_SR_ProtocolConfiguration key,
const void *value)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
uint8_t BLF = 0;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_PROTOCOL_PARAM);
SETU8(msg, i, protocol);
if (TMR_TAG_PROTOCOL_GEN2 == key.protocol)
{
SETU8(msg, i, key.u.gen2);
switch (key.u.gen2)
{
case TMR_SR_GEN2_CONFIGURATION_SESSION:
SETU8(msg, i, *(TMR_GEN2_Session *)value);
break;
case TMR_SR_GEN2_CONFIGURATION_TAGENCODING:
SETU8(msg, i, *(TMR_GEN2_TagEncoding *)value);
break;
case TMR_SR_GEN2_CONFIGURATION_LINKFREQUENCY:
#ifndef BARE_METAL
switch (*(int *)value)
#else
switch (*(TMR_GEN2_LinkFrequency *)value)
#endif
{
case 40:
BLF = 0x03;
break;
case 250:
BLF = 0x00;
break;
case 320:
BLF = 0x02;
break;
case 400:
BLF = 0x02;
break;
case 640:
BLF = 0x04;
break;
default:
return TMR_ERROR_INVALID;
}
SETU8(msg, i, BLF);
break;
case TMR_SR_GEN2_CONFIGURATION_TARI:
SETU8(msg, i, *(TMR_GEN2_Tari *)value);
break;
case TMR_SR_GEN2_CONFIGURATION_PROTCOLEXTENSION:
SETU8(msg, i, *(TMR_GEN2_ProtocolExtension *)value);
break;
case TMR_SR_GEN2_CONFIGURATION_TARGET:
switch (*(TMR_GEN2_Target *)value)
{
case TMR_GEN2_TARGET_A:
SETU16(msg, i, 0x0100);
break;
case TMR_GEN2_TARGET_B:
SETU16(msg, i, 0x0101);
break;
case TMR_GEN2_TARGET_AB:
SETU16(msg, i, 0x0000);
break;
case TMR_GEN2_TARGET_BA:
SETU16(msg, i, 0x0001);
break;
default:
return TMR_ERROR_INVALID;
}
break;
case TMR_SR_GEN2_CONFIGURATION_Q:
{
const TMR_SR_GEN2_Q *q = value;
if (q->type == TMR_SR_GEN2_Q_DYNAMIC)
{
SETU8(msg, i, 0);
}
else if (q->type == TMR_SR_GEN2_Q_STATIC)
{
SETU8(msg, i, 1);
SETU8(msg, i, q->u.staticQ.initialQ);
}
else
{
return TMR_ERROR_INVALID;
}
break;
}
case TMR_SR_GEN2_CONFIGURATION_BAP:
{
TMR_GEN2_Bap *bap;
bap = (TMR_GEN2_Bap *)value;
SETU8(msg, i, 0x01); //version
SETU16(msg, i, 0x03);// currently we supports only this enable bits.
SETU32(msg, i, bap->powerUpDelayUs);
SETU32(msg, i, bap->freqHopOfftimeUs);
/**
* Currently support for M value and FlexQueryPayload has been disabled
* TO DO: add support for these parameters when firmware support has added for this.
**/
break;
}
default:
return TMR_ERROR_NOT_FOUND;
}
}
#ifdef TMR_ENABLE_ISO180006B
else if (TMR_TAG_PROTOCOL_ISO180006B == key.protocol
|| TMR_TAG_PROTOCOL_ISO180006B_UCODE == key.protocol)
{
switch (key.u.iso180006b)
{
case TMR_SR_ISO180006B_CONFIGURATION_LINKFREQUENCY:
{
switch (*(int *)value)
{
case 40:
BLF = 0x01;
break;
case 160:
BLF = 0x00;
break;
default:
return TMR_ERROR_INVALID;
}
break;
}
case TMR_SR_ISO180006B_CONFIGURATION_MODULATION_DEPTH:
{
switch (*(int *)value)
{
case 0:
BLF = TMR_ISO180006B_Modulation99percent;
break;
case 1:
BLF = TMR_ISO180006B_Modulation11percent;
break;
default:
return TMR_ERROR_INVALID;
}
break;
}
case TMR_SR_ISO180006B_CONFIGURATION_DELIMITER:
{
switch (*(int *)value)
{
case 1:
BLF = TMR_ISO180006B_Delimiter1;
break;
case 4:
BLF = TMR_ISO180006B_Delimiter4;
break;
default:
return TMR_ERROR_INVALID;
}
break;
}
default:
return TMR_ERROR_NOT_FOUND;
}
SETU8(msg, i, key.u.iso180006b);
SETU8(msg, i, BLF);
}
#endif /* TMR_ENABLE_ISO180006B */
else
{
return TMR_ERROR_INVALID;
}
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status TMR_SR_cmdGetTxRxPorts(TMR_Reader *reader, TMR_SR_PortPair *ant)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_ANTENNA_PORT);
SETU8(msg, i, 0); /* just configured ports */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
ant->txPort = msg[5];
ant->rxPort = msg[6];
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdAntennaDetect(TMR_Reader *reader, uint8_t *count,
TMR_SR_PortDetect *ports)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, j;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_ANTENNA_PORT);
SETU8(msg, i, 5); /* antenna detect option */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
for (i = 1, j = 0; i < msg[1] && j < *count; i += 2, j++)
{
ports[j].port = msg[i + 5];
ports[j].detected = (msg[i + 6] == 1);
}
*count = j;
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetAntennaPortPowersAndSettlingTime(
TMR_Reader *reader, uint8_t *count, TMR_SR_PortPowerAndSettlingTime *ports)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, j;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_ANTENNA_PORT);
SETU8(msg, i, 4); /* power and settling time option */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
for (i = 1, j = 0; i < msg[1] && j < *count; i += 7, j++)
{
ports[j].port = GETU8AT(msg, i + 5);
ports[j].readPower = (int16_t)GETS16AT(msg, i + 6);
ports[j].writePower = (int16_t)GETS16AT(msg, i + 8);
ports[j].settlingTime = GETU16AT(msg, i + 10);
}
*count = j;
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetAntennaReturnLoss(TMR_Reader *reader, TMR_PortValueList *ports)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, j, count;
count = TMR_SR_MAX_ANTENNA_PORTS;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_ANTENNA_PORT);
SETU8(msg, i, 6); /* antenna return loss option */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
for (i = 1, j = 0; i < msg[1] && j < count; i += 2, j++)
{
if (j < ports->max)
{
ports->list[j].port = (uint8_t)GETU8AT(msg, i + 5);
ports->list[j].value = (int16_t)GETU8AT(msg, i + 6);
}
else
{
/* no sufficent memory, break from here */
break;
}
}
ports->len = (uint8_t)j;
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetReadTxPower(TMR_Reader *reader, int32_t *power)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_READ_TX_POWER);
SETU8(msg, i, 0); /* just return power */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*power = (int32_t)GETS16AT(msg, 6);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetReadTxPowerWithLimits(TMR_Reader *reader,
TMR_SR_PowerWithLimits *power)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_READ_TX_POWER);
SETU8(msg, i, 1); /* return limits */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
power->setPower = GETU16AT(msg, 6);
power->maxPower = GETU16AT(msg, 8);
power->minPower = GETU16AT(msg, 10);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetWriteTxPower(TMR_Reader *reader, int32_t *power)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_WRITE_TX_POWER);
SETU8(msg, i, 0); /* just return power */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*power = (int32_t)GETS16AT(msg, 6);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetFrequencyHopTable(TMR_Reader *reader, uint8_t *count,
uint32_t *hopTable)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, j, len;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_FREQ_HOP_TABLE);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
len = msg[1] / 4;
for (j = 0; i < *count && j < len ; j++)
{
hopTable[j] = GETU32AT(msg, 5 + 4*j);
}
*count = len;
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetFrequencyHopTime(TMR_Reader *reader, uint32_t *hopTime)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_FREQ_HOP_TABLE);
SETU8(msg, i, 1); /* get time */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*hopTime = GETU32AT(msg, 6);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetGPIO(TMR_Reader *reader, uint8_t *count, TMR_GpioPin *state)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE] = {0};
uint8_t i, j, len, offset;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_USER_GPIO_INPUTS);
SETU8(msg, i, 0x01); // option
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);
if (TMR_SUCCESS != ret)
return ret;
len = (msg[1] - 1)/3;
if (len > *count)
{
len = *count;
}
offset = 6;
for (j = 0; j < len ; j++)
{
state[j].id = msg[offset++];
state[j].output = (1 == msg[offset++]) ? true : false;
state[j].high = (1 == msg[offset++]) ? true : false;
}
*count = len;
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetGPIODirection(TMR_Reader *reader, uint8_t pin, bool *out)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_USER_GPIO_OUTPUTS);
SETU8(msg, i, pin);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
return ret;
*out = (msg[6] == 1);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdSetGPIODirection(TMR_Reader *reader, uint8_t pin, bool out)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_USER_GPIO_OUTPUTS);
SETU8(msg, i, 1); /* Option flag */
SETU8(msg, i, pin);
SETU8(msg, i, (out == true) ? 1 : 0);
SETU8(msg, i, 0); /* New value if output */
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
return ret;
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetCurrentProtocol(TMR_Reader *reader, TMR_TagProtocol *protocol)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_TAG_PROTOCOL);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*protocol = (TMR_TagProtocol)GETU16AT(msg, 5);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetRegion(TMR_Reader *reader, TMR_Region *region)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_REGION);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*region = (TMR_Region)GETU8AT(msg, 5);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetRegionConfiguration(TMR_Reader *reader,
TMR_SR_RegionConfiguration key,
void *value)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_REGION);
SETU8(msg, i, 1);
SETU8(msg, i, key);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
switch (key)
{
case TMR_SR_REGION_CONFIGURATION_LBT_ENABLED:
*(bool *)value = (GETU8AT(msg, 8) == 1);
break;
default:
return TMR_ERROR_NOT_FOUND;
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetPowerMode(TMR_Reader *reader, TMR_SR_PowerMode *mode)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_POWER_MODE);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*mode = (TMR_SR_PowerMode)GETU8AT(msg, 5);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetUserMode(TMR_Reader *reader, TMR_SR_UserMode *mode)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_USER_MODE);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*mode = (TMR_SR_UserMode)GETU8AT(msg, 5);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetReaderConfiguration(TMR_Reader *reader, TMR_SR_Configuration key,
void *value)
{
TMR_SR_SerialReader *sr = &reader->u.serialReader;
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_READER_OPTIONAL_PARAMS);
SETU8(msg, i, 1); /* key-value form of command */
SETU8(msg, i, key);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
switch (key)
{
case TMR_SR_CONFIGURATION_ANTENNA_CONTROL_GPIO:
*(uint8_t *)value = GETU8AT(msg, 7);
break;
case TMR_SR_CONFIGURATION_TRIGGER_READ_GPIO:
*(uint8_t *)value = GETU8AT(msg, 7);
break;
case TMR_SR_CONFIGURATION_UNIQUE_BY_ANTENNA:
case TMR_SR_CONFIGURATION_UNIQUE_BY_DATA:
case TMR_SR_CONFIGURATION_UNIQUE_BY_PROTOCOL:
*(bool *)value = (GETU8AT(msg, 7) == 0);
break;
case TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE:
if(TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0])
{
if(GETU8AT(msg, 7) == 2)
{
//Open loop power calibration
*(bool *)value = 1;
}
else
{
//Closed loop power calibration
*(bool *)value = 0;
}
}
else
{
*(bool *)value = (GETU8AT(msg, 7) == 1);
}
break;
case TMR_SR_CONFIGURATION_EXTENDED_EPC:
case TMR_SR_CONFIGURATION_SAFETY_ANTENNA_CHECK:
case TMR_SR_CONFIGURATION_SAFETY_TEMPERATURE_CHECK:
case TMR_SR_CONFIGURATION_RECORD_HIGHEST_RSSI:
case TMR_SR_CONFIGURATION_RSSI_IN_DBM:
case TMR_SR_CONFIGURATION_SELF_JAMMER_CANCELLATION:
case TMR_SR_CONFIGURATION_ENABLE_READ_FILTER:
case TMR_SR_CONFIGURATION_SEND_CRC:
*(bool *)value = (GETU8AT(msg, 7) == 1);
break;
case TMR_SR_CONFIGURATION_CURRENT_MSG_TRANSPORT:
*(uint8_t *)value = GETU8AT(msg, 7) ;
break;
case TMR_SR_CONFIGURATION_READ_FILTER_TIMEOUT:
*(uint32_t *)value = GETU32AT(msg, 7);
break;
case TMR_SR_CONFIGURATION_PRODUCT_GROUP_ID:
*(uint16_t *)value = GETU16AT(msg, 7);
break;
case TMR_SR_CONFIGURATION_PRODUCT_ID:
*(uint16_t *)value = GETU16AT(msg, 7);
break;
default:
return TMR_ERROR_NOT_FOUND;
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetProtocolConfiguration(TMR_Reader *reader, TMR_TagProtocol protocol,
TMR_SR_ProtocolConfiguration key,
void *value)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_PROTOCOL_PARAM);
SETU8(msg, i, protocol);
if (TMR_TAG_PROTOCOL_GEN2 == key.protocol)
{
SETU8(msg, i, key.u.gen2);
}
#ifdef TMR_ENABLE_ISO180006B
else if (TMR_TAG_PROTOCOL_ISO180006B == key.protocol
|| TMR_TAG_PROTOCOL_ISO180006B_UCODE == key.protocol)
{
SETU8(msg, i, key.u.iso180006b);
}
#endif
else
{
return TMR_ERROR_INVALID;
}
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (TMR_TAG_PROTOCOL_GEN2 == key.protocol)
{
switch (key.u.gen2)
{
case TMR_SR_GEN2_CONFIGURATION_SESSION:
*(TMR_GEN2_Session *)value = (TMR_GEN2_Session)GETU8AT(msg, 7);
break;
case TMR_SR_GEN2_CONFIGURATION_TAGENCODING:
*(TMR_GEN2_TagEncoding *)value = (TMR_GEN2_TagEncoding)GETU8AT(msg, 7);
break;
case TMR_SR_GEN2_CONFIGURATION_LINKFREQUENCY:
*(TMR_GEN2_LinkFrequency *)value = (TMR_GEN2_LinkFrequency)GETU8AT(msg, 7);
break;
case TMR_SR_GEN2_CONFIGURATION_TARI:
*(TMR_GEN2_Tari *)value = (TMR_GEN2_Tari)GETU8AT(msg, 7);
break;
case TMR_SR_GEN2_CONFIGURATION_PROTCOLEXTENSION:
*(TMR_GEN2_ProtocolExtension *)value = (TMR_GEN2_ProtocolExtension)GETU8AT(msg, 7);
break;
case TMR_SR_GEN2_CONFIGURATION_BAP:
{
TMR_GEN2_Bap *b = value;
i = 10;
b->powerUpDelayUs = GETU32(msg,i);
b->freqHopOfftimeUs = GETU32(msg,i);
break;
}
case TMR_SR_GEN2_CONFIGURATION_TARGET:
{
uint16_t target;
target = GETU16AT(msg, 7);
switch (target)
{
case 0x0100:
*(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_A;
break;
case 0x0101:
*(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_B;
break;
case 0x0000:
*(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_AB;
break;
case 0x0001:
*(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_BA;
break;
default:
*(TMR_GEN2_Target *)value = TMR_GEN2_TARGET_INVALID;
}
break;
}
case TMR_SR_GEN2_CONFIGURATION_Q:
{
TMR_SR_GEN2_Q *q = value;
q->type = (TMR_SR_GEN2_QType)GETU8AT(msg, 7);
if (q->type == TMR_SR_GEN2_Q_DYNAMIC)
{
; /* No further data to get */
}
else if (q->type == TMR_SR_GEN2_Q_STATIC)
{
q->u.staticQ.initialQ = GETU8AT(msg, 8);
}
break;
}
default:
return TMR_ERROR_NOT_FOUND;
}
}
#ifdef TMR_ENABLE_ISO180006B
else if (TMR_TAG_PROTOCOL_ISO180006B == key.protocol
|| TMR_TAG_PROTOCOL_ISO180006B_UCODE == key.protocol)
{
switch (key.u.iso180006b)
{
case TMR_SR_ISO180006B_CONFIGURATION_LINKFREQUENCY:
{
TMR_iso18000BBLFValToInt(GETU8AT(msg, 7), value);
break;
}
case TMR_SR_ISO180006B_CONFIGURATION_MODULATION_DEPTH:
{
uint8_t val;
val = GETU8AT(msg, 7);
switch (val)
{
case 0:
*(TMR_ISO180006B_ModulationDepth *)value = TMR_ISO180006B_Modulation99percent;
break;
case 1:
*(TMR_ISO180006B_ModulationDepth *)value = TMR_ISO180006B_Modulation11percent;
break;
default:
return TMR_ERROR_NOT_FOUND;
}
break;
}
case TMR_SR_ISO180006B_CONFIGURATION_DELIMITER:
{
uint8_t val;
val = GETU8AT(msg, 7);
switch (val)
{
case 1:
*(TMR_ISO180006B_Delimiter *)value = TMR_ISO180006B_Delimiter1;
break;
case 4:
*(TMR_ISO180006B_Delimiter *)value = TMR_ISO180006B_Delimiter4;
break;
default:
return TMR_ERROR_NOT_FOUND;
}
break;
}
default:
return TMR_ERROR_NOT_FOUND;
}
}
#endif /* TMR_ENABLE_ISO180006B */
else
{
return TMR_ERROR_INVALID;
}
return TMR_SUCCESS;
}
TMR_Status TMR_iso18000BBLFValToInt(int val, void *lf)
{
switch (val)
{
case 1:
*(TMR_ISO180006B_LinkFrequency *)lf = TMR_ISO180006B_LINKFREQUENCY_40KHZ;
break;
case 0:
*(TMR_ISO180006B_LinkFrequency *)lf = TMR_ISO180006B_LINKFREQUENCY_160KHZ;
break;
default:
return TMR_ERROR_NOT_FOUND;
}
return TMR_SUCCESS;
}
/* Helper function to frame the multiple protocol search command */
TMR_Status
TMR_SR_msgSetupMultipleProtocolSearch(TMR_Reader *reader, uint8_t *msg, TMR_SR_OpCode op, TMR_TagProtocolList *protocols, TMR_TRD_MetadataFlag metadataFlags, TMR_SR_SearchFlag antennas, TMR_TagFilter **filter, uint16_t timeout)
{
TMR_Status ret;
uint8_t i;
uint32_t j;
uint16_t subTimeout;
ret = TMR_SUCCESS;
i=2;
SETU8(msg, i, TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP); //Opcode
if(reader->continuousReading)
{
/* Timeout should be zero for true continuous reading */
SETU16(msg, i, 0);
SETU8(msg, i, (uint8_t)0x1);//TM Option 1, for continuous reading
}
else
{
SETU16(msg, i, timeout); //command timeout
SETU8(msg, i, (uint8_t)0x11);//TM Option, turns on metadata
SETU16(msg, i, (uint16_t)metadataFlags);
}
SETU8(msg, i, (uint8_t)op);//sub command opcode
if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)
{
reader->isStopNTags = false;
/**
* in case of multi read plan look for the stop N trigger option
**/
for (j = 0; j < reader->readParams.readPlan->u.multi.planCount; j++)
{
if (reader->readParams.readPlan->u.multi.plans[j]->u.simple.stopOnCount.stopNTriggerStatus)
{
reader->numberOfTagsToRead += reader->readParams.readPlan->u.multi.plans[j]->u.simple.stopOnCount.noOfTags;
reader->isStopNTags = true;
}
}
}
else
{
reader->numberOfTagsToRead += reader->readParams.readPlan->u.simple.stopOnCount.noOfTags;
}
if (reader->isStopNTags && !reader->continuousReading)
{
/**
* True means atlest one sub read plan has the requested for stop N trigger.
* Enable the flag and add the total tag count. This is only supported for sync read
* case.
*/
SETU16(msg, i, (uint16_t)TMR_SR_SEARCH_FLAG_RETURN_ON_N_TAGS);
SETU32(msg, i, reader->numberOfTagsToRead);
}
else
{
SETU16(msg, i, (uint16_t)0x0000);//search flags, only 0x0001 is supported
}
/**
* TODO:add the timeout as requested by the user
**/
subTimeout =(uint16_t)(timeout/(protocols->len));
for (j=0;j<protocols->len;j++) // iterate through the protocol search list
{
int PLenIdx;
TMR_TagProtocol subProtocol=protocols->list[j];
SETU8(msg, i, (uint8_t)(subProtocol)); //protocol ID
PLenIdx = i;
SETU8(msg, i, 0); //PLEN
/**
* in case of multi readplan and the total weight is not zero,
* we should use the weight as provided by the user.
**/
if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)
{
if (0 != reader->readParams.readPlan->u.multi.totalWeight)
{
subTimeout = (uint16_t)(reader->readParams.readPlan->u.multi.plans[j]->weight * timeout
/ reader->readParams.readPlan->u.multi.totalWeight);
}
}
/**
* In case of Multireadplan, check each simple read plan FastSearch option and
* stop N trigger option.
*/
if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)
{
reader->fastSearch = reader->readParams.readPlan->u.multi.plans[j]->u.simple.useFastSearch;
reader->triggerRead = reader->readParams.readPlan->u.multi.plans[j]->u.simple.triggerRead.enable;
reader->isStopNTags = false;
reader->isStopNTags = reader->readParams.readPlan->u.multi.plans[j]->u.simple.stopOnCount.stopNTriggerStatus;
reader->numberOfTagsToRead = reader->readParams.readPlan->u.multi.plans[j]->u.simple.stopOnCount.noOfTags;
}
switch(op)
{
case TMR_SR_OPCODE_READ_TAG_ID_SINGLE :
{
ret = TMR_SR_msgSetupReadTagSingle(msg, &i, subProtocol,metadataFlags, filter[j], subTimeout);
break;
}
case TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE:
{
/**
* simple read plan uses this function, only when tagop is NULL,
* s0, need to check for simple read plan tagop.
**/
if (TMR_READ_PLAN_TYPE_MULTI == reader->readParams.readPlan->type)
{
/* check for the tagop */
if (NULL != reader->readParams.readPlan->u.multi.plans[j]->u.simple.tagop)
{
uint32_t readTimeMs = (uint32_t)subTimeout;
uint8_t lenbyte = 0;
//add the tagoperation here
ret = TMR_SR_addTagOp(reader,reader->readParams.readPlan->u.multi.plans[j]->u.simple.tagop,
reader->readParams.readPlan->u.multi.plans[j], msg, &i, readTimeMs, &lenbyte);
}
else
{
ret = TMR_SR_msgSetupReadTagMultipleWithMetadata(reader, msg, &i, subTimeout, antennas, metadataFlags ,filter[j], subProtocol, 0);
}
}
else
{
if (NULL != reader->readParams.readPlan->u.simple.tagop)
{
uint32_t readTimeMs = (uint32_t)subTimeout;
uint8_t lenbyte = 0;
//add the tagoperation here
ret = TMR_SR_addTagOp(reader, reader->readParams.readPlan->u.simple.tagop,
reader->readParams.readPlan, msg, &i, readTimeMs, &lenbyte);
}
else
{
ret = TMR_SR_msgSetupReadTagMultipleWithMetadata(reader, msg, &i, subTimeout, antennas, metadataFlags ,filter[j], subProtocol, 0);
}
}
break;
}
default :
{
return TMR_ERROR_INVALID_OPCODE;
}
}
msg[PLenIdx]= i - PLenIdx - 2; //PLEN
msg[1]=i - 3;
}
return ret;
}
TMR_Status TMR_SR_cmdMultipleProtocolSearch(TMR_Reader *reader,TMR_SR_OpCode op,TMR_TagProtocolList *protocols, TMR_TRD_MetadataFlag metadataFlags,TMR_SR_SearchFlag antennas, TMR_TagFilter **filter, uint16_t timeout, uint32_t *tagsFound)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
TMR_SR_SerialReader *sr;
sr = &reader->u.serialReader;
*tagsFound = 0 ;
ret = TMR_SR_msgSetupMultipleProtocolSearch(reader, msg, op, protocols, metadataFlags, antennas, filter, timeout);
if (ret != TMR_SUCCESS)
{
return ret;
}
if (op == TMR_SR_OPCODE_READ_TAG_ID_SINGLE)
{
uint8_t opcode;
sr->opCode = op;
ret = TMR_SR_sendMessage(reader, msg, &opcode, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
sr->tagsRemaining = 1;
}
if (op == TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE)
{
sr->opCode = op;
if(reader->continuousReading)
{
uint8_t opcode;
ret = TMR_SR_sendMessage(reader, msg, &opcode, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
reader->hasContinuousReadStarted = true;
sr->tagsRemaining=1;
}
else
{
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_ERROR_NO_TAGS_FOUND == ret)
{
sr->tagsRemaining = *tagsFound = 0;
return ret;
}
else if ((TMR_ERROR_TM_ASSERT_FAILED == ret) ||
(TMR_ERROR_TIMEOUT == ret))
{
return ret;
}
else if (TMR_SUCCESS != ret)
{
uint16_t remainingTagsCount;
TMR_Status ret1;
/* Check for the tag count (in case of module error)*/
ret1 = TMR_SR_cmdGetTagsRemaining(reader, &remainingTagsCount);
if (TMR_SUCCESS != ret1)
{
return ret1;
}
*tagsFound = remainingTagsCount;
sr->tagsRemaining = *tagsFound;
return ret;
}
*tagsFound = GETU32AT(msg , 9);
sr->tagsRemaining = *tagsFound;
}
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetAvailableProtocols(TMR_Reader *reader,
TMR_TagProtocolList *protocols)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_AVAILABLE_PROTOCOLS);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
protocols->len = 0;
for (i = 0; i < msg[1] ; i += 2)
{
LISTAPPEND(protocols, (TMR_TagProtocol)GETU16AT(msg, 5 + i));
}
reader->u.serialReader.versionInfo.protocols = 0x0000;
for (i = 0 ; i < protocols->len; i ++)
{
reader->u.serialReader.versionInfo.protocols |= (1 << (protocols->list[i] - 1));
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetAvailableRegions(TMR_Reader *reader, TMR_RegionList *regions)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_AVAILABLE_REGIONS);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
regions->len = 0;
for (i = 0; i < msg[1] ; i++)
{
LISTAPPEND(regions, (TMR_Region)GETU8AT(msg, 5 + i));
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdGetTemperature(TMR_Reader *reader, int8_t *temp)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_TEMPERATURE);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
*temp = msg[5];
return TMR_SUCCESS;
}
static TMR_Status
filterbytes(TMR_TagProtocol protocol, const TMR_TagFilter *filter,
uint8_t *option, uint8_t *i, uint8_t *msg,
uint32_t accessPassword, bool usePassword)
{
int j;
if (isSecureAccessEnabled)
{
*option = TMR_SR_GEN2_SINGULATION_OPTION_SECURE_READ_DATA;
}
if (NULL == filter && 0 == accessPassword)
{
*option = 0x00;
return TMR_SUCCESS;
}
if (TMR_TAG_PROTOCOL_GEN2 == protocol)
{
if (usePassword)
{
if (filter && TMR_FILTER_TYPE_GEN2_SELECT == filter->type)
{
if (filter->u.gen2Select.bank != TMR_GEN2_EPC_LENGTH_FILTER)
SETU32(msg, *i, accessPassword);
}
else
{
SETU32(msg, *i, accessPassword);
}
}
if (NULL == filter)
{
*option |= TMR_SR_GEN2_SINGULATION_OPTION_USE_PASSWORD;
}
else if (TMR_FILTER_TYPE_GEN2_SELECT == filter->type)
{
const TMR_GEN2_Select *fp;
fp = &filter->u.gen2Select;
if (1 == fp->bank)
{
*option |= TMR_SR_GEN2_SINGULATION_OPTION_SELECT_ON_ADDRESSED_EPC;
}
else /* select based on the bank */
{
*option |= fp->bank;
}
if (fp->bank == TMR_GEN2_EPC_LENGTH_FILTER)
{
SETU16(msg, *i, fp->maskBitLength);
}
else
{
if(true == fp->invert)
{
*option |= TMR_SR_GEN2_SINGULATION_OPTION_INVERSE_SELECT_BIT;
}
if (fp->maskBitLength > 255)
{
*option |= TMR_SR_GEN2_SINGULATION_OPTION_EXTENDED_DATA_LENGTH;
}
SETU32(msg, *i, fp->bitPointer);
if (fp->maskBitLength > 255)
{
SETU8(msg, *i, (fp->maskBitLength >> 8) & 0xFF);
}
SETU8(msg, *i, fp->maskBitLength & 0xFF);
if (*i + 1 + tm_u8s_per_bits(fp->maskBitLength) > TMR_SR_MAX_PACKET_SIZE)
{
return TMR_ERROR_TOO_BIG;
}
for(j = 0; j < tm_u8s_per_bits(fp->maskBitLength) ; j++)
{
SETU8(msg, *i, fp->mask[j]);
}
}
}
else if (TMR_FILTER_TYPE_TAG_DATA == filter->type)
{
const TMR_TagData *fp;
int bitCount;
fp = &filter->u.tagData;
bitCount = fp->epcByteCount * 8;
/* select on the EPC */
*option |= 1;
if (bitCount > 255)
{
*option |= TMR_SR_GEN2_SINGULATION_OPTION_EXTENDED_DATA_LENGTH;
SETU8(msg, *i, (bitCount>>8) & 0xFF);
}
SETU8(msg, *i, (bitCount & 0xFF));
if (*i + 1 + fp->epcByteCount > TMR_SR_MAX_PACKET_SIZE)
{
return TMR_ERROR_TOO_BIG;
}
for(j = 0 ; j < fp->epcByteCount ; j++)
{
SETU8(msg, *i, fp->epc[j]);
}
}
else
{
return TMR_ERROR_INVALID;
}
}
#ifdef TMR_ENABLE_ISO180006B
else if (TMR_TAG_PROTOCOL_ISO180006B == protocol)
{
if (option)
{
*option = 1;
}
if (NULL == filter)
{
/* Set up a match-anything filter, since it isn't the default */
SETU8(msg, *i, TMR_ISO180006B_SELECT_OP_EQUALS);
SETU8(msg, *i, 0); /* address */
SETU8(msg, *i, 0); /* mask - don't compare anything */
SETU32(msg, *i, 0); /* dummy tag ID bytes 0-3, not compared */
SETU32(msg, *i, 0); /* dummy tag ID bytes 4-7, not compared */
return TMR_SUCCESS;
}
else if (TMR_FILTER_TYPE_ISO180006B_SELECT == filter->type)
{
const TMR_ISO180006B_Select *fp;
fp = &filter->u.iso180006bSelect;
if (false == fp->invert)
{
SETU8(msg, *i, fp->op);
}
else
{
SETU8(msg, *i, fp->op | 4);
}
SETU8(msg, *i, fp->address);
SETU8(msg, *i, fp->mask);
for (j = 0 ; j < 8 ; j++)
{
SETU8(msg, *i, fp->data[j]);
}
}
else if (TMR_FILTER_TYPE_TAG_DATA == filter->type)
{
const TMR_TagData *fp;
uint8_t mask;
fp = &filter->u.tagData;
if (fp->epcByteCount > 8)
{
return TMR_ERROR_INVALID;
}
/* Convert the byte count to a MSB-based bit mask */
mask = (0xff00 >> fp->epcByteCount) & 0xff;
SETU8(msg, *i, TMR_ISO180006B_SELECT_OP_EQUALS);
SETU8(msg, *i, 0); /* Address - EPC is at the start of memory */
SETU8(msg, *i, mask);
for (j = 0 ; j < fp->epcByteCount; j++)
{
SETU8(msg, *i, fp->epc[j]);
}
for ( ; j < 8 ; j++)
{
SETU8(msg, *i, 0); /* EPC data must be 8 bytes */
}
}
else
{
return TMR_ERROR_INVALID;
}
}
#endif /* TMR_ENABLE_ISO180006B */
else
{
return TMR_ERROR_INVALID;
}
return TMR_SUCCESS;
}
/**
* Alien Higgs2 and Higgs3 Specific Commands
**/
/** Helper routine to form the Higgs2 Partial Load Image command **/
void TMR_SR_msgAddHiggs2PartialLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint8_t len, const uint8_t *epc, TMR_TagFilter* target)
{
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS_SILICON); /* Chip - type*/
SETU8(msg, *i, (uint8_t)0x01); /* Sub command, partial load image */
SETU32(msg, *i, killPassword);
SETU32(msg, *i, accessPassword);
memcpy(&msg[*i], epc, len);
*i += len;
}
/**
* Partial Load Image (only 96-bit EPC with no user memory versions)
* Chip type = 0x01
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to write on the tag
* @param killPassword The kill password to write on the tag
* @param len Length of the EPC
* @param epc The EPC to write to the tag. Maximum of 12 bytes (96 bits)
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdHiggs2PartialLoadImage(TMR_Reader *reader, uint16_t timeout,
TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword,
uint8_t len, const uint8_t epc[], TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
if(NULL != target)
{
return TMR_ERROR_UNSUPPORTED;
}
TMR_SR_msgAddHiggs2PartialLoadImage(msg, &i, timeout, accessPassword, killPassword, len, epc, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/** Helper routine to form the Higgs2 Full Load Image command **/
void TMR_SR_msgAddHiggs2FullLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t lockBits, uint16_t pcWord, uint8_t len, const uint8_t *epc, TMR_TagFilter* target)
{
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS_SILICON); /* Chip - type*/
SETU8(msg, *i, (uint8_t)0x03); /* Sub command, full load image */
SETU32(msg, *i, killPassword);
SETU32(msg, *i, accessPassword);
SETU16(msg, *i, lockBits);
SETU16(msg, *i, pcWord);
memcpy(&msg[*i], epc, len);
*i += len;
}
/**
* Full Load Image (only 96-bit EPC with no user memory versions)
* Chip type = 0x01
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to write on the tag
* @param killPassword The kill password to write on the tag
* @param lockBits locking the tag according to the Alien Higgs LockBits
* @param pcWord PC Word in the Tag EPC memBank defined in the Gen2 Specification
* @param len Length of the EPC
* @param epc The EPC to write to the tag. Maximum of 12 bytes (96 bits)
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdHiggs2FullLoadImage(TMR_Reader *reader, uint16_t timeout,
TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword,
uint16_t lockBits, uint16_t pcWord, uint8_t len,
const uint8_t epc[], TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
if(NULL != target)
{
return TMR_ERROR_UNSUPPORTED;
}
TMR_SR_msgAddHiggs2FullLoadImage(msg, &i, timeout, accessPassword, killPassword, lockBits, pcWord, len, epc, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/** Helper routine to form the Higgs3 Fast Load Image command **/
void TMR_SR_msgAddHiggs3FastLoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password currentAccessPassword,
TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t pcWord, uint8_t len, const uint8_t *epc, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS3_SILICON); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x01); /* Sub command, fast load image */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false);
msg[rec]=msg[rec]|option;
SETU32(msg, *i, currentAccessPassword);
SETU32(msg, *i, killPassword);
SETU32(msg, *i, accessPassword);
SETU16(msg, *i, pcWord);
memcpy(&msg[*i], epc, len);
*i += len;
}
/**
* Higgs3 Fast Load Image (only 96-bit EPC)
* Chip type = 0x05
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param currentAccessPassword The access password to use to write to the tag
* @param accessPassword The access password to write on the tag
* @param killPassword The kill password to write on the tag
* @param pcWord PC Word in the Tag EPC memBank defined in the Gen2 Specification
* @param len Length of the EPC
* @param epc The EPC to write to the tag. Maximum of 12 bytes (96 bits)
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdHiggs3FastLoadImage(TMR_Reader *reader, uint16_t timeout,
TMR_GEN2_Password currentAccessPassword, TMR_GEN2_Password accessPassword,
TMR_GEN2_Password killPassword, uint16_t pcWord, uint8_t len, const uint8_t epc[], TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddHiggs3FastLoadImage(msg, &i, timeout, currentAccessPassword, accessPassword, killPassword, pcWord, len, epc, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/** Helper routine to form the Higgs3 Load Image command **/
void TMR_SR_msgAddHiggs3LoadImage(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password currentAccessPassword,
TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword, uint16_t pcWord, uint8_t len, const uint8_t *epcAndUserData, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS3_SILICON); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x03); /* Sub command, Load image */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false);
msg[rec]=msg[rec]|option;
SETU32(msg, *i, currentAccessPassword);
SETU32(msg, *i, killPassword);
SETU32(msg, *i, accessPassword);
SETU16(msg, *i, pcWord);
memcpy(&msg[*i], epcAndUserData, len);
*i += len;
}
/**
* Higgs3 Load Image
* Chip type = 0x05
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param currentAccessPassword The access password to use to write to the tag
* @param accessPassword The access password to write on the tag
* @param killPassword The kill password to write on the tag
* @param pcWord PC Word in the Tag EPC memBank defined in the Gen2 Specification
* @param len Length of epcAndUserData
* @param epcAndUserData The EPC and user data to write to the tag. Must be exactly 76 bytes.
* The pcWord specifies which of this is EPC and which is user data.
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdHiggs3LoadImage(TMR_Reader *reader, uint16_t timeout,
TMR_GEN2_Password currentAccessPassword,
TMR_GEN2_Password accessPassword, TMR_GEN2_Password killPassword,
uint16_t pcWord, uint8_t len, const uint8_t epcAndUserData[], TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddHiggs3LoadImage(msg, &i, timeout, currentAccessPassword, accessPassword,
killPassword, pcWord, len, epcAndUserData, target); /* Length of epcAndUserData must be 76 */
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/** Helper routine to form the Higgs3 Block Read Lock command**/
void TMR_SR_msgAddHiggs3BlockReadLock(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_GEN2_Password accessPassword, uint8_t lockBits, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_ALIEN_HIGGS3_SILICON); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x09); /* Sub command, Block Read Lock */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false);
msg[rec]=msg[rec]|option;
SETU32(msg, *i, accessPassword);
SETU8(msg, *i, lockBits);
}
/**
* Higgs3 Block Read Lock
* Chip type = 0x05
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param lockBits A bitmask of bits to lock. Valid range 0-255
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdHiggs3BlockReadLock(TMR_Reader *reader, uint16_t timeout,
TMR_GEN2_Password accessPassword, uint8_t lockBits, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddHiggs3BlockReadLock(msg, &i, timeout, accessPassword, lockBits, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* NXP Silicon (G2xL and G2iL) Specific Commands
* Chip Type = 0x02 and 0x07
**/
/** Helper routine to form the NXP Set Read Protect command**/
void TMR_SR_msgAddNXPSetReadProtect(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x01); /* Sub command, Set Read Protect */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false);
msg[rec]=msg[rec]|option;
SETU32(msg, *i, accessPassword);
}
/** Helper routine to form the NXP Set Read Protect command**/
void TMR_SR_msgAddNXPResetReadProtect(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x02); /* Sub command, Reset Read Protect */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false);
msg[rec]=msg[rec]|option;
SETU32(msg, *i, accessPassword);
}
/**
* NXP Set Read Protect
* Chip type = 0x02 or 0x07, Command = 0x01
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param chip The NXP Chip type (G2iL or G2xL)
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdNxpSetReadProtect(TMR_Reader *reader, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddNXPSetReadProtect(msg, &i, timeout, chip, accessPassword, target); /* set read protect */
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* NXP Reset Read Protect
* Chip type = 0x02 or 0x07, Command = 0x02
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param chip The NXP Chip type (G2iL or G2xL)
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdNxpResetReadProtect(TMR_Reader *reader, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddNXPResetReadProtect(msg, &i, timeout, chip, accessPassword, target); /* Reset read protect */
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/** Helper routine to form the NXP Change EAS command**/
void TMR_SR_msgAddNXPChangeEAS(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, bool reset, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x03); /* Sub command, Change EAS */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false);
msg[rec]=msg[rec]|option;
SETU32(msg, *i, accessPassword);
if(reset)
{
SETU8(msg, *i, (uint8_t)0x02); /* reset EAS */
}
else
{
SETU8(msg, *i, (uint8_t)0x01); /* set EAS */
}
}
/**
* NXP Change EAS
* Chip type = 0x02 or 0x07, Command = 0x03
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param chip The NXP Chip type (G2iL or G2xL)
* @param accessPassword The access password to use to write on the tag
* @param reset Reset or set EAS bit
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdNxpChangeEas(TMR_Reader *reader, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, bool reset, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddNXPChangeEAS(msg, &i, timeout, chip, accessPassword, reset, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/** Helper routine to form the NXP EAS Alarm command **/
void TMR_SR_msgAddNXPEASAlarm(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt, TMR_TagFilter* target)
{
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x04); /* Sub command, EAS Alarm */
SETU8(msg, *i, (uint8_t)dr);
SETU8(msg, *i, (uint8_t)m);
SETU8(msg, *i, (uint8_t)trExt);
}
/**
* NXP EAS Alarm
* Chip type = 0x02 or 0x07, Command = 0x04
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param chip The NXP Chip type (G2iL or G2xL)
* @param dr Gen2 divide ratio to use
* @param m Gen2 M(tag encoding) parameter to use
* @param trExt Gen2 TrExt value to use
* @param data 8 bytes of EAS alarm data will be returned, on successful operation
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdNxpEasAlarm(TMR_Reader *reader, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_DivideRatio dr, TMR_GEN2_TagEncoding m, TMR_GEN2_TrExt trExt,
TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
if (NULL != target)
{ /* EAS Alarm command is sent without any singulation of the tag*/
return TMR_ERROR_UNSUPPORTED;
}
TMR_SR_msgAddNXPEASAlarm(msg, &i, timeout, chip, dr, m, trExt, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Alarm data always starts at position 9 */
/* FF 0A 2D 00 00 xx 40 00 04 [8 bytes] ?? ??
* SOH Length OpCode Status ChipType option SubCommand [EAS AlarmData] CRC
*/
i = 9;
if (NULL != data)
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
return TMR_SUCCESS;
}
/** Helper routine to form the NXP Calibrate command **/
void TMR_SR_msgAddNXPCalibrate(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x05); /* Sub command, Calibrate */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, 0, false);
msg[rec]=msg[rec]|option;
SETU32(msg, *i, accessPassword);
}
/**
* NXP Calibrate (only for G2xL)
* Chip type = 0x02, Command = 0x05
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param chip The NXP Chip type (G2iL or G2xL)
* @param accessPassword The access password to use to write on the tag
* @param data 64 bytes of calibration data will be returned on a successful operation
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdNxpCalibrate(TMR_Reader *reader, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddNXPCalibrate(msg, &i, timeout, chip, accessPassword, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Calibration data always starts at position 9 */
/* FF 42 2D 00 00 xx 40 00 05 [64 bytes] ?? ??
* SOH Length OpCode Status ChipType option SubCommand [CalibrateData] CRC
*/
i = 9;
if (NULL != data)
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
return TMR_SUCCESS;
}
/** Helper routine to form the NXP ChangeConfig command **/
void TMR_SR_msgAddNXPChangeConfig(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord, TMR_TagFilter* target)
{
//uint16_t configData;
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x07); /* Sub command, ChangeConfig */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)0x00); //RFU
SETU16(msg, *i, configWord.data);
}
/**
* NXP ChangeConfig (only for G2iL)
* Chip type = 0x07, Command = 0x07
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param chip The NXP Chip type (G2iL or G2xL)
* @param accessPassword The access password to use to write on the tag
* @param configWord (I/O)The config word to write on the tag.
* @param data If the operation is success, this data contains the current configword setting on the tag.
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdNxpChangeConfig(TMR_Reader *reader, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, TMR_NXP_ConfigWord configWord,
TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
if (chip == TMR_SR_GEN2_NXP_G2X_SILICON)
{
/* ChangeConfig works only for G2iL tags*/
return TMR_ERROR_UNSUPPORTED;
}
TMR_SR_msgAddNXPChangeConfig(msg, &i, timeout, chip, accessPassword, configWord, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the config data from response back to the user */
i = 9;
/* FF 06 2d 00 00 07 40 00 07 80 46 59 2f
* SOH Length OpCode Status ChipType option SubCommand [ConfigData] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
void TMR_SR_msgAddGen2v2NxpUntraceable(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, uint16_t configWord,
TMR_TagOp_GEN2_NXP_Untraceable op ,TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x00);//option
SETU8(msg, *i, (uint8_t)op.subCommand); /* Sub command, Untraceable */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, false);
msg[rec]=msg[rec]|option;
SETU16(msg, *i, configWord);
if(op.subCommand == 0x02)// Untraceable with Authentication
{
SETU8(msg,*i, op.auth.tam1Auth.Authentication);
SETU8(msg,*i,op.auth.tam1Auth.CSI);
SETU8(msg,*i,op.auth.tam1Auth.keyID);
SETU8(msg,*i,op.auth.tam1Auth.KeyLength);
{
uint32_t iWord;
for (iWord = 0; iWord < op.auth.tam1Auth.Key.len; iWord++)
{
SETU8(msg, *i, (op.auth.tam1Auth.Key.list[iWord]));
// SETU8(msg, *i, ((op.auth.tam1Auth.Key.list[iWord]>>0)&0xFF));
}
}
SETU8(msg,*i,op.auth.tam1Auth.IchallengeLength);
{
uint32_t iWord;
for (iWord = 0; iWord < op.auth.tam1Auth.Ichallenge.len; iWord++)
{
SETU8(msg, *i, (op.auth.tam1Auth.Ichallenge.list[iWord]));
//SETU8(msg, *i, ((op.auth.tam1Auth.Ichallenge.list[iWord]>>0)&0xFF));
}
}
}
else //Untraceable with Access
{
SETU32(msg, *i,op.auth.accessPassword);
}
}
TMR_Status TMR_SR_cmdGen2v2NXPUntraceable(TMR_Reader *reader, uint16_t timeout,
TMR_SR_GEN2_SiliconType chip, TMR_GEN2_Password accessPassword, uint16_t configWord,
TMR_TagOp_GEN2_NXP_Untraceable op,TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddGen2v2NxpUntraceable(msg, &i, timeout, chip, accessPassword, configWord, op ,target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
return TMR_SUCCESS;
}
uint8_t getCmdProtModeBlockCount(uint8_t protMode, uint8_t blockCount)
{
uint8_t protModeBlockCount = 0x01; //The UCODE AES Tag only supports ProtMode = "0001b" (CBC encryption)
uint16_t mask = 0x0F;
int pos = 4;
protModeBlockCount |= ((blockCount & mask) << pos);
return protModeBlockCount;
}
uint16_t getCmdProfileOffset(uint16_t profile, uint16_t offset)
{
uint16_t profileOffset = 0x0000;
uint16_t mask;
int pos;
mask = 0xF;
pos = 12;
profileOffset |= ((profile & mask) << pos);
mask = 0xFFF;
pos = 0;
profileOffset |= ((offset & mask) << pos);
return profileOffset;
}
void TMR_SR_msgAddGen2v2NxpAuthenticate(uint8_t *msg, uint8_t *i, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,
TMR_GEN2_Password accessPassword,TMR_TagOp_GEN2_NXP_Authenticate op ,TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x00);//option
SETU8(msg, *i, (uint8_t)op.subCommand); /* Sub command, Untraceable */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, false);
msg[rec]=msg[rec]|option;
SETU8(msg,*i, op.tam1Auth.Authentication);
SETU8(msg,*i,op.tam1Auth.CSI);
SETU8(msg,*i,op.tam1Auth.keyID);
SETU8(msg,*i,op.tam1Auth.KeyLength);
{
uint8_t iWord;
for (iWord = 0; iWord < op.tam1Auth.Key.len; iWord++)
{
SETU8(msg, *i, (op.tam1Auth.Key.list[iWord]));
}
}
SETU8(msg,*i,op.tam1Auth.IchallengeLength);
{
uint8_t iWord;
for (iWord = 0; iWord < op.tam1Auth.Ichallenge.len; iWord++)
{
SETU8(msg, *i, (op.tam1Auth.Ichallenge.list[iWord]));
}
}
if(op.type == TAM2_AUTHENTICATION)
{
SETU16(msg, *i, getCmdProfileOffset(op.tam2Auth.profile,op.tam2Auth.Offset));
SETU8(msg, *i, getCmdProtModeBlockCount(op.tam2Auth.ProtMode,op.tam2Auth.BlockCount));
}
}
TMR_Status TMR_SR_cmdGen2v2NXPAuthenticate(TMR_Reader *reader, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,
TMR_GEN2_Password accessPassword, TMR_TagOp_GEN2_NXP_Authenticate op, TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddGen2v2NxpAuthenticate(msg, &i, timeout, chip, accessPassword, op ,target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (NULL != data->list)
{
i = 8;
{
uint16_t dataLength;
uint16_t copyLength;
copyLength = dataLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
data->len = copyLength;
memcpy(data->list, &msg[i], copyLength);
i += dataLength;
}
}
return TMR_SUCCESS;
}
uint16_t getCmdWordPointer(uint16_t wordPointer)
{
uint16_t rdBufferWordPointer = 0x0000;
if (wordPointer > 0)
{
uint16_t mask = 0x0FFF;
int pos = 0;
rdBufferWordPointer |= ((wordPointer & mask) << pos);
}
return rdBufferWordPointer;
}
uint16_t getCmdBitCount(uint16_t bitCount)
{
uint16_t rdBufferBitCount = 0x0000;
if (bitCount > 0)
{
uint16_t mask = 0x0FFF;
int pos = 0;
rdBufferBitCount |= ((bitCount & mask) << pos);
}
return rdBufferBitCount;
}
void TMR_SR_msgAddGen2v2NxpReadBuffer(uint8_t *msg, uint8_t *i, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,
TMR_GEN2_Password accessPassword,TMR_TagOp_GEN2_NXP_Readbuffer op ,TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)chip); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x00);//option
SETU8(msg, *i, (uint8_t)op.authenticate.subCommand); /* Sub command, Untraceable */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, false);
msg[rec]=msg[rec]|option;
SETU16(msg, *i, getCmdWordPointer(op.wordPointer));
SETU16(msg, *i, getCmdBitCount(op.bitCount));
SETU8(msg,*i, op.authenticate.tam1Auth.Authentication);
SETU8(msg,*i,op.authenticate.tam1Auth.CSI);
SETU8(msg,*i,op.authenticate.tam1Auth.keyID);
SETU8(msg,*i,op.authenticate.tam1Auth.KeyLength);
{
uint8_t iWord;
for (iWord = 0; iWord < op.authenticate.tam1Auth.Key.len; iWord++)
{
SETU8(msg, *i, (op.authenticate.tam1Auth.Key.list[iWord]));
}
}
SETU8(msg,*i,op.authenticate.tam1Auth.IchallengeLength);
{
uint8_t iWord;
for (iWord = 0; iWord < op.authenticate.tam1Auth.Ichallenge.len; iWord++)
{
SETU8(msg, *i, (op.authenticate.tam1Auth.Ichallenge.list[iWord]));
}
}
if(op.authenticate.type == TAM2_AUTHENTICATION)
{
SETU16(msg, *i, getCmdProfileOffset(op.authenticate.tam2Auth.profile,op.authenticate.tam2Auth.Offset));
SETU8(msg, *i, getCmdProtModeBlockCount(op.authenticate.tam2Auth.ProtMode,op.authenticate.tam2Auth.BlockCount));
}
}
TMR_Status TMR_SR_cmdGen2v2NXPReadBuffer(TMR_Reader *reader, uint16_t timeout,TMR_SR_GEN2_SiliconType chip,
TMR_GEN2_Password accessPassword, TMR_TagOp_GEN2_NXP_Readbuffer op, TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddGen2v2NxpReadBuffer(msg, &i, timeout, chip, accessPassword, op ,target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
if (NULL != data->list)
{
i = 8;
{
uint16_t dataLength;
uint16_t copyLength;
copyLength = dataLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
data->len = copyLength;
memcpy(data->list, &msg[i], copyLength);
i += dataLength;
}
}
return TMR_SUCCESS;
}
/**
* Monza4 Silicon Specific Commands
* Chip Type = 0x08
**/
/** Helper routine to form the Monza4 QT Read/Write command **/
void TMR_SR_msgAddMonza4QTReadWrite(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
TMR_Monza4_ControlByte controlByte, TMR_Monza4_Payload payload, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IMPINJ_MONZA4_SILICON); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)0x00); /* Sub command, QT Read/Write */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, controlByte.data);
SETU16(msg, *i, payload.data);
}
/**
* Impinj Monza4 QT Read/Write
* Chip type = 0x08, command = 0x00
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param controlByte The control byte to write on the tag
* @param payload The payload
* @param data If the operation is success, this data contains the payload
* When Read/Write (bit) = 0, then the payload is the value read,
* When Read/Write (bit) = 1, then the payload is the value written.
* @param target Filter to be applied.
*/
TMR_Status TMR_SR_cmdMonza4QTReadWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
TMR_Monza4_ControlByte controlByte, TMR_Monza4_Payload payload, TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddMonza4QTReadWrite(msg, &i, timeout, accessPassword, controlByte, payload, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the payload data from response back to the user */
i = 9;
/* FF 06 2d 00 00 08 40 00 00 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [payload] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* IDS SL900A specific commands
* chip type 0A
*/
/**
* Helper routine to form the IDS SL900A get battery level command
*/
void TMR_SR_msgAddIdsSL900aGetBatteryLevel(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, BatteryType batteryType,
TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU8(msg, *i, batteryType);
}
/**
* IDS SL900A Get Battery Level
* Chip type = 0x0A, command = 0x00 AA
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aGetBatteryLevel(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level,BatteryType type,
TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aGetBatteryLevel(msg, &i, timeout, accessPassword, CommandCode, password, level, type, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the battery level data from response back to the user */
i = 9;
/* FF 06 2d 00 00 0A 42 00 AD xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [level] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* Helper routine to form the IDS SL900A get sensor value command
*/
void TMR_SR_msgAddIdsSL900aGetSensorValue(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, Sensor sensortype,
TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU8(msg, *i, sensortype);
}
/**
* IDS SL900A Get Sensor value
* Chip type = 0x0A, command = 0x00 AD
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aGetSensorValue(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level,Sensor sensortype,
TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aGetSensorValue(msg, &i, timeout, accessPassword, CommandCode, password, level, sensortype, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the sensor type data from response back to the user */
i = 9;
/* FF 06 2d 00 00 0A 42 00 AD xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [type] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* Helper routine to form the IDS SL900A get measurment setup command
*/
void TMR_SR_msgAddIdsSL900aGetMeasurementSetup(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
}
/**
* IDS SL900A Get Sensor value
* Chip type = 0x0A, command = 0x00 A3
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aGetMeasurementSetup(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level,
TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aGetMeasurementSetup(msg, &i, timeout, accessPassword, CommandCode, password, level, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the measurment data from response back to the user */
i = 9;
/* FF 06 2d 00 00 0A 42 00 AD xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [data] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* Helper routine to form the IDS SL900A get log state command
*/
void TMR_SR_msgAddIdsSL900aGetLogState(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
}
/**
* IDS SL900A Get log State
* Chip type = 0x0A, command = 0x00 AD
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param to specify SL900A sensor type
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aGetLogState(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level,TMR_uint8List *data,
TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aGetLogState(msg, &i, timeout, accessPassword, CommandCode, password, level, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the sensor type data from response back to the user */
i = 9;
/* FF 06 2d 00 00 0A 42 00 AD xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [type] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* Helper routine to form the IDS SL900A set log mode command
*/
void TMR_SR_msgAddIdsSL900aSetLogMode(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, LoggingForm form,
StorageRule rule, bool Ext1Enable, bool Ext2Enable, bool TempEnable, bool BattEnable,
uint16_t LogInterval, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
uint32_t logmode = 0;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
logmode |= (uint32_t)form << 21;
logmode |= (uint32_t)rule << 20;
logmode |= (uint32_t)(Ext1Enable ? 1 : 0) << 19;
logmode |= (uint32_t)(Ext2Enable ? 1 : 0) << 18;
logmode |= (uint32_t)(TempEnable ? 1 : 0) << 17;
logmode |= (uint32_t)(BattEnable ? 1 : 0) << 16;
logmode |= (uint32_t)LogInterval << 1;
SETU8(msg, *i, (uint8_t)((logmode >> 16) & 0xFF));
SETU8(msg, *i, (uint8_t)((logmode >> 8) & 0xFF));
SETU8(msg, *i, (uint8_t)((logmode >> 0) & 0xFF));
}
/**
* IDS SL900A Get log State
* Chip type = 0x0A, command = 0x00 AD
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param level IDS password level
* @param form IDS logging form
* @param rule IDS storage rule
* @param Ext1Enable to Enable log for EXT1 external sensor
* @param Ext2Enable to Enable log for EXT2 external sensor
* @param TempEnable to Enable log for temperature sensor
* @param BattEnable to Enable log for battery sensor
* @param LogInterval to Time (seconds) between log readings
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aSetLogMode(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, LoggingForm form,
StorageRule rule, bool Ext1Enable, bool Ext2Enable, bool TempEnable, bool BattEnable,
uint16_t LogInterval, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aSetLogMode(msg, &i, timeout, accessPassword, CommandCode, password, level, form,
rule, Ext1Enable, Ext2Enable, TempEnable, BattEnable, LogInterval, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/* Helper routine to form the IDS SL900A initialize command */
void TMR_SR_msgAddIdsSL900aInitialize(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t delayTime,
uint16_t applicatioData, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU16(msg, *i, delayTime);
SETU16(msg, *i, applicatioData);
}
/**
* IDS SL900A initialize command
* Chip type = 0x0A, command = 0x00 AC
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param delayTime to secify delayTime
* @param applicatioData to specify applicationData
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aInitialize(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t delayTime,
uint16_t applicationData, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aInitialize(msg, &i, timeout, accessPassword, CommandCode, password, level, delayTime,
applicationData, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* Helper routine to form the IDS SL900A end log command
*/
void TMR_SR_msgAddIdsSL900aEndLog(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
}
/**
* IDS SL900A Initialize command
* Chip type = 0x0A, command = 0x00 A6
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aEndLog(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aEndLog(msg, &i, timeout, accessPassword, CommandCode, password, level, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* Helper function to form the IDS SL900A SetPassword command
*/
void TMR_SR_msgAddIdsSL900aSetPassword(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t newPassword,
PasswordLevel newPasswordLevel, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU8(msg, *i, (uint8_t)newPasswordLevel);
SETU32(msg, *i, newPassword);
}
/**
* IDS SL900A SetPassword command
* Chip type = 0x0A, command = 0x00 A0
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aSetPassword(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t newPassword,
PasswordLevel newPasswordLevel, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aSetPassword(msg, &i, timeout, accessPassword, CommandCode, password, level, newPassword, newPasswordLevel, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* Helper routine to form the IDS SL900A AccessFifo Status command
*/
void TMR_SR_msgAddIdsSL900aAccessFifoStatus(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,
TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU8(msg, *i, (uint8_t)operation);
}
/**
* IDS SL900A AccessFifo status command
* Chip type = 0x0A, command = 0x00 AF
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aAccessFifoStatus(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,
uint32_t password, PasswordLevel level, AccessFifoOperation operation,TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aAccessFifoStatus(msg, &i, timeout, accessPassword, CommandCode, password, level, operation, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the sensor type data from response back to the user */
i = 9;
/* FF 06 2d 00 00 0A 42 00 AF xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [type] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* Helper routine to form the IDS SL900A AccessFifo Read command
*/
void TMR_SR_msgAddIdsSL900aAccessFifoRead(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,
uint8_t length, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU8(msg, *i, (uint8_t)(operation | length));
}
/**
* IDS SL900A AccessFifo read command
* Chip type = 0x0A, command = 0x00 AF
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aAccessFifoRead(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,
uint32_t password, PasswordLevel level, AccessFifoOperation operation, uint8_t length, TMR_uint8List *data,
TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aAccessFifoRead(msg, &i, timeout, accessPassword, CommandCode, password, level, operation, length, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the sensor type data from response back to the user */
i = 9;
/* FF 06 2d 00 00 0A 42 00 AF xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [type] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* Helper routine to form the IDS SL900A AccessFifo Write command
*/
void TMR_SR_msgAddIdsSL900aAccessFifoWrite(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, AccessFifoOperation operation,
TMR_uint8List *payLoad, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU8(msg, *i, (uint8_t)(operation | payLoad->len));
memcpy(&msg[*i], payLoad->list, payLoad->len);
*i += payLoad->len;
}
/**
* IDS SL900A AccessFifo Write command
* Chip type = 0x0A, command = 0x00 AF
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aAccessFifoWrite(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,
uint32_t password, PasswordLevel level, AccessFifoOperation operation, TMR_uint8List *payLoad, TMR_uint8List *data,
TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aAccessFifoWrite(msg, &i, timeout, accessPassword, CommandCode, password, level, operation, payLoad, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the sensor type data from response back to the user */
i = 9;
/* FF 06 2d 00 00 0A 42 00 AF xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [type] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* Helper routine to form the IDS SL900A Start Log command
*/
void TMR_SR_msgAddIdsSL900aStartLog(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t time, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU32(msg, *i, time);
}
/**
* IDS SL900A StartLog command
* Chip type = 0x0A, command = 0x00 A7
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param startTime to specify count start time
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aStartLog(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t CommandCode,
uint32_t password, PasswordLevel level, uint32_t time, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aStartLog(msg, &i, timeout, accessPassword, CommandCode, password, level, time, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* Helper routine to form the IDS SL900A get calibration data command
*/
void TMR_SR_msgAddIdsSL900aGetCalibrationData(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
}
/**
* IDS SL900A Get Calibration Data
* Chip type = 0x0A, command = 0x00 A9
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aGetCalibrationData(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level,
TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aGetCalibrationData(msg, &i, timeout, accessPassword, CommandCode, password, level, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the calibration data from response back to the user */
i = 9;
/* FF 06 2d 00 00 0A 42 00 A9 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [data] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* Helper routine to form the IDS SL900A set calibration data command
*/
void TMR_SR_msgAddIdsSL900aSetCalibrationData(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint64_t calibration,
TMR_TagFilter* target)
{
uint8_t option = 0, rec;
uint8_t calBytes[8];
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
calBytes[0] = (uint8_t) (calibration >> 56);
calBytes[1] = (uint8_t) (calibration >> 48);
calBytes[2] = (uint8_t) (calibration >> 40);
calBytes[3] = (uint8_t) (calibration >> 32);
calBytes[4] = (uint8_t) (calibration >> 24);
calBytes[5] = (uint8_t) (calibration >> 16);
calBytes[6] = (uint8_t) (calibration >> 8);
calBytes[7] = (uint8_t) (calibration >> 0);
memcpy(&msg[*i], calBytes + 1, 7);
*i += 7;
}
/**
* IDS SL900A Set Calibration Data
* Chip type = 0x0A, command = 0x00 A5
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param calibration to spcify the calibration data
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aSetCalibrationData(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint64_t calibration,
TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aSetCalibrationData(msg, &i, timeout, accessPassword, CommandCode, password, level, calibration, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* Helper routine to form the IDS SL900A set sfe parameters command
*/
void TMR_SR_msgAddIdsSL900aSetSfeParameters(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t sfe,
TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU16(msg, *i, sfe);
}
/**
* IDS SL900A Set Calibration Data
* Chip type = 0x0A, command = 0x00 A4
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param sfe to spcify the sfe parameters
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aSetSfeParameters(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t sfe,
TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aSetSfeParameters(msg, &i, timeout, accessPassword, CommandCode, password, level, sfe, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* Helper routine to form the IDS Sl900A set log mode command
*/
void TMR_SR_msgAddIdsSL900aSetLogLimit(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t exLower,
uint16_t lower, uint16_t upper, uint16_t exUpper, TMR_TagFilter* target)
{
uint8_t option = 0, rec;
uint64_t temp = 0;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
temp |= (uint64_t)exLower << 30;
temp |= (uint64_t)lower << 20;
temp |= (uint64_t)upper << 10;
temp |= (uint64_t)exUpper << 0;
SETU8(msg, *i, (uint8_t)((temp >> 32) & 0xFF));
SETU8(msg, *i, (uint8_t)((temp >> 24) & 0xFF));
SETU8(msg, *i, (uint8_t)((temp >> 16) & 0xFF));
SETU8(msg, *i, (uint8_t)((temp >> 8) & 0xFF));
SETU8(msg, *i, (uint8_t)((temp >> 0) & 0xFF));
}
/**
* IDS SL90A SetLogLimit
* Chip type = 0x0A, command = 0x00 A2
*
* @param reader The reader
* @param timeout The timeout of the operation, in millisecondds. Valid range 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param level IDS password level
* @param exLoweer IDS extreamLower limit
* @param lower IDS lower limit
* @param upper IDS upper limit
* @param exUpper IDS extreamUpper limit
*/
TMR_Status
TMR_SR_cmdSL900aSetLogLimit(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint16_t exLower,
uint16_t lower, uint16_t upper, uint16_t exUpper, TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aSetLogLimit(msg, &i, timeout, accessPassword, CommandCode, password, level, exLower,
lower, upper, exUpper, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* Helper routine to form the IDS SL900A SetShelfLife command
*/
void TMR_SR_msgAddIdsSL900aSetShelfLife(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t block0, uint32_t block1,
TMR_TagFilter* target)
{
uint8_t option = 0, rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_IDS_SL900A_SILICON); /* chip type */
rec = *i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)CommandCode);
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)level);
SETU32(msg, *i, password);
SETU32(msg, *i, block0);
SETU32(msg, *i, block1);
}
/**
* IDS SL900A SetShelfLife
* Chip type = 0x0A, command = 0x00 AB
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param commandcode to specify the operation
* @param password to specify SL900A password access level values
* @param data If the operation is success, this data contains the requested value
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdSL900aSetShelfLife(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t CommandCode, uint32_t password, PasswordLevel level, uint32_t block0, uint32_t block1,
TMR_TagFilter* target)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIdsSL900aSetShelfLife(msg, &i, timeout, accessPassword, CommandCode, password, level, block0, block1, target);
msg[1] = i - 3; /* Install length */
return TMR_SR_sendTimeout(reader, msg, timeout);
}
/**
* Gen2 IAVDenatran Custom Commands
* Chip Type = 0x0B
**/
/** Helper routine to form the Gen2 IAVDenatran Custom commands **/
void TMR_SR_msgAddIAVDenatranCustomOp(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t mode, uint8_t payload, TMR_TagFilter* target)
{
uint8_t option=0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_DENATRAN_IAV_SILICON); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)mode); /* Sub command */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
SETU8(msg, *i, (uint8_t)payload);
}
/**
* IAV Denatran Custom Commands
* Chip type = 0x0B, command = 0x00
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdIAVDenatranCustomOp(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,
TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, timeout, accessPassword, mode, payload, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the response back to the user */
i = 9;
/* FF 06 2d 00 00 08 40 00 00 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [payload] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/** Helper routine to form the Gen2 IAVDenatran Custom commad readFromMemMap */
void TMR_SR_msgAddIAVDenatranCustomReadFromMemMap(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordAddress)
{
TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);
/* Add the address to be read from user bank */
SETU16(msg, *i, wordAddress);
}
/** * IAV Denatran Custom Command Read From MemMap
* Chip type = 0x0B, command = 0x06
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
* @param wordAddress address to be read from USER bank
*/
TMR_Status
TMR_SR_cmdIAVDenatranCustomReadFromMemMap(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,
TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordAddress)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIAVDenatranCustomReadFromMemMap(msg, &i, timeout, accessPassword, mode, payload, target, wordAddress);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the response back to the user */
i = 9;
/* FF 06 2d 00 00 08 40 00 00 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [payload] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/** Helper routine to form the Gen2 IAVDenatran Custom commad read sec */
void TMR_SR_msgAddIAVDenatranCustomReadSec(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordAddress)
{
TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);
/* Add the address to be read from user bank */
SETU16(msg, *i, wordAddress);
}
/** * IAV Denatran Custom Command Read Sec
* Chip type = 0x0B, command = 0x0A
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
* @param wordAddress address to be read from USER bank
*/
TMR_Status
TMR_SR_cmdIAVDenatranCustomReadSec(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,
TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordAddress)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIAVDenatranCustomReadSec(msg, &i, timeout, accessPassword, mode, payload, target, wordAddress);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the response back to the user */
i = 9;
/* FF 06 2d 00 00 08 40 00 00 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [payload] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/** Helper routine to form the Gen2 IAVDenatran Custom commad Activate Siniav Mode */
void TMR_SR_msgAddIAVDenatranCustomActivateSiniavMode(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t mode, uint8_t payload, TMR_TagFilter* target, bool tokenDesc, uint8_t *token)
{
uint8_t j;
TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);
/* add the token field */
if (tokenDesc)
{
for (j = 0; j < 8; j++)
{
SETU8(msg, *i, token[j]);
}
}
}
/**
* IAV Denatran Custom Commands Activate Siniav Mode
* Chip type = 0x0B, command = 0x02
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
* @param token 64bit value to active the tag
*/
TMR_Status
TMR_SR_cmdIAVDenatranCustomActivateSiniavMode(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,
TMR_uint8List *data, TMR_TagFilter* target, bool tokenDesc, uint8_t *token)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIAVDenatranCustomActivateSiniavMode(msg, &i, timeout, accessPassword, mode, payload, target, tokenDesc, token);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the response back to the user */
i = 9;
/* FF 06 2d 00 00 08 40 00 00 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [payload] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/** Helper routine to form the Gen2 IAVDenatran Custom commad writeToMemMap */
void TMR_SR_msgAddIAVDenatranCustomWriteToMemMap(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint16_t wordPtr, uint16_t wordData, uint8_t* tagId, uint8_t* dataBuf)
{
uint8_t j;
TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);
/* Add the address to be read from user bank */
SETU16(msg, *i, wordPtr);
SETU16(msg, *i, wordData);
for (j = 0; j < 8; j++)
{
SETU8(msg, *i, tagId[j]);
}
for (j = 0; j < 16; j++)
{
SETU8(msg, *i, dataBuf[j]);
}
}
/** Helper routine to form the Gne2 IAVDenatran Custom command get token Id */
void TMR_SR_msgAddIAVDenatranCustomGetTokenId(uint8_t *msg, uint8_t *i, uint16_t timeout,
TMR_GEN2_Password accessPassword, uint8_t mode, TMR_TagFilter* target)
{
uint8_t option = 0,rec;
SETU8(msg, *i, TMR_SR_OPCODE_WRITE_TAG_SPECIFIC);
SETU16(msg, *i, timeout);
SETU8(msg, *i, (uint8_t)TMR_SR_GEN2_DENATRAN_IAV_SILICON); /* Chip - type*/
rec=*i;
SETU8(msg,*i,0x40);//option
SETU8(msg, *i, (uint8_t)0x00);
SETU8(msg, *i, (uint8_t)mode); /* Sub command */
filterbytes(TMR_TAG_PROTOCOL_GEN2, target, &option, i, msg, accessPassword, true);
msg[rec]=msg[rec]|option;
}
/**
* IAV Denatran Custom Command write to MemMap
* Chip type = 0x0B, command = 0x06
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
* @param wordPtr pointer to the USER data
* @param wordData data to be written
* @param dataBuf credentials written word
*/
TMR_Status
TMR_SR_cmdIAVDenatranCustomWriteToMemMap(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,
TMR_uint8List *data, TMR_TagFilter* target, uint16_t wordPtr, uint16_t wordData, uint8_t* tagId, uint8_t* dataBuf)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIAVDenatranCustomWriteToMemMap(msg, &i, timeout, accessPassword, mode, payload, target, wordPtr, wordData, tagId, dataBuf);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the response back to the user */
i = 9;
/* FF 06 2d 00 00 08 40 00 00 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [payload] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/** Helper routine to form the Gen2 IAVDenatran Custom commad write Sec */
void TMR_SR_msgAddIAVDenatranCustomWriteSec(uint8_t *msg, uint8_t *i, uint16_t timeout, TMR_GEN2_Password accessPassword,
uint8_t mode, uint8_t payload, TMR_TagFilter* target, uint8_t* data, uint8_t* dataBuf)
{
uint8_t j;
TMR_SR_msgAddIAVDenatranCustomOp(msg, i, timeout, accessPassword, mode, payload, target);
for (j = 0; j < 6; j++)
{
SETU8(msg, *i, data[j]);
}
for (j = 0; j < 16; j++)
{
SETU8(msg, *i, dataBuf[j]);
}
}
/**
* IAV Denatran Custom Command write sec
* Chip type = 0x0B, command = 0x0B
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
* @param wordPtr pointer to the USER data
* @param data data words
* @param dataBuf credentials written word
*/
TMR_Status
TMR_SR_cmdIAVDenatranCustomWriteSec(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode, uint8_t payload,
TMR_uint8List *data, TMR_TagFilter* target, uint8_t* dataWords, uint8_t* dataBuf)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIAVDenatranCustomWriteSec(msg, &i, timeout, accessPassword, mode, payload, target, dataWords, dataBuf);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the response back to the user */
i = 9;
/* FF 06 2d 00 00 08 40 00 00 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [payload] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* IAV Denatran Custom Command Get Token Id
* Chip type = 0x0B, command = 0x09
*
* @param reader The reader
* @param timeout The timeout of the operation, in milliseconds. Valid range is 0-65535.
* @param accessPassword The access password to use to write on the tag
* @param target Filter to be applied.
*/
TMR_Status
TMR_SR_cmdIAVDenatranCustomGetTokenId(TMR_Reader *reader, uint16_t timeout, TMR_GEN2_Password accessPassword, uint8_t mode,
TMR_uint8List *data, TMR_TagFilter* target)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
TMR_SR_msgAddIAVDenatranCustomGetTokenId(msg, &i, timeout, accessPassword, mode, target);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, timeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the response back to the user */
i = 9;
/* FF 06 2d 00 00 08 40 00 00 xx xx xx xx
* SOH Length OpCode Status ChipType option SubCommand [payload] CRC
*/
{
uint16_t copyLength;
copyLength = msg[1] + 5 - i;
if (copyLength > data->max)
{
copyLength = data->max;
}
if (NULL != data)
{
memcpy(data->list, &msg[i], copyLength);
data->len = copyLength;
}
}
return TMR_SUCCESS;
}
/**
* TMR_SR_cmdGetReaderStatistics
* Get the current per-port statistics.
*
* @param reader [in]The reader
* @param statFlags [in]The set of statistics together
* @param stats [out]The ReaderStatistics structure populated with requested per-port values
*/
TMR_Status
TMR_SR_cmdGetReaderStatistics(TMR_Reader *reader, TMR_SR_ReaderStatisticsFlag statFlags,
TMR_SR_ReaderStatistics *stats)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, length, offset;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_READER_STATS);
SETU8(msg, i, (uint8_t)TMR_SR_READER_STATS_OPTION_GET_PER_PORT); /* Option byte */
SETU8(msg, i, (uint8_t)statFlags);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the statistics from response */
if (NULL != stats)
{
uint8_t port = 0;
offset = 7;
length = reader->u.serialReader.txRxMap->len;
while (offset < (msg[1] + 2))
{
if (0 != (msg[offset] & TMR_SR_READER_STATS_FLAG_RF_ON_TIME))
{
offset += 2;
for (i = 0; i < length; i++)
{
port = msg[offset];
if (i == (port-1))
{
offset ++;
stats->rfOnTime[i] = GETU32(msg, offset);
}
else
{
stats->rfOnTime[i] = 0;
}
}
stats->numPorts = length;
}
else if (0 != (msg[offset] & TMR_SR_READER_STATS_FLAG_NOISE_FLOOR))
{
offset += 2;
for (i = 0; i < length; i++)
{
port = msg[offset];
if (i == (port-1))
{
offset ++;
stats->noiseFloor[i] = msg[offset++];
}
else
{
stats->noiseFloor[i] = 0;
}
}
stats->numPorts = length;
}
else if (0 != (msg[offset] & TMR_SR_READER_STATS_FLAG_NOISE_FLOOR_TX_ON))
{
offset += 2;
for (i = 0; i < length; i++)
{
port = msg[offset];
if (i == (port-1))
{
offset ++;
stats->noiseFloorTxOn[i] = msg[offset++];
}
else
{
stats->noiseFloorTxOn[i] = 0;
}
}
stats->numPorts = length;
}
}
}
return TMR_SUCCESS;
}
/**
* TMR_SR_cmdResetReaderStatistics
* Reset the per-port statistics.
*
* @param reader [in]The reader
* @param statFlags [in]The set of statistics to reset. Only the RF on time statistic may be reset.
*/
TMR_Status
TMR_SR_cmdResetReaderStatistics(TMR_Reader *reader, TMR_SR_ReaderStatisticsFlag statFlags)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_READER_STATS);
SETU8(msg, i, (uint8_t)TMR_SR_READER_STATS_OPTION_RESET); /* Option byte */
SETU8(msg, i, (uint8_t)statFlags);
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
return TMR_SUCCESS;
}
/**
* Helper function to be used in GetReaderStats
*/
TMR_Status
TMR_fillReaderStats(TMR_Reader *reader, TMR_Reader_StatsValues* stats, uint16_t flag, uint8_t* msg, uint8_t offset)
{
uint8_t i;
while (offset < (msg[1] + 2))
{
if ((0x80) > msg[offset])
{
flag = msg[offset];
}
else
{
/**
* the response flag will be in EBV format,
* convert that to the api enum values
*/
flag = ((msg[offset] << 8) | (msg[offset + 1]));
flag &= 0x7fff;
flag = ((flag >> 1) | (flag & 0x7f));
}
if (flag & TMR_READER_STATS_FLAG_RF_ON_TIME)
{
uint8_t tx;
offset += 2;
for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)
{
tx = GETU8(msg, offset);
if (tx == reader->u.serialReader.txRxMap->list[i].txPort)
{
stats->perAntenna.list[i].antenna = reader->u.serialReader.txRxMap->list[i].antenna;
stats->perAntenna.list[i].rfOnTime = GETU32(msg, offset);
}
}
}
else if (flag & TMR_READER_STATS_FLAG_NOISE_FLOOR_SEARCH_RX_TX_WITH_TX_ON)
{
uint8_t tx,rx, len;
offset++;
len = GETU8(msg, offset);
while (len)
{
tx = GETU8(msg, offset);
rx = GETU8(msg, offset);
for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)
{
if ((rx == reader->u.serialReader.txRxMap->list[i].rxPort) && (tx == reader->u.serialReader.txRxMap->list[i].txPort))
{
stats->perAntenna.list[i].antenna = reader->u.serialReader.txRxMap->list[i].antenna;
stats->perAntenna.list[i].noiseFloor = GETU8(msg, offset);
len -= 3;
}
}
}
}
else if (flag & TMR_READER_STATS_FLAG_FREQUENCY)
{
offset += 3;
stats->frequency = GETU24(msg, offset);
}
else if (flag & TMR_READER_STATS_FLAG_TEMPERATURE)
{
offset += 3;
stats->temperature = GETU8(msg, offset);
}
else if (flag & TMR_READER_STATS_FLAG_PROTOCOL)
{
offset += 3;
stats->protocol = (TMR_TagProtocol)GETU8(msg, offset);
}
else if (flag & TMR_READER_STATS_FLAG_ANTENNA_PORTS)
{
uint8_t tx, rx;
offset += 3;
tx = GETU8(msg, offset);
rx = GETU8(msg, offset);
for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)
{
if ((rx == reader->u.serialReader.txRxMap->list[i].rxPort) && (tx == reader->u.serialReader.txRxMap->list[i].txPort))
{
stats->antenna = reader->u.serialReader.txRxMap->list[i].antenna;
break;
}
}
}
else if (flag & TMR_READER_STATS_FLAG_CONNECTED_ANTENNAS)
{
offset += 3;
stats->connectedAntennas.len = msg[offset - 1];
for (i = 0; i < stats->connectedAntennas.len; i++)
{
stats->connectedAntennas.list[i] = msg[offset++];
}
}
else
{
return TMR_ERROR_INVALID;
}
}/* End of while loop */
return TMR_SUCCESS;
}
/**
* TMR_SR_cmdGetReaderStats
* Get the current per-port statistics.
*
* @param reader [in]The reader
* @param statFlags [in]The set of statistics together
* @param stats [out]The ReaderStatistics structure populated with requested per-port values
*/
TMR_Status
TMR_SR_cmdGetReaderStats(TMR_Reader *reader, TMR_Reader_StatsFlag statFlags,
TMR_Reader_StatsValues *stats)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, offset;
uint16_t flag = 0, temp = 0;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_READER_STATS);
SETU8(msg, i, (uint8_t)TMR_SR_READER_STATS_OPTION_GET_PER_PORT); /* Option byte */
/**
* To extend the flag byte, an EBV technique is to be used.
* When the highest order bit of the flag byte is used,
* it signals the reader’s parser, that another flag byte is to follow
*/
if ((0x80) > statFlags)
{
SETU8(msg, i, (uint8_t)statFlags);
}
else
{
temp = statFlags & 0x7f;
statFlags &= 0xFFFE;
statFlags = (TMR_Reader_StatsFlag)((statFlags << 1) | temp);
statFlags &= 0xFF7F;
SETU16(msg, i, ((uint16_t)0x8000 | statFlags));
}
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Parse the statistics from response */
if (NULL != stats)
{
uint8_t j;
offset = 7;
/**
* preinitialize the rf ontime and the noise floor value to zero
* berfore getting the reader stats
*/
for (i = 0; i < stats->perAntenna.max; i++)
{
stats->perAntenna.list[i].antenna = 0;
stats->perAntenna.list[i].rfOnTime = 0;
stats->perAntenna.list[i].noiseFloor = 0;
}
if ((0x80) > statFlags)
{
offset = 7;
}
else
{
offset = 8;
}
ret = TMR_fillReaderStats(reader, stats, flag, msg, offset);
if (TMR_SUCCESS != ret)
{
return ret;
}
/**
* iterate through the per antenna values,
* If found any 0-antenna rows, copy the
* later rows down to compact out the empty space.
*/
for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)
{
if (!stats->perAntenna.list[i].antenna )
{
for (j = i + 1; j < reader->u.serialReader.txRxMap->len; j++)
{
if (stats->perAntenna.list[j].antenna)
{
stats->perAntenna.list[i].antenna = stats->perAntenna.list[j].antenna;
stats->perAntenna.list[i].rfOnTime = stats->perAntenna.list[j].rfOnTime;
stats->perAntenna.list[i].noiseFloor = stats->perAntenna.list[j].noiseFloor;
stats->perAntenna.list[j].antenna = 0;
stats->perAntenna.list[j].rfOnTime = 0;
stats->perAntenna.list[j].noiseFloor = 0;
stats->perAntenna.len++;
break;
}
}
}
else
{
/* Increment the length */
stats->perAntenna.len++;
}
}
}/* end of outermost if block */
/* Store the requested flags for future validation */
stats->valid = reader->statsFlag;
return TMR_SUCCESS;
}
/**
* TMR_SR_cmdResetReaderStats
* Reset the per-port statistics.
*
* @param reader [in]The reader
* @param statFlags [in]The set of statistics to reset. Only the RF on time statistic may be reset.
*/
TMR_Status
TMR_SR_cmdResetReaderStats(TMR_Reader *reader, TMR_Reader_StatsFlag statFlags)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
uint16_t temp = 0;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_GET_READER_STATS);
SETU8(msg, i, (uint8_t)TMR_SR_READER_STATS_OPTION_RESET); /* Option byte */
/**
* To extend the flag byte, an EBV technique is to be used.
* When the highest order bit of the flag byte is used,
* it signals the reader’s parser, that another flag byte is to follow
*/
if ((0x80) > statFlags)
{
SETU8(msg, i, (uint8_t)statFlags);
}
else
{
temp = statFlags & 0x7f;
statFlags &= 0xFFFE;
statFlags = (TMR_Reader_StatsFlag)((statFlags << 1) | temp);
statFlags &= 0xFF7F;
SETU16(msg, i, ((uint16_t)0x8000 | statFlags));
}
msg[1] = i - 3; /* Install length */
ret = TMR_SR_sendTimeout(reader, msg, reader->u.serialReader.commandTimeout);
if (TMR_SUCCESS != ret)
{
return ret;
}
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_receiveAutonomousReading(struct TMR_Reader *reader, TMR_TagReadData *trd, TMR_Reader_StatsValues *stats)
{
TMR_Status ret;
ret = TMR_SUCCESS;
reader->continuousReading = true;
ret = TMR_SR_hasMoreTags(reader);
if (TMR_SUCCESS == ret)
{
uint16_t flags;
if (false == reader->isStatusResponse)
{
/* Ignore the fail cases and pass only valid messages */
flags = GETU16AT(reader->u.serialReader.bufResponse, 8);
TMR_SR_parseMetadataFromMessage(reader, trd, flags, &reader->u.serialReader.bufPointer, reader->u.serialReader.bufResponse);
TMR_SR_postprocessReaderSpecificMetadata(trd, &reader->u.serialReader);
trd->reader = reader;
reader->u.serialReader.tagsRemainingInBuffer--;
}
else
{
/* A status stream response */
uint8_t offset, i,j;
uint16_t flags = 0;
TMR_STATS_init(stats);
offset = reader->u.serialReader.bufPointer;
/* Get status content flags */
if ((0x80) > reader->statsFlag)
{
offset += 1;
}
else
{
offset += 2;
}
/**
* preinitialize the rf ontime and the noise floor value to zero
* berfore getting the reader stats
*/
for (i = 0; i < stats->perAntenna.max; i++)
{
stats->perAntenna.list[i].antenna = 0;
stats->perAntenna.list[i].rfOnTime = 0;
stats->perAntenna.list[i].noiseFloor = 0;
}
TMR_fillReaderStats(reader, stats, flags, reader->u.serialReader.bufResponse, offset);
/**
* iterate through the per antenna values,
* If found any 0-antenna rows, copy the
* later rows down to compact out the empty space.
*/
for (i = 0; i < reader->u.serialReader.txRxMap->len; i++)
{
if (!stats->perAntenna.list[i].antenna)
{
for (j = i + 1; j < reader->u.serialReader.txRxMap->len; j++)
{
if (stats->perAntenna.list[j].antenna)
{
stats->perAntenna.list[i].antenna = stats->perAntenna.list[j].antenna;
stats->perAntenna.list[i].rfOnTime = stats->perAntenna.list[j].rfOnTime;
stats->perAntenna.list[i].noiseFloor = stats->perAntenna.list[j].noiseFloor;
stats->perAntenna.list[j].antenna = 0;
stats->perAntenna.list[j].rfOnTime = 0;
stats->perAntenna.list[j].noiseFloor = 0;
stats->perAntenna.len++;
break;
}
}
}
else
{
/* Increment the length */
stats->perAntenna.len++;
}
}
/* store the requested flags for future use */
stats->valid = reader->statsFlag;
}
}
reader->continuousReading = false;
return ret;
}
TMR_Status
TMR_SR_cmdStopReading(struct TMR_Reader *reader)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, op;
reader->hasContinuousReadStarted = false;
i = 2;
op = TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP;
SETU8(msg, i, op);
SETU16(msg, i, 0); /* Timeout, Currently ignored */
SETU8(msg, i, (uint8_t)0x02); /* option - stop continuous reading */
msg[1]=i - 3; /* Install length */
/* No need to capture the response */
return TMR_SR_sendMessage(reader, msg, &op, reader->u.serialReader.commandTimeout);
}
TMR_Status
TMR_SR_cmdGetReaderWriteTimeOut (struct TMR_Reader *reader, TMR_TagProtocol protocol,
TMR_SR_Gen2ReaderWriteTimeOut *value)
{
TMR_Status ret;
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i, op;
i = 2;
op = TMR_SR_OPCODE_GET_PROTOCOL_PARAM;
SETU8(msg, i, op);
SETU8(msg, i, protocol);
SETU8(msg, i, (uint8_t)0x3f); /* option - reader write timeout */
msg[1]=i - 3; /* Install length */
ret = TMR_SR_send(reader, msg);
if (TMR_SUCCESS != ret)
{
return ret;
}
/* Get the values */
value->earlyexit = GETU8AT(msg, 7);
value->writetimeout = GETU16AT(msg, 8);
return TMR_SUCCESS;
}
TMR_Status
TMR_SR_cmdSetReaderWriteTimeOut (struct TMR_Reader *reader, TMR_TagProtocol protocol,
TMR_SR_Gen2ReaderWriteTimeOut *value)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
i = 2;
SETU8(msg, i, TMR_SR_OPCODE_SET_PROTOCOL_PARAM);
SETU8(msg, i, protocol);
SETU8(msg, i, (uint8_t)0x3f); /* option - reader write timeout */
SETU8(msg, i, (uint8_t)value->earlyexit);
SETU16(msg,i, value->writetimeout);
msg[1] = i - 3; /* Install length */
return TMR_SR_send(reader, msg);
}
TMR_Status
TMR_SR_cmdAuthReqResponse(struct TMR_Reader *reader, TMR_TagAuthentication *auth)
{
uint8_t msg[TMR_SR_MAX_PACKET_SIZE];
uint8_t i;
uint8_t opcode;
i = 2;
SETU8(msg, i, (uint8_t)TMR_SR_OPCODE_MULTI_PROTOCOL_TAG_OP);
SETU8(msg, i, (uint8_t)0x00);
SETU8(msg, i, (uint8_t)0x00);
SETU8(msg, i, (uint8_t)0x03);
SETU8(msg, i, (uint8_t)0x00);
SETU8(msg, i, (uint8_t)0x01);
SETU8(msg, i, (uint8_t)0x00);
switch (auth->type)
{
default:
return TMR_ERROR_UNSUPPORTED;
case TMR_AUTH_TYPE_GEN2_PASSWORD:
{
TMR_GEN2_Password password = auth->u.gen2Password;
SETU8(msg, i, (uint8_t)0x20);
SETU8(msg, i, (uint8_t)(password>>24));
SETU8(msg, i, (uint8_t)(password>>16));
SETU8(msg, i, (uint8_t)(password>> 8));
SETU8(msg, i, (uint8_t)(password>> 0));
}
break;
}
msg[1] = i - 3; /* Install length */
return TMR_SR_sendMessage(reader, msg, &opcode, 0);
}
#endif /* TMR_ENABLE_SERIAL_READER */