/** * @file serial_reader.c * @brief Mercury API - serial reader high level implementation * @author Nathan Williams * @date 10/28/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 #include #include #include "tm_reader.h" #include "serial_reader_imp.h" #include "tmr_utils.h" #include "osdep.h" #define HASPORT(mask, port) ((1 << ((port)-1)) & (mask)) #define TMR_MAX_PROTOCOLS (32) #ifdef TMR_ENABLE_SERIAL_READER static TMR_Status initTxRxMapFromPorts(TMR_Reader *reader) { TMR_Status ret; TMR_SR_PortDetect ports[TMR_SR_MAX_ANTENNA_PORTS]; uint8_t i, numPorts; TMR_SR_SerialReader *sr; numPorts = numberof(ports); sr = &reader->u.serialReader; /* Need number of ports to set up Tx-Rx map */ ret = TMR_SR_cmdAntennaDetect(reader, &numPorts, ports); if (TMR_SUCCESS != ret) { return ret; } sr->portMask = 0; /* Modify TxRxMap according to reader product */ switch (sr->productId) { case 0x0001: { /* Ruggedized Reader (Tool Link, Vega) */ TMR_AntennaMap newMap[] = {{1,2,2}, {2,5,5}, {3,1,1}}; numPorts = 3; for (i = 0; i < numPorts; i++) { sr->portMask |= 1 << (newMap[i].antenna - 1); sr->staticTxRxMapData[i].antenna = newMap[i].antenna; sr->staticTxRxMapData[i].rxPort = newMap[i].rxPort; sr->staticTxRxMapData[i].txPort = newMap[i].txPort; if (0 == reader->tagOpParams.antenna && ports[i].detected) { reader->tagOpParams.antenna = ports[i].port; } } break; } case 0x0002: /* * USB Reader -- Default map is okay * M5e-C only has 1 antenna port, anyway * * However, M6eMicro USB has 2 ports and no auto antenna detection, * so manually limit to first port for now. * TODO: Revisit if M6eMicro USB starts supporting port 2 in future. * port for now. */ if ((TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]) && (sr->versionInfo.hardware[3] == TMR_SR_MODEL_M6E_MICRO_USB)) { numPorts = 1; /* skip the antenna port 2 */ for (i = 0; i < numPorts; i++) { sr->portMask |= 1 << (ports[i].port - 1); sr->staticTxRxMapData[i].antenna = ports[i].port; sr->staticTxRxMapData[i].txPort = ports[i].port; sr->staticTxRxMapData[i].rxPort = ports[i].port; if (0 == reader->tagOpParams.antenna && ports[i].detected) { reader->tagOpParams.antenna = ports[i].port; } } break; } default: { for (i = 0; i < numPorts; i++) { sr->portMask |= 1 << (ports[i].port - 1); sr->staticTxRxMapData[i].antenna = ports[i].port; sr->staticTxRxMapData[i].txPort = ports[i].port; sr->staticTxRxMapData[i].rxPort = ports[i].port; if (0 == reader->tagOpParams.antenna && ports[i].detected) { reader->tagOpParams.antenna = ports[i].port; } } break; } } sr->staticTxRxMap.max = TMR_SR_MAX_ANTENNA_PORTS; sr->staticTxRxMap.len = numPorts; sr->staticTxRxMap.list = sr->staticTxRxMapData; sr->txRxMap = &sr->staticTxRxMap; return TMR_SUCCESS; } static TMR_Status TMR_SR_configPreamble(TMR_SR_SerialReader *sr) { TMR_Status ret = TMR_SUCCESS; bool value; /* Only some readers support wakeup preambles */ switch (sr->versionInfo.hardware[0]) { case TMR_SR_MODEL_M6E: case TMR_SR_MODEL_MICRO: case TMR_SR_MODEL_M6E_I: value = true; break; case TMR_SR_MODEL_M6E_NANO: value = false; break; default: value = false; break; } sr->supportsPreamble = value; return ret; } static TMR_Status TMR_SR_boot(TMR_Reader *reader, uint32_t currentBaudRate) { TMR_Status ret; uint8_t program; bool boolval; TMR_SR_SerialReader *sr; TMR_SR_SerialTransport *transport; int i; bool value; ret = TMR_SUCCESS; sr = &reader->u.serialReader; transport = &sr->transport; /* Get current program */ ret = TMR_SR_cmdGetCurrentProgram(reader, &program); if (TMR_SUCCESS != ret) { return ret; } /* If bootloader, enter app */ if ((program & 0x3) == 1) { ret = TMR_SR_cmdBootFirmware(reader); if (TMR_SUCCESS != ret) { return ret; } } /* * Once out of bootloader, configure for wakeup preambles. * Bootloader doesn't support preambles, and some versions * fail to respond to normal commands afterwards. * * It is safe to avoid preambles up to this point because * TMR_SR_connect has already been talking to the module * to keep it awake. */ ret = TMR_SR_configPreamble(sr); if (TMR_SUCCESS != ret) { return ret; } /* Initialize cached power mode value */ /* Should read power mode as soon as possible. * Default mode assumes module is in deep sleep and * adds a lengthy "wake-up preamble" to every command. */ if (sr->powerMode == TMR_SR_POWER_MODE_INVALID) { ret = TMR_paramGet(reader, TMR_PARAM_POWERMODE, &sr->powerMode); if (TMR_SUCCESS != ret) { return ret; } } /** * In case for M6E and its variant check for CRC **/ if ((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])) { /** * Get the transport/BUS type **/ ret = TMR_SR_cmdGetReaderConfiguration(reader, TMR_SR_CONFIGURATION_CURRENT_MSG_TRANSPORT, &reader->u.serialReader.transportType); if (TMR_SUCCESS != ret) { return ret; } /** * In case of USB port disable the CRC **/ if (TMR_SR_MSG_SOURCE_USB == reader->u.serialReader.transportType) { value = false; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_SEND_CRC, &value); if (TMR_SUCCESS == ret) { reader->u.serialReader.crcEnabled = false; } else { /** * Not Fatal, Going ahead with CRC enabled **/ } } } if (sr->baudRate != currentBaudRate) { 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. */ /* Bring baud rate up to the parameterized value */ ret = TMR_SR_cmdSetBaudRate(reader, sr->baudRate); if (TMR_SUCCESS != ret) { return ret; } ret = transport->setBaudRate(transport, sr->baudRate); if (TMR_SUCCESS != ret) { return ret; } } } /*ret = TMR_SR_cmdVersion(reader, &sr->versionInfo); if (TMR_SUCCESS != ret) { return ret; }*/ /* If we need to check the version information for something operational, this is the place to do it. */ sr->gpioDirections = -1; /* Needs fetching */ reader->continuousReading = ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0])); reader->continuousReading = false; //fix bug 1745 in the current release temporarily /** * This version check is required for the new reader stats. * Older firmwares does not support this. Currently, firmware version * 1.21.1.2 has support for new reader stats. **/ if ( (((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0])) && compareVersion(reader, 1, 21, 1, 2)) || ((TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]) && compareVersion(reader, 1, 3, 0, 20)) || ((TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) && compareVersion(reader, 1, 3, 2, 74)) ) { reader->_storeSupportsResetStats = true; reader->pSupportsResetStats = &(reader->_storeSupportsResetStats); } else { reader->_storeSupportsResetStats = false; reader->pSupportsResetStats = &(reader->_storeSupportsResetStats); } /* Initialize the paramPresent and paramConfirmed bits. */ /* This block is expected to be collapsed by the compiler into a * small number of constant-value writes into the sr->paramPresent * array. */ for (i = 0 ; i < TMR_PARAMWORDS; i++) { sr->paramPresent[i] = 0; } BITSET(sr->paramPresent, TMR_PARAM_BAUDRATE); BITSET(sr->paramPresent, TMR_PARAM_PROBEBAUDRATES); BITSET(sr->paramPresent, TMR_PARAM_COMMANDTIMEOUT); BITSET(sr->paramPresent, TMR_PARAM_TRANSPORTTIMEOUT); BITSET(sr->paramPresent, TMR_PARAM_POWERMODE); BITSET(sr->paramPresent, TMR_PARAM_USERMODE); BITSET(sr->paramPresent, TMR_PARAM_ANTENNA_CHECKPORT); BITSET(sr->paramPresent, TMR_PARAM_ANTENNA_PORTLIST); BITSET(sr->paramPresent, TMR_PARAM_ANTENNA_CONNECTEDPORTLIST); BITSET(sr->paramPresent, TMR_PARAM_ANTENNA_PORTSWITCHGPOS); BITSET(sr->paramPresent, TMR_PARAM_ANTENNA_SETTLINGTIMELIST); BITSET(sr->paramPresent, TMR_PARAM_ANTENNA_RETURNLOSS); BITSET(sr->paramPresent, TMR_PARAM_ANTENNA_TXRXMAP); BITSET(sr->paramPresent, TMR_PARAM_GPIO_INPUTLIST); BITSET(sr->paramPresent, TMR_PARAM_GPIO_OUTPUTLIST); BITSET(sr->paramPresent, TMR_PARAM_GEN2_ACCESSPASSWORD); BITSET(sr->paramPresent, TMR_PARAM_GEN2_Q); BITSET(sr->paramPresent, TMR_PARAM_GEN2_BAP); BITSET(sr->paramPresent, TMR_PARAM_GEN2_TAGENCODING); BITSET(sr->paramPresent, TMR_PARAM_GEN2_SESSION); BITSET(sr->paramPresent, TMR_PARAM_GEN2_TARGET); BITSET(sr->paramPresent, TMR_PARAM_GEN2_PROTOCOLEXTENSION); BITSET(sr->paramPresent, TMR_PARAM_READ_ASYNCOFFTIME); BITSET(sr->paramPresent, TMR_PARAM_READ_ASYNCONTIME); BITSET(sr->paramPresent, TMR_PARAM_READ_PLAN); BITSET(sr->paramPresent, TMR_PARAM_RADIO_ENABLEPOWERSAVE); BITSET(sr->paramPresent, TMR_PARAM_RADIO_POWERMAX); BITSET(sr->paramPresent, TMR_PARAM_RADIO_POWERMIN); BITSET(sr->paramPresent, TMR_PARAM_RADIO_PORTREADPOWERLIST); BITSET(sr->paramPresent, TMR_PARAM_RADIO_PORTWRITEPOWERLIST); BITSET(sr->paramPresent, TMR_PARAM_RADIO_READPOWER); BITSET(sr->paramPresent, TMR_PARAM_RADIO_WRITEPOWER); BITSET(sr->paramPresent, TMR_PARAM_RADIO_TEMPERATURE); BITSET(sr->paramPresent, TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI); BITSET(sr->paramPresent, TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM); BITSET(sr->paramPresent, TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA); BITSET(sr->paramPresent, TMR_PARAM_TAGREADDATA_UNIQUEBYDATA); BITSET(sr->paramPresent, TMR_PARAM_TAGOP_ANTENNA); BITSET(sr->paramPresent, TMR_PARAM_TAGOP_PROTOCOL); BITSET(sr->paramPresent, TMR_PARAM_VERSION_HARDWARE); BITSET(sr->paramPresent, TMR_PARAM_VERSION_MODEL); BITSET(sr->paramPresent, TMR_PARAM_VERSION_SOFTWARE); BITSET(sr->paramPresent, TMR_PARAM_VERSION_SERIAL); BITSET(sr->paramPresent, TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS); BITSET(sr->paramPresent, TMR_PARAM_REGION_ID); BITSET(sr->paramPresent, TMR_PARAM_REGION_SUPPORTEDREGIONS); BITSET(sr->paramPresent, TMR_PARAM_REGION_HOPTABLE); BITSET(sr->paramPresent, TMR_PARAM_REGION_HOPTIME); BITSET(sr->paramPresent, TMR_PARAM_REGION_LBT_ENABLE); BITSET(sr->paramPresent, TMR_PARAM_EXTENDEDEPC); BITSET(sr->paramPresent, TMR_PARAM_READER_STATS); BITSET(sr->paramPresent, TMR_PARAM_READER_STATISTICS); BITSET(sr->paramPresent, TMR_PARAM_URI); BITSET(sr->paramPresent, TMR_PARAM_PRODUCT_GROUP_ID); BITSET(sr->paramPresent, TMR_PARAM_PRODUCT_GROUP); BITSET(sr->paramPresent, TMR_PARAM_PRODUCT_ID); BITSET(sr->paramPresent, TMR_PARAM_TAGREADATA_TAGOPSUCCESSCOUNT); BITSET(sr->paramPresent, TMR_PARAM_TAGREADATA_TAGOPFAILURECOUNT); BITSET(sr->paramPresent, TMR_PARAM_TAGREADDATA_ENABLEREADFILTER); BITSET(sr->paramPresent, TMR_PARAM_READER_WRITE_REPLY_TIMEOUT); BITSET(sr->paramPresent, TMR_PARAM_READER_WRITE_EARLY_EXIT); BITSET(sr->paramPresent, TMR_PARAM_ISO180006B_DELIMITER); BITSET(sr->paramPresent, TMR_PARAM_ISO180006B_MODULATION_DEPTH); BITSET(sr->paramPresent, TMR_PARAM_READER_STATS_ENABLE); BITSET(sr->paramPresent, TMR_PARAM_TRIGGER_READ_GPI); if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0])) { BITSET(sr->paramPresent, TMR_PARAM_LICENSE_KEY); BITSET(sr->paramPresent, TMR_PARAM_USER_CONFIG); BITSET(sr->paramPresent, TMR_PARAM_RADIO_ENABLESJC); BITSET(sr->paramPresent, TMR_PARAM_TAGREADDATA_READFILTERTIMEOUT); BITSET(sr->paramPresent, TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL); } for (i = 0 ; i < TMR_PARAMWORDS; i++) { sr->paramConfirmed[i] = sr->paramPresent[i]; } /* Get productGroupID early, so other params (e.g., txRxMap) can use it */ { ret = TMR_SR_cmdGetReaderConfiguration(reader, TMR_SR_CONFIGURATION_PRODUCT_GROUP_ID, &sr->productId); if (TMR_SUCCESS != ret) { if (TMR_ERROR_MSG_INVALID_PARAMETER_VALUE == ret) { /* * Modules with firmware older than wilder will throw 0x105 error, as it was not * implemented. Catch this error but do not return. */ sr->productId = 0xFFFF; } else { return ret; } } /* * If product is ruggedized reader, * set reader's GPO pin which is used for antenna port switching */ if (1 == sr->productId) { uint8_t pin = 1; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ANTENNA_CONTROL_GPIO, &pin); if (TMR_SUCCESS != ret) { return ret; } } } /* Set region if user set the param */ if (TMR_REGION_NONE != sr->regionId) { ret = TMR_SR_cmdSetRegion(reader, sr->regionId); if (TMR_SUCCESS != ret) { return ret; } } ret = TMR_SR_cmdGetCurrentProtocol(reader, &sr->currentProtocol); if (TMR_SUCCESS != ret) { return ret; } if (TMR_TAG_PROTOCOL_NONE == sr->currentProtocol) { TMR_TagProtocolList protocolList; TMR_TagProtocol protocols[TMR_MAX_PROTOCOLS]; uint8_t index; protocolList.list = &protocols[0]; protocolList.max = TMR_MAX_PROTOCOLS; /* * Serach whether GEN2 Protocol is supported by reader in its protocol list. * If so set it as current protocol, else leave protocol selection to user. */ ret = TMR_SR_cmdGetAvailableProtocols(reader, &protocolList); for(index = 0; index < protocolList.len; index++) { if(TMR_TAG_PROTOCOL_GEN2 == protocolList.list[index]) { ret = TMR_SR_cmdSetProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } sr->currentProtocol = TMR_TAG_PROTOCOL_GEN2; break; } } } reader->tagOpParams.protocol = sr->currentProtocol; reader->tagOpParams.antenna = 0; ret = initTxRxMapFromPorts(reader); /** * Enable the extended EPC flag in case * of M5E and its variants */ if ((TMR_SR_MODEL_M6E != sr->versionInfo.hardware[0]) && (TMR_SR_MODEL_MICRO != sr->versionInfo.hardware[0]) && (TMR_SR_MODEL_M6E_NANO != sr->versionInfo.hardware[0]) && (TMR_SR_MODEL_M6E_I != sr->versionInfo.hardware[0])) { /* Do this only if the module is other than M6e*/ boolval = true; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_EXTENDED_EPC, &boolval); if (TMR_SUCCESS != ret) { return ret; } reader->u.serialReader.extendedEPC = boolval; } /* Report RSSI in dbm */ if ((TMR_SR_MODEL_M6E != sr->versionInfo.hardware[0]) && (TMR_SR_MODEL_MICRO != sr->versionInfo.hardware[0]) && (TMR_SR_MODEL_M6E_NANO != sr->versionInfo.hardware[0]) && (TMR_SR_MODEL_M6E_I != sr->versionInfo.hardware[0])) { /* Do this only if the module is other than M6e*/ boolval = true; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_RSSI_IN_DBM, &boolval); if (TMR_SUCCESS != ret) { return ret; } } else { /* Do this only in case of M6e */ int32_t timeout = 0; /* Get reader's enable read filter setting */ ret = TMR_SR_cmdGetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &reader->u.serialReader.enableReadFiltering); if (TMR_SUCCESS != ret) { return ret; } /* Get reader's read filter entry timeout */ ret = TMR_SR_cmdGetReaderConfiguration(reader, TMR_SR_CONFIGURATION_READ_FILTER_TIMEOUT, &timeout); if (TMR_SUCCESS != ret) { return ret; } reader->u.serialReader.readFilterTimeout = (0 == timeout) ? TMR_DEFAULT_READ_FILTER_TIMEOUT : timeout; } return ret; } /** * Probing the correct baudrate to communicate with the serial reader. * * @param reader The reader * @param currentBaudRate the baud rate at which module is communicating. */ TMR_Status TMR_SR_cmdProbeBaudRate(TMR_Reader *reader, uint32_t *currentBaudRate) { TMR_Status ret; TMR_SR_SerialReader *sr; TMR_SR_SerialTransport *transport; uint32_t rate = 0x00; int i,count = 2; ret = TMR_SUCCESS; sr = &reader->u.serialReader; transport = &reader->u.serialReader.transport; for (i = 0; (uint32_t)i < sr->probeBaudRates.len; i++) { if (i <= 1 && count) { rate = sr->baudRate; /* Try this first */ /* Module might be in deep sleep mode, if there is no response for the * first attempt, Try the same baudrate again. i = 0 and i = 1 */ count--; /* Hold i=0 (undo increment) until count has expired */ i--; } else { rate = sr->probeBaudRates.list[i]; if (rate == sr->baudRate) continue; /* We already tried this one */ } 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 = transport->setBaudRate(transport, rate); if (TMR_SUCCESS != ret) { return ret; } } ret = transport->flush(transport); if ((TMR_SUCCESS != ret) && (TMR_ERROR_UNIMPLEMENTED != ret)) { return ret; } contact: ret = TMR_SR_cmdVersion(reader, &(reader->u.serialReader.versionInfo)); if (TMR_SUCCESS == ret) { /* Got a reply? Then this is the right baud rate! */ break; } /* Timeouts are okay -- they usually mean "wrong baud rate", * so just try the next one. All other errors are real * and should be forwarded immediately. */ else if (TMR_ERROR_TIMEOUT != ret) { if (TMR_ERROR_COMM(ret)) { ret = verifySearchStatus(reader); if (TMR_SUCCESS == ret) { goto contact; } else { return ret; } } else { return ret; } } } if (i == sr->probeBaudRates.len) { return TMR_ERROR_TIMEOUT; } /* copy the baud rate */ *currentBaudRate = rate; return ret; } TMR_Status TMR_SR_connect(TMR_Reader *reader) { TMR_Status ret; uint32_t rate; TMR_SR_SerialReader *sr; TMR_SR_SerialTransport *transport; ret = TMR_SUCCESS; sr = &reader->u.serialReader; transport = &reader->u.serialReader.transport; ret = transport->open(transport); if (TMR_SUCCESS != ret) { return ret; } rate = sr->probeBaudRates.list[0]; //this fixes the compilation errors in some compilers ret = TMR_SR_cmdProbeBaudRate(reader, &rate); if (TMR_SUCCESS != ret) { return ret; } reader->connected = true; /* Boot */ ret = TMR_SR_boot(reader, rate); if(ret !=TMR_SUCCESS) { if(ret == TMR_ERROR_AUTOREAD_ENABLED) { ret = verifySearchStatus(reader); if (TMR_SUCCESS != ret) { return ret; } ret = TMR_SR_boot(reader, rate); } } return ret; } TMR_Status TMR_SR_destroy(TMR_Reader *reader) { TMR_SR_SerialTransport *transport; reader->hasContinuousReadStarted = false; transport = &reader->u.serialReader.transport; /** * Enable the CRC, in case it is disabled **/ if (false == reader->u.serialReader.crcEnabled) { reader->u.serialReader.crcEnabled = true; TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_SEND_CRC, &reader->u.serialReader.crcEnabled); } transport->shutdown(transport); reader->connected = false; #ifdef TMR_ENABLE_BACKGROUND_READS /* Cleanup background threads */ cleanup_background_threads(reader); #endif return TMR_SUCCESS; } static TMR_Status autoDetectAntennaList(struct TMR_Reader *reader) { TMR_Status ret; TMR_SR_PortDetect ports[TMR_SR_MAX_ANTENNA_PORTS]; TMR_SR_PortPair searchList[TMR_SR_MAX_ANTENNA_PORTS]; uint8_t i, listLen, numPorts; uint16_t j; TMR_AntennaMapList *map; ret = TMR_SUCCESS; map = reader->u.serialReader.txRxMap; /* 1. Detect current set of antennas */ numPorts = TMR_SR_MAX_ANTENNA_PORTS; ret = TMR_SR_cmdAntennaDetect(reader, &numPorts, ports); if (TMR_SUCCESS != ret) { return ret; } /* 2. Set antenna list based on detected antennas (Might be clever * to cache this and not bother sending the set-list command * again, but it's more code and data space). */ for (i = 0, listLen = 0; i < numPorts; i++) { if (ports[i].detected) { /* Ensure that the port exists in the map */ for (j = 0; j < map->len; j++) if (ports[i].port == map->list[j].txPort) { searchList[listLen].txPort = map->list[j].txPort; searchList[listLen].rxPort = map->list[j].rxPort; listLen++; break; } } } if (0 == listLen) /* No ports auto-detected */ { return TMR_ERROR_NO_ANTENNA; } ret = TMR_SR_cmdSetAntennaSearchList(reader, listLen, searchList); return ret; } static TMR_Status setAntennaList(struct TMR_Reader *reader, TMR_uint8List *antennas) { TMR_SR_PortPair searchList[16]; uint16_t i, j, listLen; TMR_AntennaMapList *map; map = reader->u.serialReader.txRxMap; /** @todo cache the set list and don't reset it if it hasn't changed */ listLen = 0; for (i = 0; i < antennas->len ; i++) { for (j = 0; j < map->len; j++) { if (antennas->list[i] == map->list[j].antenna) { searchList[listLen].txPort = map->list[j].txPort; searchList[listLen].rxPort = map->list[j].rxPort; listLen++; break; } } } return TMR_SR_cmdSetAntennaSearchList(reader,(uint8_t)listLen, searchList); } static TMR_Status setProtocol(struct TMR_Reader *reader, TMR_TagProtocol protocol) { TMR_Status ret; if(reader->u.serialReader.currentProtocol != protocol) { ret = TMR_SR_cmdSetProtocol(reader, protocol); if (TMR_SUCCESS != ret) { return ret; } /* Set extended EPC -- This bit is reset when the protocol changes */ if (reader->u.serialReader.extendedEPC) { bool boolval; boolval = true; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_EXTENDED_EPC, &boolval); if (TMR_SUCCESS != ret) { return ret; } } reader->u.serialReader.currentProtocol = protocol; /* Set enable filtering -- module automatically resets this when protocol is changed */ ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &reader->u.serialReader.enableReadFiltering); if (TMR_SUCCESS != ret) { return ret; } { /* Set the read filter timeout */ uint32_t moduleValue = (TMR_DEFAULT_READ_FILTER_TIMEOUT == reader->u.serialReader.readFilterTimeout) ? 0 : reader->u.serialReader.readFilterTimeout; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_READ_FILTER_TIMEOUT, &moduleValue); if (TMR_SUCCESS != ret) { return ret; } reader->u.serialReader.readFilterTimeout = moduleValue; } } return TMR_SUCCESS; } /** * Compare two firmware versions, return true current firmware is higher than refernced firmware. * else return false; **/ bool compareVersion(TMR_Reader *reader, uint8_t firstByte, uint8_t secondByte, uint8_t thirdByte, uint8_t fourthByte) { TMR_SR_SerialReader *sr = &reader->u.serialReader; uint8_t temp; /* compre the first byte */ temp = sr->versionInfo.fwVersion[0]; if (temp > firstByte) { /* Higher version, return true */ return true; } else if (temp < firstByte) { /* lower version, return flase */ return false; } else { /* Compare the second byte */ temp = sr->versionInfo.fwVersion[1]; if (temp > secondByte) { /* Higher version, return true */ return true; } else if (temp < secondByte) { /* lower version, return flase */ return false; } else { /* compare the third byte */ temp = sr->versionInfo.fwVersion[2]; if (temp > thirdByte) { /* Higher version, return true */ return true; } else if (temp < thirdByte) { /* lower version, return flase */ return false; } else { /* compare the fourth byte */ temp = sr->versionInfo.fwVersion[3]; if (temp > fourthByte) { return true; } else if (temp < fourthByte) { /* lower version, return flase */ return false; } else { /* both the firmwares are equal */ return true; } } } } } /** * Compare antenna list in readplans list, return true if antenna * list are consistent across the entire set of read plans. **/ bool compareAntennas(TMR_MultiReadPlan *multi) { TMR_ReadPlan *plan1, *plan2; uint8_t allAntennasNull = 0; uint8_t matchingPlanCount = 0; uint8_t i; bool status = false; for (i = 0; i < multi->planCount; i++) { plan1 = multi->plans[0]; plan2 = multi->plans[i]; if ((0 != plan1->u.simple.antennas.len) && (0 != plan2->u.simple.antennas.len)) { uint8_t j; if (plan1->u.simple.antennas.len == plan2->u.simple.antennas.len) { for (j = 0; j < plan1->u.simple.antennas.len; j++) { if (plan1->u.simple.antennas.list[j] != plan2->u.simple.antennas.list[j]) { status = false; break; } } if (j == plan1->u.simple.antennas.len) { matchingPlanCount++; } } } else if ((0 == plan1->u.simple.antennas.len) && (0 == plan2->u.simple.antennas.len)) { allAntennasNull++; } else { status = false; break; } } if ((matchingPlanCount == multi->planCount) || (allAntennasNull == multi->planCount)) { status = true; } return status; } TMR_Status prepForSearch(TMR_Reader *reader, TMR_uint8List *antennaList) { TMR_Status ret; if (antennaList->len == 0) { ret = autoDetectAntennaList(reader); } else { ret = setAntennaList(reader, antennaList); } return ret; } static TMR_Status prepEmbReadTagMultiple(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, uint8_t *lenbyte) { TMR_Status ret; ret = TMR_SR_msgSetupReadTagMultiple(reader, msg, i, (uint16_t)timeout, searchFlag, filter, protocol, accessPassword); /* Embedded command count (Currently supports only one command)*/ SETU8(msg, *i, 1); *lenbyte = (*i)++; return ret; } static TMR_Status TMR_SR_read_internal(struct TMR_Reader *reader, uint32_t timeoutMs, int32_t *tagCount, TMR_ReadPlan *rp) { TMR_Status ret = TMR_SUCCESS; TMR_SR_SerialReader *sr; TMR_SR_MultipleStatus multipleStatus = {0}; uint32_t count, elapsed, elapsed_tagop; uint32_t readTimeMs, starttimeLow, starttimeHigh; TMR_uint8List *antennaList = NULL; sr = &reader->u.serialReader; if (TMR_READ_PLAN_TYPE_MULTI == rp->type) { int 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_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]))) || (true == reader->continuousReading) ) { TMR_SR_SearchFlag antennas = TMR_SR_SEARCH_FLAG_CONFIGURED_LIST; 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; } /** * take the time stamp only in case of sync read, * async read does not depend on this **/ if (!reader->continuousReading) { /* Cache the read time so it can be put in tag read data later */ tm_gettime_consistent(&starttimeHigh, &starttimeLow); sr->readTimeHigh = starttimeHigh; sr->readTimeLow = starttimeLow; sr->lastSentTagTimestampHigh = starttimeHigh; sr->lastSentTagTimestampLow = starttimeLow; } if (reader->continuousReading) { bool value = false; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, &value); if (TMR_SUCCESS != ret) { return ret; } } ret = TMR_SR_cmdMultipleProtocolSearch(reader, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE, protocolList, reader->userMetadataFlag, antennas, filters, (uint16_t)timeoutMs, &count); if (NULL != tagCount) { *tagCount += count; } return ret; } } if (TMR_READ_PLAN_TYPE_SIMPLE == rp->type) { antennaList = &rp->u.simple.antennas; reader->fastSearch = rp->u.simple.useFastSearch; reader->triggerRead = rp->u.simple.triggerRead.enable; if (!reader->continuousReading) { /* Currently only supported for sync read case */ reader->isStopNTags = rp->u.simple.stopOnCount.stopNTriggerStatus; reader->numberOfTagsToRead = rp->u.simple.stopOnCount.noOfTags; } } else if (TMR_READ_PLAN_TYPE_MULTI == rp->type) { uint32_t subTimeout; int i; subTimeout = 0; if (0 == rp->u.multi.totalWeight) { subTimeout = timeoutMs / rp->u.multi.planCount; } for (i = 0; i < rp->u.multi.planCount; i++) { if (rp->u.multi.totalWeight) { subTimeout = rp->u.multi.plans[i]->weight * timeoutMs / rp->u.multi.totalWeight; } ret = TMR_SR_read_internal(reader, subTimeout, tagCount, rp->u.multi.plans[i]); if (TMR_SUCCESS != ret && TMR_ERROR_NO_TAGS_FOUND != ret) { return ret; } } return ret; } else { return TMR_ERROR_INVALID; } /* At this point we're guaranteed to have a simple read plan */ ret = prepForSearch(reader, antennaList); if (TMR_SUCCESS != ret) { return ret; } /* Set protocol to that specified by the read plan. */ ret = setProtocol(reader, rp->u.simple.protocol); 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; } } /* Cache the read time so it can be put in tag read data later */ tm_gettime_consistent(&starttimeHigh, &starttimeLow); sr->readTimeHigh = starttimeHigh; sr->readTimeLow = starttimeLow; sr->lastSentTagTimestampHigh = starttimeHigh; sr->lastSentTagTimestampLow = starttimeLow; /* Cache search timeout for later call to streaming receive */ sr->searchTimeoutMs = timeoutMs; elapsed = tm_time_subtract(tmr_gettime_low(), starttimeLow); elapsed_tagop = elapsed; /** * Ignoring the elapsed time calculation in case of true * continuous reading, */ if ((reader->continuousReading) && (0 != timeoutMs)) { elapsed = timeoutMs - 1; } while (elapsed <= timeoutMs) { readTimeMs = timeoutMs - elapsed; if (readTimeMs > 65535) { readTimeMs = 65535; } if (NULL == rp->u.simple.tagop) { if(reader->continuousReading) { 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; protocolList->len = 1; protocolList->max = 1; protocolList->list = protocols; 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_cmdMultipleProtocolSearch(reader, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE, protocolList, reader->userMetadataFlag, antennas, filters, (uint16_t)timeoutMs, &count); } else { ret = TMR_SR_cmdReadTagMultiple(reader,(uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, &count); } } else { uint8_t msg[256]; uint8_t i, lenbyte; /* Since this is embedded tagop, removing elapsed time based on * continuous reading should not be done */ readTimeMs = timeoutMs - elapsed_tagop; if (readTimeMs > 65535) { readTimeMs = 65535; } i = 2; /** * add the tagoperation **/ ret = TMR_SR_addTagOp(reader, rp->u.simple.tagop, rp, msg, &i, readTimeMs, &lenbyte); if (TMR_SUCCESS != ret) { return ret; } msg[lenbyte] = i - (lenbyte + 2); /* Install length of subcommand */ msg[1] = i - 3; /* Install length */ ret = TMR_SR_executeEmbeddedRead(reader, msg, (uint16_t)timeoutMs, &multipleStatus); count = multipleStatus.tagsFound; /* Update embedded tagop success/failure count */ reader->u.serialReader.tagopSuccessCount += multipleStatus.successCount; reader->u.serialReader.tagopFailureCount += multipleStatus.failureCount; } if (TMR_ERROR_NO_TAGS_FOUND == ret) { count = 0; ret = TMR_SUCCESS; } else if (TMR_ERROR_TM_ASSERT_FAILED == ret) { return ret; } else if (TMR_ERROR_TIMEOUT == ret) { return ret; } else if (TMR_SUCCESS != ret) { uint16_t remainingTagsCount; TMR_Status ret1; reader->isStopNTags = false; /* Check for the tag count (in case of module error)*/ ret1 = TMR_SR_cmdGetTagsRemaining(reader, &remainingTagsCount); if (TMR_SUCCESS != ret1) { return ret1; } sr->tagsRemaining += remainingTagsCount; if (NULL != tagCount) { *tagCount += remainingTagsCount; } return ret; } sr->tagsRemaining += count; if (NULL != tagCount) { *tagCount += count; } if (reader->continuousReading) { sr->tagsRemaining = 1; break; } else if (reader->isStopNTags && !reader->continuousReading) { /** * No need to loop back for stop N tags **/ break; } else { elapsed = tm_time_subtract(tmr_gettime_low(), starttimeLow); } } return ret; } /* Reset reader stats (unless command not supported by reader) */ static TMR_Status _resetReaderStats(TMR_Reader *reader, TMR_Reader_StatsFlag statFlags) { TMR_Status ret; if ((NULL != reader->pSupportsResetStats) && (false == *(reader->pSupportsResetStats))) { /* Command not supported, just skip it */ ret = TMR_SUCCESS; } else { ret = TMR_SR_cmdResetReaderStats(reader, statFlags); /* Initialize reader->pSupportsResetStats, if necessary*/ if (NULL == reader->pSupportsResetStats) { switch (ret) { case TMR_SUCCESS: reader->_storeSupportsResetStats = true; reader->pSupportsResetStats = &(reader->_storeSupportsResetStats); break; case TMR_ERROR_MSG_WRONG_NUMBER_OF_DATA: case TMR_ERROR_INVALID_OPCODE: case TMR_ERROR_UNIMPLEMENTED_OPCODE: case TMR_ERROR_UNIMPLEMENTED_FEATURE: case TMR_ERROR_INVALID: case TMR_ERROR_UNIMPLEMENTED: case TMR_ERROR_UNSUPPORTED: case TMR_ERROR_UNSUPPORTED_READER_TYPE: /* If command unsupported, make a note not to do it again then * proceed normally */ reader->_storeSupportsResetStats = false; reader->pSupportsResetStats = &(reader->_storeSupportsResetStats); ret = TMR_SUCCESS; break; } } } return ret; } TMR_Status TMR_SR_read(struct TMR_Reader *reader, uint32_t timeoutMs, int32_t *tagCount) { TMR_Status ret; TMR_ReadPlan *rp; /** * Reset the reader statistics at the beginning of every search, * currently reader statistics only supports in m6e.. * TO DO: Enable this for other readers in future. */ ret = _resetReaderStats(reader, TMR_READER_STATS_FLAG_ALL); if (TMR_SUCCESS != ret) { return ret; } if (!reader->continuousReading) { /** * In case of sync read only * clear tag buffer */ ret = TMR_SR_cmdClearTagBuffer(reader); if (TMR_SUCCESS != ret) { return ret; } } reader->u.serialReader.tagsRemaining = 0; #ifdef TMR_ENABLE_BACKGROUND_READS if (false == reader->backgroundEnabled) /** * if TMR_ENABLE_BACKGROUND_READS is not defined, then * only sync read is possible. (Continuous and pseudo async reads * are not available) **/ #endif { /* If sync read, then reset tagop result count here */ reader->u.serialReader.tagopSuccessCount = 0; reader->u.serialReader.tagopFailureCount = 0; } rp = reader->readParams.readPlan; if (tagCount) { *tagCount = 0; } ret = TMR_SR_read_internal(reader, timeoutMs, tagCount, rp); if (ret != TMR_SUCCESS) { return ret; } if (reader->continuousReading) reader->hasContinuousReadStarted = true; return ret; } TMR_Status verifySearchStatus(TMR_Reader *reader) { TMR_SR_SerialReader *sr; TMR_Status ret; uint8_t *msg; uint32_t timeoutMs; bool crcEnable; sr = &reader->u.serialReader; msg = sr->bufResponse; timeoutMs = sr->searchTimeoutMs; reader->u.serialReader.crcEnabled = false; TMR_SR_cmdStopReading(reader); while(true) { ret = TMR_SR_receiveMessage(reader, msg, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE, timeoutMs); if(TMR_SUCCESS == ret || TMR_ERROR_DEVICE_RESET == ret) { if ((0x2F == msg[2]) && (0x02 == msg[5])) { /** * 0x2F with type 0x02 means stop continuous reading. * Module has already pushed all the tagreads before * sending this response. i.e., reading is finished **/ if (TMR_SR_MSG_SOURCE_USB == reader->u.serialReader.transportType) { crcEnable = false; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_SEND_CRC, &crcEnable); if (TMR_SUCCESS == ret) reader->u.serialReader.crcEnabled = false; else reader->u.serialReader.crcEnabled = true; } else { reader->u.serialReader.crcEnabled = true; } return TMR_SUCCESS; } else if ((0x2F == msg[2]) && (0x01 == msg[3] && (0x00 == msg[4]))) { /** * 0x2F with error status can also be treated as response for * stop continuous reading. **/ return TMR_SUCCESS; } } else { /** * We might get comm errors here, either CRC or TIMEOUT errors * What should we do here?? **/ if (TMR_ERROR_CRC_ERROR == ret) { /** * When the module is pushing all tags out, just don't bother about * CRC and keep waiting for response for stopReading **/ continue; } if (TMR_ERROR_TIMEOUT == ret) { return ret; } } } } TMR_Status TMR_SR_hasMoreTags(struct TMR_Reader *reader) { TMR_SR_SerialReader* sr; TMR_Status ret; sr = &reader->u.serialReader; //#ifdef TMR_ENABLE_BACKGROUND_READS if ((reader->continuousReading) && (0 == sr->tagsRemainingInBuffer)) { uint8_t *msg; uint32_t timeoutMs; uint8_t response_type_pos; uint8_t response_type; msg = sr->bufResponse; timeoutMs = sr->searchTimeoutMs; ret = TMR_SR_receiveMessage(reader, msg, TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE, timeoutMs); if (TMR_ERROR_TAG_ID_BUFFER_AUTH_REQUEST == ret) { /* Tag password needed to complete tagop. * Parse TagReadData and pass to password-generating callback, * which will return the appropriate authentication. */ uint16_t flags = 0; uint8_t bufptr; TMR_TagReadData trd; TMR_TagAuthentication tauth; TMR_TRD_init(&trd); /* In case of streaming the flags always start at position 8 */ bufptr = 8; flags = GETU16AT(msg, bufptr); bufptr += 2; bufptr++; /* Skip tag count (always = 1) */ TMR_SR_parseMetadataFromMessage(reader, &trd, flags, &bufptr, msg); TMR_SR_postprocessReaderSpecificMetadata(&trd, sr); trd.reader = reader; #ifndef BARE_METAL // printf("Parsed 0604 TagReadData: readCount=%d rssi=%d ant=%d, freq=%d, t_hi=%X, t_lo=%X\n", //trd.readCount, trd.rssi, trd.antenna, trd.frequency, trd.timestampHigh, trd.timestampLow, trd.phase); { notify_authreq_listeners(reader, &trd, &tauth); } #endif /* TODO: Factor out password generation into callback */ reader->hasContinuousReadStarted = false; ret = TMR_SR_cmdAuthReqResponse(reader, &tauth); if (reader->continuousReading) reader->hasContinuousReadStarted = true; if (TMR_SUCCESS != ret) { return ret; } else { return TMR_ERROR_TAG_ID_BUFFER_AUTH_REQUEST; } } if ((TMR_SUCCESS != ret) && (TMR_ERROR_TAG_ID_BUFFER_FULL != ret) && ((TMR_ERROR_NO_TAGS_FOUND != ret) || ((TMR_ERROR_NO_TAGS_FOUND == ret) && (0 == msg[1])))) { if (msg[5] != 0x04 || msg[2] != 0x2f) { reader->u.serialReader.isBasetimeUpdated = false; return ret; } } ret = (0 == GETU16AT(msg, 3)) ? TMR_SUCCESS : TMR_ERROR_CODE(GETU16AT(msg, 3)); if ((TMR_SUCCESS == ret) && (0 == msg[1])) { /** * In case of streaming and ISO protocol after every search cycle * module sends the response for embedded operation status as * FF 00 22 00 00. * In this case return back with 0x400 error, because success response will deceive * the read thread to process it. For GEN2 case we got the response with 0x400 status. **/ return TMR_ERROR_NO_TAGS_FOUND; } if (((0x2F == msg[2]) && (TMR_ERROR_TAG_ID_BUFFER_FULL == ret)) ||((0x22 == msg[2]) && (TMR_ERROR_TAG_ID_BUFFER_FULL == ret))) { return ret; } if (0x2F == msg[2]) { if (0x02 == msg[5]) { /** * 0x2F with type 0x02 means stop continuous reading. * Module has already pushed all the tagreads before * sending this response. i.e., reading is finished **/ reader->finishedReading = true; reader->u.serialReader.isBasetimeUpdated = false; return TMR_ERROR_END_OF_READING; } else if (0x03 == msg[5]) { /** * 0x2F with type 0x03 means left over client Auth message/response, ignore it. **/ return TMR_ERROR_TAG_ID_BUFFER_AUTH_REQUEST; } else if (0x04 == msg[5]) { memcpy(&reader->paramMessage[0], msg, (msg[1] + 5) * sizeof(uint8_t)); reader->paramWait = false; } /** * Control comes here in case of the response received * for start continuous reading command. (0x2F with type 0x01) **/ return TMR_ERROR_NO_TAGS; } else if (msg[1] < 6) { /* Need at least enough bytes to get to Response Type field */ return TMR_ERROR_PARSE; } response_type_pos = (0x10 == (msg[5] & 0x10)) ? 10 : 8; response_type = msg[response_type_pos]; switch (response_type) { case 0x02: /* Handle status stream responses */ reader->isStatusResponse = true; sr->bufPointer = 9; return TMR_SUCCESS; case 0x01: /* Stream continues after this message */ reader->isStatusResponse = false; sr->tagsRemainingInBuffer = 1; sr->bufPointer = 11; return TMR_SUCCESS; case 0x00: /* while fixing bug#4190, Missed updating base timestamp for embedded read. Because of this time stamps are falling back.To fix this issue updated base time stamp. */ reader->u.serialReader.isBasetimeUpdated = false; /* Stream ends with this message */ sr->tagsRemaining = 0; if (sr->oldQ.type != TMR_SR_GEN2_Q_INVALID) { ret = TMR_paramSet(reader, TMR_PARAM_GEN2_Q, &(sr->oldQ)); if (TMR_SUCCESS != ret) { return ret; } sr->oldQ.type = TMR_SR_GEN2_Q_INVALID; } if (NULL != reader->readParams.readPlan->u.simple.tagop) { response_type_pos += 7; sr->tagopSuccessCount += GETU16(msg, response_type_pos); sr->tagopFailureCount += GETU16(msg, response_type_pos); } if (TMR_SUCCESS == ret) { /* If things look good so far, signal that we are done with tags */ return TMR_ERROR_NO_TAGS; } /* otherwise feed the error back (should only be TMR_ERROR_TAG_ID_BUFFER_FULL) */ return ret; default: /* Unknown response type */ return TMR_ERROR_PARSE; } } else //#endif { /** * TMR_SR_hasMoreTags control comes here only in case of sync reading * And in case of pseudo async reading when TMR_ENABLE_BACKGROUND_READS * is defined. **/ ret = (sr->tagsRemaining > 0) ? TMR_SUCCESS : TMR_ERROR_NO_TAGS; return ret; } } TMR_Status TMR_SR_getNextTag(struct TMR_Reader *reader, TMR_TagReadData *read) { TMR_SR_SerialReader *sr; TMR_Status ret; uint8_t *msg; uint8_t i; uint16_t flags = 0; uint32_t timeoutMs; uint8_t subResponseLen = 0; uint8_t crclen = 2 ; uint8_t epclen = 0; sr = &reader->u.serialReader; timeoutMs = sr->searchTimeoutMs; { msg = sr->bufResponse; if (sr->tagsRemaining == 0) { return TMR_ERROR_NO_TAGS; } if (sr->tagsRemainingInBuffer == 0) { /* Fetch the next set of tags from the reader */ if (reader->continuousReading) { ret = TMR_SR_hasMoreTags(reader); if (TMR_SUCCESS != ret) { return ret; } } else { if (reader->u.serialReader.opCode == TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE) { i = 2; SETU8(msg, i, TMR_SR_OPCODE_GET_TAG_ID_BUFFER); SETU16(msg, i, reader->userMetadataFlag); SETU8(msg, i, 0); /* read options */ msg[1] = i-3; /* Install length */ ret = TMR_SR_send(reader, msg); if (TMR_SUCCESS != ret) { return ret; } sr->tagsRemainingInBuffer = msg[8]; sr->bufPointer = 9; } else if (reader->u.serialReader.opCode == TMR_SR_OPCODE_READ_TAG_ID_SINGLE) { TMR_SR_receiveMessage(reader, msg, reader->u.serialReader.opCode, timeoutMs); sr->tagsRemainingInBuffer = (uint8_t)GETU32AT(msg , 9); sr->tagsRemaining = sr->tagsRemainingInBuffer; sr->bufPointer = 13 ; } else { return TMR_ERROR_INVALID_OPCODE; } } } i = sr->bufPointer; if (reader->u.serialReader.opCode == TMR_SR_OPCODE_READ_TAG_ID_MULTIPLE) { flags = GETU16AT(msg, reader->continuousReading ? 8 : 5); TMR_SR_parseMetadataFromMessage(reader, read, flags, &i, msg); } if (reader->u.serialReader.opCode == TMR_SR_OPCODE_READ_TAG_ID_SINGLE) { flags = GETU16AT(msg, i + 6); subResponseLen = msg[i+1]; i += 7; TMR_SR_parseMetadataOnly(reader, read, flags, &i, msg); epclen = subResponseLen + 4 - (i - sr->bufPointer) - crclen; read->tag.epcByteCount=epclen; memcpy(&(read->tag.epc), &msg[i], read->tag.epcByteCount); i+=epclen; read->tag.crc = GETU16(msg, i); } sr->bufPointer = i; TMR_SR_postprocessReaderSpecificMetadata(read, sr); sr->tagsRemainingInBuffer--; if (false == reader->continuousReading) { sr->tagsRemaining--; } read->reader = reader; return TMR_SUCCESS; } } TMR_Status TMR_SR_writeTag(struct TMR_Reader *reader, const TMR_TagFilter *filter, const TMR_TagData *data) { TMR_Status ret; TMR_SR_SerialReader *sr; sr = &reader->u.serialReader; ret = setProtocol(reader, reader->tagOpParams.protocol); if (TMR_SUCCESS != ret) { return ret; } if (TMR_TAG_PROTOCOL_GEN2 == reader->tagOpParams.protocol) { return TMR_SR_cmdWriteGen2TagEpc(reader, filter, sr->gen2AccessPassword, (uint16_t)(sr->commandTimeout), data->epcByteCount, data->epc, 0); } else { return TMR_ERROR_UNIMPLEMENTED; } } TMR_Status TMR_SR_readTagMemWords(TMR_Reader *reader, const TMR_TagFilter *target, uint32_t bank, uint32_t wordAddress, uint16_t wordCount, uint16_t data[]) { TMR_Status ret; ret = TMR_SR_readTagMemBytes(reader, target, bank, wordAddress * 2, wordCount * 2, (uint8_t *)data); if (TMR_SUCCESS != ret) { return ret; } #ifndef TMR_BIG_ENDIAN_HOST { uint16_t i; uint8_t *data8; /* We used the uint16_t data as temporary storage for the values read, but we need to adjust for possible endianness differences. This is technically correct on all platforms, though it's a no-op on big-endian ones. */ data8 = (uint8_t *)data; for (i = 0; i < wordCount; i++) { data[i] = (data8[2*i] << 8) | data8[2*i + 1]; } } #endif return TMR_SUCCESS; } static TMR_Status TMR_SR_readTagMemBytesUnaligned(TMR_Reader *reader, const TMR_TagFilter *target, uint32_t bank, uint32_t byteAddress, uint16_t byteCount, uint8_t data[]) { TMR_Status ret; TMR_TagReadData read; uint16_t wordCount; uint8_t buf[254]; TMR_SR_SerialReader *sr; sr = &reader->u.serialReader; wordCount = (uint16_t)((byteCount + 1 + (byteAddress & 1) ) / 2); read.data.max = 254; read.data.list = buf; read.metadataFlags = 0; ret = TMR_SR_cmdGEN2ReadTagData(reader, (uint16_t)(sr->commandTimeout), (TMR_GEN2_Bank)bank, byteAddress / 2, (uint8_t)wordCount, sr->gen2AccessPassword, target, &read); if (TMR_SUCCESS != ret) { return ret; } memcpy(data, buf + (byteAddress & 1), byteCount); return TMR_SUCCESS; } TMR_Status TMR_SR_readTagMemBytes(TMR_Reader *reader, const TMR_TagFilter *target, uint32_t bank, uint32_t byteAddress, uint16_t byteCount, uint8_t data[]) { TMR_Status ret; TMR_TagReadData read; TMR_SR_SerialReader *sr; sr = &reader->u.serialReader; ret = setProtocol(reader, reader->tagOpParams.protocol); if (TMR_SUCCESS != ret) { return ret; } read.data.max = byteCount; read.data.list = (uint8_t *)data; read.metadataFlags = 0; if (TMR_TAG_PROTOCOL_GEN2 == reader->tagOpParams.protocol) { /* * Handling unaligned reads takes spare memory; avoid allocating that * (on that stack) if not necessary. */ if ((byteAddress & 1) || (byteCount & 1)) { return TMR_SR_readTagMemBytesUnaligned(reader, target, bank, byteAddress, byteCount, data); } return TMR_SR_cmdGEN2ReadTagData(reader, (uint16_t)(sr->commandTimeout), (TMR_GEN2_Bank)bank, byteAddress / 2, byteCount / 2, sr->gen2AccessPassword, target, &read); } #ifdef TMR_ENABLE_ISO180006B else if (TMR_TAG_PROTOCOL_ISO180006B == reader->tagOpParams.protocol) { return TMR_SR_cmdISO180006BReadTagData(reader,(uint16_t)(sr->commandTimeout), (uint8_t)byteAddress, (uint8_t)byteCount, target, &read); } #endif /* TMR_ENABLE_ISO180006B */ else { return TMR_ERROR_UNIMPLEMENTED; } } TMR_Status TMR_SR_modifyFlash(TMR_Reader *reader, uint8_t sector, uint32_t address, uint32_t password, uint8_t length, const uint8_t data[], uint32_t offset) { /** * As only M6e reader and it's varient supports modifying the flash in * application mode.Hence, this check is required. */ if ((TMR_SR_MODEL_M6E == reader->u.serialReader.versionInfo.hardware[0])|| (TMR_SR_MODEL_MICRO == reader->u.serialReader.versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == reader->u.serialReader.versionInfo.hardware[0])) { return TMR_SR_cmdModifyFlashSector(reader, sector, address, password, length, data, offset); } else return TMR_ERROR_UNSUPPORTED; } TMR_Status TMR_SR_writeTagMemWords(struct TMR_Reader *reader, const TMR_TagFilter *filter, uint32_t bank, uint32_t address, uint16_t count, const uint16_t data[]) { const uint8_t *dataPtr; #ifndef TMR_BIG_ENDIAN_HOST uint8_t buf[254]; int i; for (i = 0 ; i < count ; i++) { buf[2*i ] = data[i] >> 8; buf[2*i + 1] = data[i] & 0xff; } dataPtr = buf; #else dataPtr = (const uint8_t *)data; #endif return TMR_SR_writeTagMemBytes(reader, filter, bank, address * 2, count * 2, dataPtr); } TMR_Status TMR_SR_writeTagMemBytes(struct TMR_Reader *reader, const TMR_TagFilter *filter, uint32_t bank, uint32_t address, uint16_t count, const uint8_t data[]) { TMR_Status ret; TMR_SR_SerialReader *sr; TMR_GEN2_WriteMode mode; TMR_GEN2_WriteMode *value = &mode; sr = &reader->u.serialReader; TMR_paramGet(reader, TMR_PARAM_GEN2_WRITEMODE, value); ret = setProtocol(reader, reader->tagOpParams.protocol); if (TMR_SUCCESS != ret) { return ret; } if (TMR_TAG_PROTOCOL_GEN2 == reader->tagOpParams.protocol) { /* Buffer for converting to Gen2 native word size. * A waste of space, but the only way to do byte/word conversions without * munging the original data input. ReadTagMemBytes is deprecated, anyway, * along with all the other protocol-independent methods, so avoid using it, * if possible. */ uint16_t data16[TMR_SR_MAX_PACKET_SIZE/2]; uint16_t wordCount; uint16_t iWord; /* Misaligned writes are not permitted */ if ((address & 1) || (count & 1)) { return TMR_ERROR_INVALID; } wordCount = count/2; for (iWord=0; iWordcommandTimeout), (TMR_GEN2_Bank)bank, address / 2, (uint8_t)count, data, sr->gen2AccessPassword, filter); case TMR_GEN2_BLOCK_ONLY: return TMR_SR_cmdBlockWrite(reader,(uint16_t)sr->commandTimeout, (TMR_GEN2_Bank)bank, address / 2, (uint8_t)(count/2), data16, sr->gen2AccessPassword, filter); case TMR_GEN2_BLOCK_FALLBACK: ret = TMR_SR_cmdBlockWrite(reader,(uint16_t)sr->commandTimeout, (TMR_GEN2_Bank)bank, address / 2, (uint8_t)(count/2), data16, sr->gen2AccessPassword, filter); if (TMR_SUCCESS == ret) { return ret; } else { return TMR_SR_cmdGEN2WriteTagData(reader, (uint16_t)(sr->commandTimeout), (TMR_GEN2_Bank)bank, address / 2, (uint8_t)count, data, sr->gen2AccessPassword, filter); } default: return TMR_ERROR_INVALID_WRITE_MODE; } } #ifdef TMR_ENABLE_ISO180006B else if (TMR_TAG_PROTOCOL_ISO180006B == reader->tagOpParams.protocol) { if (count != 1) { return TMR_ERROR_INVALID; } return TMR_SR_cmdISO180006BWriteTagData(reader, (uint16_t)(sr->commandTimeout), (uint8_t)address, 1, data, filter); } #endif else { return TMR_ERROR_INVALID; } } TMR_Status TMR_SR_lockTag(struct TMR_Reader *reader, const TMR_TagFilter *filter, TMR_TagLockAction *action) { TMR_Status ret; TMR_SR_SerialReader *sr; sr = &reader->u.serialReader; ret = setProtocol(reader, reader->tagOpParams.protocol); if (TMR_SUCCESS != ret) { return ret; } if (TMR_TAG_PROTOCOL_GEN2 == reader->tagOpParams.protocol) { if (TMR_LOCK_ACTION_TYPE_GEN2_LOCK_ACTION != action->type) { /* Lock type doesn't match tagop protocol */ return TMR_ERROR_INVALID; } return TMR_SR_cmdGEN2LockTag(reader, (uint16_t)sr->commandTimeout, action->u.gen2LockAction.mask, action->u.gen2LockAction.action, sr->gen2AccessPassword, filter); } #ifdef TMR_ENABLE_ISO180006B else if (TMR_TAG_PROTOCOL_ISO180006B == reader->tagOpParams.protocol) { if (TMR_LOCK_ACTION_TYPE_ISO180006B_LOCK_ACTION != action->type) { /* Lock type doesn't match tagop protocol */ return TMR_ERROR_INVALID; } return TMR_SR_cmdISO180006BLockTag(reader, (uint16_t)(sr->commandTimeout), action->u.iso180006bLockAction.address, filter); } #endif else { return TMR_ERROR_UNIMPLEMENTED; } } TMR_Status TMR_SR_reboot(TMR_Reader *reader) { TMR_Status ret; ret = TMR_SR_cmdrebootReader(reader); return ret; } TMR_Status TMR_SR_killTag(struct TMR_Reader *reader, const TMR_TagFilter *filter, const TMR_TagAuthentication *auth) { TMR_Status ret; TMR_SR_SerialReader *sr; sr = &reader->u.serialReader; ret = setProtocol(reader, reader->tagOpParams.protocol); if (TMR_SUCCESS != ret) { return ret; } if (TMR_TAG_PROTOCOL_GEN2 == reader->tagOpParams.protocol) { if (TMR_AUTH_TYPE_GEN2_PASSWORD != auth->type) { /* Auth type doesn't match tagop protocol */ return TMR_ERROR_INVALID; } return TMR_SR_cmdKillTag(reader, (uint16_t)(sr->commandTimeout), auth->u.gen2Password, filter); } else { return TMR_ERROR_UNIMPLEMENTED; } } TMR_Status TMR_SR_gpoSet(struct TMR_Reader *reader, uint8_t count, const TMR_GpioPin state[]) { TMR_Status ret; int i; for (i = 0; i < count; i++) { ret = TMR_SR_cmdSetGPIO(reader, state[i].id, state[i].high); if (TMR_SUCCESS != ret) return ret; } return TMR_SUCCESS; } TMR_Status TMR_SR_gpiGet(struct TMR_Reader *reader, uint8_t *count, TMR_GpioPin state[]) { TMR_Status ret; TMR_GpioPin pinStates[4]; uint8_t i,j, numPins; numPins = numberof(pinStates); ret = TMR_SR_cmdGetGPIO(reader, &numPins, pinStates); if (TMR_SUCCESS != ret) { return ret; } if (numPins > *count) { numPins = *count; } *count = 0; j = 0; for (i = 0 ; i < numPins ; i++) { if (!pinStates[i].output) { /* If pin is input, only then copy to output */ state[j].id = pinStates[i].id; state[j].high = pinStates[i].high; state[j].output = pinStates[i].output; (*count)++; j ++; } } return TMR_SUCCESS; } #ifdef TMR_ENABLE_STDIO TMR_Status TMR_SR_firmwareLoad(struct TMR_Reader *reader, void *cookie, TMR_FirmwareDataProvider provider) { static const uint8_t magic[] = { 0x54, 0x4D, 0x2D, 0x53, 0x50, 0x61, 0x69, 0x6B, 0x00, 0x00, 0x00, 0x02 }; TMR_Status ret; uint8_t buf[256]; uint16_t packetLen, packetRemaining, size, offset; uint32_t len, rate, address, remaining; TMR_SR_SerialReader *sr; TMR_SR_SerialTransport *transport; sr = &reader->u.serialReader; transport = &sr->transport; remaining = numberof(magic) + 4; offset = 0; while (remaining > 0) { size = (uint16_t)remaining; if (false == provider(cookie, &size, buf + offset)) { return TMR_ERROR_FIRMWARE_FORMAT; } remaining -= size; offset += size; } if (0 != memcmp(buf, magic, numberof(magic))) { return TMR_ERROR_FIRMWARE_FORMAT; } len = GETU32AT(buf, 12); /* @todo get any params we want to reset */ /* * 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); /* Bootloader doesn't support wakeup preambles */ sr->supportsPreamble = false; /* Bootloader doesn't support high speed operation */ rate = sr->baudRate; if (rate > 115200) { rate = 115200; } 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, rate); if (TMR_SUCCESS != ret) { return ret; } ret = transport->setBaudRate(transport, rate); if (TMR_SUCCESS != ret) { return ret; } } ret = TMR_SR_cmdEraseFlash(reader, 2, 0x08959121); if (TMR_SUCCESS != ret) { return ret; } address = 0; remaining = len; while (remaining > 0) { packetLen = 240; if (packetLen > remaining) { packetLen = (uint16_t)remaining; } offset = 0; packetRemaining = packetLen; while (packetRemaining > 0) { size = packetRemaining; if (false == provider(cookie, &size, buf + offset)) { return TMR_ERROR_FIRMWARE_FORMAT; } packetRemaining -= size; offset += size; } ret = TMR_SR_cmdWriteFlashSector(reader, 2, address, 0x02254410,(uint8_t) packetLen, buf, 0); if (TMR_SUCCESS != ret) { return ret; } address += packetLen; remaining -= packetLen; } ret = TMR_SR_boot(reader, rate); if(ret != TMR_SUCCESS) { if(ret == TMR_ERROR_AUTOREAD_ENABLED) { ret = TMR_ERROR_FIRMWARE_UPDATE_ON_AUTOREAD; return ret; } } return ret; } #endif static TMR_Status getHardwareInfo(struct TMR_Reader *reader, void *value) { //TMR_Status ret; //uint8_t buf[127]; char tmp[255]; //uint8_t count; TMR_SR_VersionInfo *info; info = &reader->u.serialReader.versionInfo; TMR_hexDottedQuad(info->hardware, tmp); /** * Commented below code to fix the Bug#2117 */ /* tmp[11] = '-'; count = 127; ret = TMR_SR_cmdGetHardwareVersion(reader, 0, 0, &count, buf); if (TMR_SUCCESS != ret) { count = 0; tmp[11] = '\0'; } TMR_bytesToHex(buf, count, tmp + 12); TMR_stringCopy(value, tmp, 12 + 2*count);*/ TMR_stringCopy(value, tmp, (int)strlen(tmp)); return TMR_SUCCESS; } static TMR_Status getSerialNumber(struct TMR_Reader *reader, void *value) { /* See http://trac/swtree/changeset/6498 for previous implementation */ TMR_Status ret; uint8_t buf[127]; uint8_t count; char tmp[127]; int tmplen; count = 127; tmplen = 0; ret = TMR_SR_cmdGetHardwareVersion(reader, 0, 0x40, &count, buf); if (TMR_SUCCESS != ret) { count = 0; } else { int idx; uint8_t len; idx = 3; len = buf[idx++]; if (len > (count-3)) { ret = TMR_ERROR_UNIMPLEMENTED; } else { for (tmplen=0; tmplenvalue[0] = '\0'; return TMR_SUCCESS; } TMR_stringCopy(value, tmp, tmplen); return ret; } /* Abuse the structure layout of TMR_SR_PortPowerAndSettlingTime a bit * so that this can be one function instead of three only slightly * different pieces of code. Since all three per-port values are * represented as uint16_t, take an additional 'offset' parameter that * gives the pointer distance from the first element to the element * (readPower, writePower, settlingTime) that we actually want to set. */ static TMR_Status setPortValues(struct TMR_Reader *reader, const TMR_PortValueList *list, int offset) { TMR_Status ret; TMR_SR_PortPowerAndSettlingTime ports[TMR_SR_MAX_ANTENNA_PORTS]; uint8_t count; uint16_t i, j; count = numberof(ports); ret = TMR_SR_cmdGetAntennaPortPowersAndSettlingTime(reader, &count, ports); if (TMR_SUCCESS != ret) { return ret; } /* If a value is left out, 0 is assumed */ /*for (j = 0; j < count; j++) { *(&ports[j].readPower + offset) = 0; }*/ /* * For each settling time in the user's list, try to find an * existing entry in the list returned from the reader. */ for (i = 0; i < list->len; i++) { for (j = 0 ; j < count ; j++) { if (list->list[i].port == ports[j].port) { break; } } if (j == count) { if (count == TMR_SR_MAX_ANTENNA_PORTS) { return TMR_ERROR_TOO_BIG; } ports[j].port = list->list[i].port; ports[j].readPower = 0; ports[j].writePower = 0; ports[j].settlingTime = 0; count++; } if (list->list[i].value > 32767 || list->list[i].value < -32768) { return TMR_ERROR_ILLEGAL_VALUE; } *(&ports[j].readPower + offset) = (int16_t)(list->list[i].value); } return TMR_SR_cmdSetAntennaPortPowersAndSettlingTime(reader, count, ports); } /* See comment before setPortValues() for the meaning of offset */ static TMR_Status getPortValues(struct TMR_Reader *reader, TMR_PortValueList *list, int offset) { TMR_Status ret; TMR_SR_PortPowerAndSettlingTime ports[TMR_SR_MAX_ANTENNA_PORTS]; uint8_t count; uint16_t i, j; count = numberof(ports); ret = TMR_SR_cmdGetAntennaPortPowersAndSettlingTime(reader, &count, ports); if (TMR_SUCCESS != ret) { return ret; } for (i = 0, j = 0; i < count; i++) { if ((0 == *(&ports[i].readPower + offset) && ((TMR_SR_MODEL_MICRO != 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]) || (TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0])) && (-32768 == *(&ports[i].readPower + offset)))) { continue; } if (j < list->max) { list->list[j].port = ports[i].port; list->list[j].value = (int32_t)*(&ports[i].readPower + offset); } j++; } list->len = (uint8_t)j; return TMR_SUCCESS; } static TMR_Status TMR_SR_paramSet(struct TMR_Reader *reader, TMR_Param key, const void *value) { TMR_Status ret; TMR_SR_Configuration readerkey; TMR_SR_ProtocolConfiguration protokey; TMR_SR_SerialReader *sr; TMR_SR_SerialTransport *transport; ret = TMR_SUCCESS; sr = &reader->u.serialReader; readerkey = TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE; protokey.protocol = TMR_TAG_PROTOCOL_GEN2; if (0 == BITGET(sr->paramConfirmed, key)) { TMR_paramProbe(reader, key); } if (BITGET(sr->paramConfirmed, key) && (0 == BITGET(sr->paramPresent, key))) { return TMR_ERROR_NOT_FOUND; } switch (key) { case TMR_PARAM_REGION_ID: sr->regionId = *(TMR_Region*)value; if (reader->connected) { ret = TMR_SR_cmdSetRegion(reader, sr->regionId); } break; case TMR_PARAM_URI: case TMR_PARAM_PRODUCT_GROUP_ID: case TMR_PARAM_PRODUCT_GROUP: case TMR_PARAM_PRODUCT_ID: case TMR_PARAM_TAGREADATA_TAGOPSUCCESSCOUNT: case TMR_PARAM_TAGREADATA_TAGOPFAILURECOUNT: { ret = TMR_ERROR_READONLY; break; } case TMR_PARAM_STATUS_ENABLE_ANTENNAREPORT: { *(bool *)value ? (reader->streamStats |= TMR_SR_STATUS_ANTENNA) : (reader->streamStats &= ~TMR_SR_STATUS_ANTENNA) ; break; } case TMR_PARAM_STATUS_ENABLE_FREQUENCYREPORT: { *(bool *)value ? (reader->streamStats |= TMR_SR_STATUS_FREQUENCY) : (reader->streamStats &= ~TMR_SR_STATUS_FREQUENCY) ; break; } case TMR_PARAM_STATUS_ENABLE_TEMPERATUREREPORT: { *(bool *)value ? (reader->streamStats |= TMR_SR_STATUS_TEMPERATURE) : (reader->streamStats &= ~TMR_SR_STATUS_TEMPERATURE) ; break; } case TMR_PARAM_BAUDRATE: { uint32_t rate; transport = &sr->transport; rate = *(uint32_t *)value; if (reader->connected) { 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, rate); if (TMR_SUCCESS != ret) { break; } sr->baudRate = rate; transport->setBaudRate(transport, sr->baudRate); } } else { sr->baudRate = rate; } break; } case TMR_PARAM_PROBEBAUDRATES: { const TMR_uint32List *u32List; uint8_t i; u32List = value; if (u32List->len > sr->probeBaudRates.max) { ret = TMR_ERROR_TOO_BIG; break; } for(i = 0; i < u32List->len; i++) { sr->probeBaudRates.list[i] = u32List->list[i]; } sr->probeBaudRates.len = u32List->len; break; } case TMR_PARAM_COMMANDTIMEOUT: { uint32_t val = *(uint32_t*)value; if (((uint32_t)1<<31) & val) { ret = TMR_ERROR_ILLEGAL_VALUE; } else { sr->commandTimeout = *(uint32_t *)value; } } break; case TMR_PARAM_TRANSPORTTIMEOUT: { uint32_t val = *(uint32_t*)value; if (((uint32_t)1<<31) & val) { ret = TMR_ERROR_ILLEGAL_VALUE; } else { /** * In case user specified the timeout value for connect * Enable the usrTimoutEnable option */ sr->transportTimeout = *(uint32_t *)value; sr->usrTimeoutEnable = true; } } break; case TMR_PARAM_RADIO_ENABLEPOWERSAVE: readerkey = TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE; break; case TMR_PARAM_RADIO_ENABLESJC: readerkey = TMR_SR_CONFIGURATION_SELF_JAMMER_CANCELLATION; break; case TMR_PARAM_EXTENDEDEPC: readerkey = TMR_SR_CONFIGURATION_EXTENDED_EPC; break; case TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL: if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0])) { ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_UNIQUE_BY_PROTOCOL, value); } else { ret = TMR_ERROR_NOT_FOUND; } break; case TMR_PARAM_TAGREADDATA_READFILTERTIMEOUT: if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0])) { int32_t timeout = (TMR_DEFAULT_READ_FILTER_TIMEOUT == *(int32_t *)value) ? 0 : *(int32_t *)value; ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_READ_FILTER_TIMEOUT, &timeout); if (TMR_SUCCESS == ret) { reader->u.serialReader.readFilterTimeout = timeout; } } else { ret = TMR_ERROR_NOT_FOUND; } break; case TMR_PARAM_TAGREADDATA_ENABLEREADFILTER: if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) ||(TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0])) { ret = TMR_SR_cmdSetReaderConfiguration(reader, TMR_SR_CONFIGURATION_ENABLE_READ_FILTER, value); if (TMR_SUCCESS == ret) { reader->u.serialReader.enableReadFiltering = *(bool *)value; } } else { ret = TMR_ERROR_READONLY; } break; case TMR_PARAM_RADIO_READPOWER: ret = TMR_SR_cmdSetReadTxPower(reader, *(int32_t *)value); break; case TMR_PARAM_RADIO_WRITEPOWER: ret = TMR_SR_cmdSetWriteTxPower(reader, *(int32_t *)value); break; case TMR_PARAM_RADIO_PORTREADPOWERLIST: ret = setPortValues(reader, value, 0); break; case TMR_PARAM_RADIO_PORTWRITEPOWERLIST: ret = setPortValues(reader, value, 1); break; case TMR_PARAM_ANTENNA_SETTLINGTIMELIST: ret = setPortValues(reader, value, 2); break; case TMR_PARAM_ANTENNA_CHECKPORT: readerkey = TMR_SR_CONFIGURATION_SAFETY_ANTENNA_CHECK; break; case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI: readerkey = TMR_SR_CONFIGURATION_RECORD_HIGHEST_RSSI; break; case TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM: readerkey = TMR_SR_CONFIGURATION_RSSI_IN_DBM; break; case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA: readerkey = TMR_SR_CONFIGURATION_UNIQUE_BY_ANTENNA; break; case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA: readerkey = TMR_SR_CONFIGURATION_UNIQUE_BY_DATA; break; case TMR_PARAM_ANTENNA_PORTSWITCHGPOS: { const TMR_uint8List *u8list; uint16_t i; u8list = value; reader->portmask = 0; for (i = 0 ; i < u8list->len && i < u8list->max ; i++) { reader->portmask |= 1 << (u8list->list[i] - 1); } ret = TMR_SR_cmdSetReaderConfiguration( reader, TMR_SR_CONFIGURATION_ANTENNA_CONTROL_GPIO, &reader->portmask); if (TMR_SUCCESS != ret) { break; } ret = initTxRxMapFromPorts(reader); break; } case TMR_PARAM_TRIGGER_READ_GPI: { uint8_t portmask; const TMR_uint8List *u8list; uint16_t i; u8list = value; portmask = 0; for (i = 0 ; i < u8list->len && i < u8list->max ; i++) { portmask |= 1 << (u8list->list[i] - 1); } ret = TMR_SR_cmdSetReaderConfiguration( reader, TMR_SR_CONFIGURATION_TRIGGER_READ_GPIO, &portmask); break; } case TMR_PARAM_ANTENNA_TXRXMAP: { const TMR_AntennaMapList *map; TMR_AntennaMapList *mymap; uint8_t len; uint16_t i, j; map = value; mymap = sr->txRxMap; if (map->len > mymap->max) { ret = TMR_ERROR_TOO_BIG; break; } len = 0; for (i = 0 ; i < map->len ; i++) { if (!HASPORT(sr->portMask, map->list[i].txPort) || !HASPORT(sr->portMask, map->list[i].rxPort)) { return TMR_ERROR_NO_ANTENNA; } /* Error check for txrxmap */ for (j = i+1; j < map->len; j++) { if (map->list[i].antenna == map->list[j].antenna) { return TMR_ERROR_INVALID_ANTENNA_CONFIG; } } len = i+1; } for (i = 0; i < len; i ++) { mymap->list[i] = map->list[i]; } mymap->len = len; break; } case TMR_PARAM_REGION_HOPTABLE: { const TMR_uint32List *u32list; u32list = value; ret = TMR_SR_cmdSetFrequencyHopTable(reader, (uint8_t)u32list->len, u32list->list); break; } case TMR_PARAM_REGION_HOPTIME: ret = TMR_SR_cmdSetFrequencyHopTime(reader, *(uint32_t *)value); break; case TMR_PARAM_REGION_LBT_ENABLE: { uint32_t hopTable[64]; uint8_t count; count = numberof(hopTable); ret = TMR_SR_cmdGetFrequencyHopTable(reader, &count, hopTable); if (TMR_SUCCESS != ret) { break; } ret = TMR_SR_cmdSetRegionLbt(reader, sr->regionId, *(bool *)value); if (TMR_SUCCESS != ret) { break; } ret = TMR_SR_cmdSetFrequencyHopTable(reader, count, hopTable); break; } case TMR_PARAM_TAGOP_ANTENNA: { uint16_t i; TMR_AntennaMapList *map; uint8_t antenna; uint8_t txPort, rxPort; map = sr->txRxMap; antenna = *(uint8_t *)value; txPort = rxPort = 0; for (i = 0; i < map->len && i < map->max; i++) { if (map->list[i].antenna == antenna) { txPort = map->list[i].txPort; rxPort = map->list[i].rxPort; reader->tagOpParams.antenna = antenna; break; } } if (txPort == 0) { ret = TMR_ERROR_NO_ANTENNA; } else { ret = TMR_SR_cmdSetTxRxPorts(reader, txPort, rxPort); } break; } case TMR_PARAM_TAGOP_PROTOCOL: if (0 == ((1 << (*(TMR_TagProtocol *)value - 1)) & sr->versionInfo.protocols)) { ret = TMR_ERROR_UNSUPPORTED; } else { reader->tagOpParams.protocol = *(TMR_TagProtocol *)value; if (reader->connected) { ret = setProtocol(reader, reader->tagOpParams.protocol); if (TMR_SUCCESS == ret) { reader->u.serialReader.currentProtocol = reader->tagOpParams.protocol; } } } break; case TMR_PARAM_READ_PLAN: { const TMR_ReadPlan *plan; TMR_ReadPlan tmpPlan; plan = value; tmpPlan = *plan; ret = validateReadPlan(reader, &tmpPlan, sr->txRxMap, sr->versionInfo.protocols); if (TMR_SUCCESS != ret) { return ret; } *reader->readParams.readPlan = tmpPlan; break; } case TMR_PARAM_GPIO_INPUTLIST: case TMR_PARAM_GPIO_OUTPUTLIST: if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0])) { const TMR_uint8List *u8list; int bit, i, newDirections, pin; u8list = value; if (key == TMR_PARAM_GPIO_OUTPUTLIST) { newDirections = 0; } else { newDirections = 0x1e; } for (i = 0 ; i < u8list->len && i < u8list->max ; i++) { if (key == TMR_PARAM_GPIO_OUTPUTLIST) { newDirections |= (1 << u8list->list[i]); } else { newDirections &= ~(1 << u8list->list[i]); } } for (pin = 0 ; pin < u8list->len ; pin++) { bit = 1 << (u8list->list[pin]); ret = TMR_SR_cmdSetGPIODirection(reader, u8list->list[pin], (newDirections & bit) != 0); if (TMR_SUCCESS != ret) { return ret; } } break; } case TMR_PARAM_RADIO_POWERMAX: case TMR_PARAM_RADIO_POWERMIN: case TMR_PARAM_REGION_SUPPORTEDREGIONS: case TMR_PARAM_ANTENNA_PORTLIST: case TMR_PARAM_ANTENNA_CONNECTEDPORTLIST: case TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS: case TMR_PARAM_RADIO_TEMPERATURE: case TMR_PARAM_VERSION_HARDWARE: case TMR_PARAM_VERSION_MODEL: case TMR_PARAM_VERSION_SOFTWARE: case TMR_PARAM_ANTENNA_RETURNLOSS: case TMR_PARAM_GEN2_PROTOCOLEXTENSION: ret = TMR_ERROR_READONLY; break; case TMR_PARAM_POWERMODE: if (reader->connected) { ret = TMR_SR_cmdSetPowerMode(reader, *(TMR_SR_PowerMode *)value); if (TMR_SUCCESS == ret) { sr->powerMode = *(TMR_SR_PowerMode *)value; } } else { sr->powerMode = *(TMR_SR_PowerMode *)value; } break; case TMR_PARAM_USERMODE: ret = TMR_SR_cmdSetUserMode(reader, *(TMR_SR_UserMode *)value); break; case TMR_PARAM_GEN2_Q: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_Q; break; case TMR_PARAM_GEN2_TAGENCODING: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_TAGENCODING; break; case TMR_PARAM_GEN2_SESSION: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_SESSION; break; case TMR_PARAM_GEN2_TARGET: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_TARGET; break; case TMR_PARAM_GEN2_BLF: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_LINKFREQUENCY; break; case TMR_PARAM_GEN2_TARI: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_TARI; break; case TMR_PARAM_GEN2_WRITEMODE: sr->writeMode = *(TMR_GEN2_WriteMode *)value; break; case TMR_PARAM_GEN2_BAP: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_BAP; break; #ifdef TMR_ENABLE_ISO180006B case TMR_PARAM_ISO180006B_BLF: protokey.protocol = TMR_TAG_PROTOCOL_ISO180006B; protokey.u.iso180006b = TMR_SR_ISO180006B_CONFIGURATION_LINKFREQUENCY; break; case TMR_PARAM_ISO180006B_MODULATION_DEPTH: { protokey.protocol = TMR_TAG_PROTOCOL_ISO180006B; protokey.u.iso180006b = TMR_SR_ISO180006B_CONFIGURATION_MODULATION_DEPTH; break; } case TMR_PARAM_ISO180006B_DELIMITER: { protokey.protocol = TMR_TAG_PROTOCOL_ISO180006B; protokey.u.iso180006b = TMR_SR_ISO180006B_CONFIGURATION_DELIMITER; break; } #endif /* TMR_ENABLE_ISO180006B */ case TMR_PARAM_GEN2_ACCESSPASSWORD: sr->gen2AccessPassword = *(TMR_GEN2_Password *)value; break; case TMR_PARAM_LICENSE_KEY: { uint32_t supportedProtocols; TMR_uint8List *license = (TMR_uint8List *)value; ret = TMR_SR_cmdSetProtocolLicenseKey(reader, TMR_SR_SET_LICENSE_KEY, license->list, license->len, &supportedProtocols); } break; case TMR_PARAM_USER_CONFIG: { TMR_SR_UserConfigOp *config = (TMR_SR_UserConfigOp *)value; switch(config->op) { case TMR_USERCONFIG_SAVE: /* Save the configuration section to flash */ ret = TMR_SR_cmdSetUserProfile(reader, TMR_USERCONFIG_SAVE, config->category, TMR_SR_CUSTOM_CONFIGURATION); break; case TMR_USERCONFIG_RESTORE: /* Restore the saved configuration section from flash */ ret = TMR_SR_cmdSetUserProfile(reader, TMR_USERCONFIG_RESTORE, config->category, TMR_SR_CUSTOM_CONFIGURATION); break; case TMR_USERCONFIG_CLEAR: /* Clear configuration section from flash, and restore default configuration section */ ret = TMR_SR_cmdSetUserProfile(reader, TMR_USERCONFIG_CLEAR, config->category, TMR_SR_CUSTOM_CONFIGURATION); break; case TMR_USERCONFIG_VERIFY: ret = TMR_SR_cmdSetUserProfile(reader, TMR_USERCONFIG_VERIFY, config->category, TMR_SR_CUSTOM_CONFIGURATION); break; case TMR_USERCONFIG_SAVE_WITH_READPLAN: /* Save the read plan configuration section to flash */ ret = TMR_SR_cmdSetUserProfile(reader, TMR_USERCONFIG_SAVE_WITH_READPLAN, config->category, TMR_SR_CUSTOM_CONFIGURATION); break; default: ret = TMR_ERROR_NOT_FOUND; } } break; case TMR_PARAM_READER_STATISTICS: /* Only RF On time statistic can be reset to 0 */ ret = TMR_SR_cmdResetReaderStatistics(reader, TMR_SR_READER_STATS_ALL); break; case TMR_PARAM_READER_STATS: { if ((NULL != reader->pSupportsResetStats) && (false == *(reader->pSupportsResetStats))) { /* Command not supported, pop up the error */ return TMR_ERROR_UNSUPPORTED; } /* Only RF On time statistic can be reset to 0 */ ret = TMR_SR_cmdResetReaderStats(reader, TMR_READER_STATS_FLAG_ALL); break; } case TMR_PARAM_READER_STATS_ENABLE: { if ((NULL != reader->pSupportsResetStats) && (false == *(reader->pSupportsResetStats))) { /* Command not supported, pop up the error */ return TMR_ERROR_UNSUPPORTED; } /* Store the statitics flags requested by the user */ reader->statsFlag = *(TMR_Reader_StatsFlag *)value; break; } case TMR_PARAM_READER_WRITE_REPLY_TIMEOUT: case TMR_PARAM_READER_WRITE_EARLY_EXIT: { TMR_SR_Gen2ReaderWriteTimeOut timeout; /* in case of timeout check for range */ switch (key) { case TMR_PARAM_READER_WRITE_REPLY_TIMEOUT: { if ( *(uint16_t *)value < 1000 || *(uint16_t *)value > 21000) return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE; break; } default: ; } /* Get the values before setting it */ ret = TMR_SR_cmdGetReaderWriteTimeOut(reader, protokey.protocol, &timeout); if (TMR_SUCCESS != ret) { break; } /* set the parameter asked by the user */ switch (key) { case TMR_PARAM_READER_WRITE_REPLY_TIMEOUT: { timeout.writetimeout = *(uint16_t *)value; break; } case TMR_PARAM_READER_WRITE_EARLY_EXIT: { timeout.earlyexit = !(*(bool *)value); break; } default: ret = TMR_ERROR_NOT_FOUND; } /* set the vakue */ ret = TMR_SR_cmdSetReaderWriteTimeOut (reader,protokey.protocol, &timeout); break; } case TMR_PARAM_METADATAFLAG: { if (*(TMR_TRD_MetadataFlag *)value & TMR_TRD_METADATA_FLAG_PROTOCOL) reader->userMetadataFlag = *(TMR_TRD_MetadataFlag *)value; else ret = TMR_ERROR_MSG_INVALID_PARAMETER_VALUE; break; } default: ret = TMR_ERROR_NOT_FOUND; } switch (key) { case TMR_PARAM_ANTENNA_CHECKPORT: case TMR_PARAM_RADIO_ENABLEPOWERSAVE: case TMR_PARAM_RADIO_ENABLESJC: case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI: case TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM: case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA: case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA: ret = TMR_SR_cmdSetReaderConfiguration(reader, readerkey, value); break; case TMR_PARAM_EXTENDEDEPC: { if ((TMR_SR_MODEL_M6E == reader->u.serialReader.versionInfo.hardware[0])|| (TMR_SR_MODEL_MICRO == reader->u.serialReader.versionInfo.hardware[0])|| (TMR_SR_MODEL_M6E_NANO == reader->u.serialReader.versionInfo.hardware[0])|| (TMR_SR_MODEL_M6E_I == reader->u.serialReader.versionInfo.hardware[0])) { ret = TMR_ERROR_UNSUPPORTED; } else { ret = TMR_SR_cmdSetReaderConfiguration(reader, readerkey, value); if(TMR_SUCCESS == ret) { /* cache the extended epc setting */ reader->u.serialReader.extendedEPC = *(bool *)value; } } } break; case TMR_PARAM_GEN2_BAP: { TMR_GEN2_Bap *bap; bap = (TMR_GEN2_Bap *)value; if (NULL == (TMR_GEN2_Bap *)value) { /** It means user is disabling the bap support, make the flag down * and skip the command sending **/ sr->isBapEnabled = false; break; } else if ((-1 > bap->powerUpDelayUs) || (-1 > bap->freqHopOfftimeUs)) { /* * Invalid values for BAP parameters, * Accepts only positive values or -1 for NULL */ return TMR_ERROR_ILLEGAL_VALUE; } else if ((-1 == bap->powerUpDelayUs) && (-1 == bap->freqHopOfftimeUs)) { /** * Here -1 signifies NULL. API should skips the parameter and does not sent the matching * command to the reader. Let reader use its own default **/ sr->isBapEnabled = true; break; } else { /* * do a paramGet of BAP parameters. This serves two purposes. * 1. API knows wheather module supports the BAP options or not. * 2. API can assign default values to the fields, are not set by the user. */ TMR_GEN2_Bap getBapParams; ret = TMR_SR_cmdGetProtocolConfiguration(reader, protokey.protocol, protokey, &getBapParams); if (TMR_SUCCESS != ret) { /* throw the error and come out from the loop */ break; } else { /* * Modify the get BAP structure if either of the set BAP params are -1 */ sr->isBapEnabled = true; if (-1 == bap->powerUpDelayUs) { bap->powerUpDelayUs = getBapParams.powerUpDelayUs; } if (-1 == bap->freqHopOfftimeUs) { bap->freqHopOfftimeUs = getBapParams.freqHopOfftimeUs; } } } // No break -- fall through to regular Gen2 param handler } case TMR_PARAM_GEN2_Q: case TMR_PARAM_GEN2_TAGENCODING: case TMR_PARAM_GEN2_SESSION: case TMR_PARAM_GEN2_TARGET: case TMR_PARAM_GEN2_BLF: case TMR_PARAM_GEN2_TARI: #ifdef TMR_ENABLE_ISO180006B case TMR_PARAM_ISO180006B_BLF: case TMR_PARAM_ISO180006B_MODULATION_DEPTH: case TMR_PARAM_ISO180006B_DELIMITER: #endif /* TMR_ENABLE_ISO180006B */ ret = TMR_SR_cmdSetProtocolConfiguration(reader, protokey.protocol, protokey, value); break; default: ; } return ret; } static TMR_Status TMR_SR_paramGet(struct TMR_Reader *reader, TMR_Param key, void *value) { TMR_Status ret; TMR_SR_Configuration readerkey; TMR_SR_ProtocolConfiguration protokey; TMR_SR_SerialReader *sr; ret = TMR_SUCCESS; sr = &reader->u.serialReader; readerkey = TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE; protokey.protocol = TMR_TAG_PROTOCOL_GEN2; if (BITGET(sr->paramConfirmed, key) && 0 == BITGET(sr->paramPresent, key)) { return TMR_ERROR_NOT_FOUND; } switch (key) { case TMR_PARAM_BAUDRATE: *(uint32_t *)value = sr->baudRate; break; case TMR_PARAM_PROBEBAUDRATES: { TMR_uint32List *uint32List; uint8_t i; uint32List = value; if (sr->probeBaudRates.len > uint32List->max) { sr->probeBaudRates.len = uint32List->max; } if (sr->probeBaudRates.len) { for(i = 0; i < sr->probeBaudRates.len; i++) { uint32List->list[i] = sr->probeBaudRates.list[i]; } uint32List->len = sr->probeBaudRates.len; } else { //list is empty } break; } case TMR_PARAM_URI: if (NULL != value) { TMR_stringCopy((TMR_String *)value, reader->uri, (int)strlen(reader->uri)); } else { ret = TMR_ERROR_ILLEGAL_VALUE; } break; case TMR_PARAM_COMMANDTIMEOUT: *(uint32_t *)value = sr->commandTimeout; break; case TMR_PARAM_TRANSPORTTIMEOUT: *(uint32_t *)value = sr->transportTimeout; break; case TMR_PARAM_REGION_ID: { if ((TMR_REGION_NONE == sr->regionId) && (reader->connected)) { ret = TMR_SR_cmdGetRegion(reader, &sr->regionId); } *(TMR_Region *)value = sr->regionId; } break; case TMR_PARAM_RADIO_ENABLEPOWERSAVE: readerkey = TMR_SR_CONFIGURATION_TRANSMIT_POWER_SAVE; break; case TMR_PARAM_RADIO_ENABLESJC: readerkey = TMR_SR_CONFIGURATION_SELF_JAMMER_CANCELLATION; break; case TMR_PARAM_TAGREADDATA_READFILTERTIMEOUT: if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0])) { *(int32_t *)value = sr->readFilterTimeout; } else { ret = TMR_ERROR_NOT_FOUND; } break; case TMR_PARAM_TAGREADDATA_ENABLEREADFILTER: *(bool *)value = sr->enableReadFiltering; break; case TMR_PARAM_EXTENDEDEPC: readerkey = TMR_SR_CONFIGURATION_EXTENDED_EPC; break; case TMR_PARAM_RADIO_POWERMAX: { TMR_SR_PowerWithLimits power; ret = TMR_SR_cmdGetReadTxPowerWithLimits(reader, &power); if (TMR_SUCCESS != ret) { break; } *(int16_t *)value = power.maxPower; break; } case TMR_PARAM_RADIO_POWERMIN: { TMR_SR_PowerWithLimits power; ret = TMR_SR_cmdGetReadTxPowerWithLimits(reader, &power); if (TMR_SUCCESS != ret) break; *(int16_t *)value = power.minPower; break; } case TMR_PARAM_RADIO_READPOWER: ret = TMR_SR_cmdGetReadTxPower(reader, (int32_t *)value); break; case TMR_PARAM_RADIO_WRITEPOWER: ret = TMR_SR_cmdGetWriteTxPower(reader, (int32_t *)value); break; case TMR_PARAM_ANTENNA_CHECKPORT: readerkey = TMR_SR_CONFIGURATION_SAFETY_ANTENNA_CHECK; break; case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI: readerkey = TMR_SR_CONFIGURATION_RECORD_HIGHEST_RSSI; break; case TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM: readerkey = TMR_SR_CONFIGURATION_RSSI_IN_DBM; break; case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA: readerkey = TMR_SR_CONFIGURATION_UNIQUE_BY_ANTENNA; break; case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA: readerkey = TMR_SR_CONFIGURATION_UNIQUE_BY_DATA; break; case TMR_PARAM_TAGREADDATA_UNIQUEBYPROTOCOL: if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0])) { ret = TMR_SR_cmdGetReaderConfiguration(reader, TMR_SR_CONFIGURATION_UNIQUE_BY_PROTOCOL, value); } else { ret = TMR_ERROR_NOT_FOUND; } break; case TMR_PARAM_PRODUCT_GROUP_ID: readerkey = TMR_SR_CONFIGURATION_PRODUCT_GROUP_ID; break; case TMR_PARAM_PRODUCT_ID: readerkey = TMR_SR_CONFIGURATION_PRODUCT_ID; break; case TMR_PARAM_STATUS_ENABLE_ANTENNAREPORT: *(bool *)value = (reader->streamStats & TMR_SR_STATUS_ANTENNA) ? true : false; break; case TMR_PARAM_STATUS_ENABLE_FREQUENCYREPORT: *(bool *)value = (reader->streamStats & TMR_SR_STATUS_FREQUENCY) ? true : false; break; case TMR_PARAM_STATUS_ENABLE_TEMPERATUREREPORT: *(bool *)value = (reader->streamStats & TMR_SR_STATUS_TEMPERATURE) ? true : false; break; case TMR_PARAM_ANTENNA_PORTSWITCHGPOS: { TMR_uint8List *u8list; u8list = value; ret = TMR_SR_cmdGetReaderConfiguration( reader, TMR_SR_CONFIGURATION_ANTENNA_CONTROL_GPIO, &reader->portmask); if (TMR_SUCCESS != ret) { break; } u8list->len = 0; if (reader->portmask & 1) { LISTAPPEND(u8list, 1); } if (reader->portmask & 2) { LISTAPPEND(u8list, 2); } if (reader->portmask & 3) { LISTAPPEND(u8list, 3); } break; } case TMR_PARAM_TRIGGER_READ_GPI: { uint8_t portmask; TMR_uint8List *u8list; u8list = value; ret = TMR_SR_cmdGetReaderConfiguration( reader, TMR_SR_CONFIGURATION_TRIGGER_READ_GPIO, &portmask); if (TMR_SUCCESS != ret) { break; } u8list->len = 0; if (portmask & 1) { LISTAPPEND(u8list, 1); } if (portmask & 2) { LISTAPPEND(u8list, 2); } break; } case TMR_PARAM_ANTENNA_SETTLINGTIMELIST: ret = getPortValues(reader, value, 2); break; case TMR_PARAM_RADIO_PORTREADPOWERLIST: ret = getPortValues(reader, value, 0); break; case TMR_PARAM_RADIO_PORTWRITEPOWERLIST: ret = getPortValues(reader, value, 1); break; case TMR_PARAM_ANTENNA_RETURNLOSS: ret = TMR_SR_cmdGetAntennaReturnLoss(reader, value); break; case TMR_PARAM_GPIO_INPUTLIST: case TMR_PARAM_GPIO_OUTPUTLIST: { TMR_uint8List *u8list; u8list = value; u8list->len = 0; if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0])) { int pin, wantout; bool out; TMR_GpioPin pinStates[16]; uint8_t numPins; sr->gpioDirections = -1; numPins = numberof(pinStates); ret = TMR_SR_cmdGetGPIO(reader, &numPins, pinStates); if (TMR_SUCCESS != ret) { return ret; } wantout = (key == TMR_PARAM_GPIO_OUTPUTLIST) ? 1 : 0; if (-1 == sr->gpioDirections) { /* Cache the current state */ sr->gpioDirections = 0; for (pin = 1; pin <= numPins ; pin++) { ret = TMR_SR_cmdGetGPIODirection(reader, pin, &out); if (TMR_SUCCESS != ret) { return ret; } if (out) { sr->gpioDirections |= 1 << pin; } } } for (pin = 1; pin <= numPins ; pin++) { if (wantout == ((sr->gpioDirections >> pin) & 1)) { LISTAPPEND(u8list, pin); } } } else { LISTAPPEND(u8list, 1); LISTAPPEND(u8list, 2); } break; } case TMR_PARAM_ANTENNA_PORTLIST: { uint8_t i; TMR_uint8List *u8list; u8list = value; u8list->len = 0; for (i = 0; i < reader->u.serialReader.txRxMap->len; i++) { LISTAPPEND(u8list, reader->u.serialReader.txRxMap->list[i].antenna); } break; } case TMR_PARAM_ANTENNA_CONNECTEDPORTLIST: { // Store detected ports in array for quick lookup bool detected[TMR_SR_MAX_ANTENNA_PORTS+1]; uint8_t i; TMR_uint8List *u8list; for (i=0; ilen = 0; for (i=0; iu.serialReader.txRxMap->len; i++) { int ant = reader->u.serialReader.txRxMap->list[i].antenna; int tx = reader->u.serialReader.txRxMap->list[i].txPort; int rx = reader->u.serialReader.txRxMap->list[i].rxPort; if (detected[tx] && detected[rx]) { LISTAPPEND(u8list, ant); } } break; } case TMR_PARAM_ANTENNA_TXRXMAP: { TMR_AntennaMapList *map, *mymap; uint16_t i; map = value; mymap = sr->txRxMap; for (i = 0 ; i < mymap->len && i < map->max ; i++) map->list[i] = mymap->list[i]; map->len = mymap->len; break; } case TMR_PARAM_REGION_HOPTABLE: { TMR_uint32List *u32List; uint8_t count; u32List = value; count = (uint8_t)u32List->max; ret = TMR_SR_cmdGetFrequencyHopTable(reader,&count, u32List->list); if (TMR_SUCCESS != ret) { break; } u32List->len = count; break; } case TMR_PARAM_REGION_HOPTIME: ret = TMR_SR_cmdGetFrequencyHopTime(reader, value); break; case TMR_PARAM_REGION_LBT_ENABLE: ret = TMR_SR_cmdGetRegionConfiguration(reader, TMR_SR_REGION_CONFIGURATION_LBT_ENABLED, value); if (TMR_SUCCESS != ret && TMR_ERROR_IS_CODE(ret)) { *(bool *)value = false; ret = TMR_SUCCESS; } break; case TMR_PARAM_TAGOP_ANTENNA: *(uint8_t *)value = reader->tagOpParams.antenna; break; case TMR_PARAM_TAGOP_PROTOCOL: *(TMR_TagProtocol *)value = reader->tagOpParams.protocol; break; case TMR_PARAM_POWERMODE: if (reader->connected) { TMR_SR_PowerMode pm; ret = TMR_SR_cmdGetPowerMode(reader, &pm); if (TMR_SUCCESS == ret) { sr->powerMode = pm; } } *(TMR_SR_PowerMode*)value = sr->powerMode; break; case TMR_PARAM_USERMODE: ret = TMR_SR_cmdGetUserMode(reader, value); break; case TMR_PARAM_GEN2_Q: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_Q; break; case TMR_PARAM_GEN2_TAGENCODING: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_TAGENCODING; break; case TMR_PARAM_GEN2_SESSION: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_SESSION; break; case TMR_PARAM_GEN2_TARGET: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_TARGET; break; case TMR_PARAM_GEN2_BLF: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_LINKFREQUENCY; break; case TMR_PARAM_GEN2_TARI: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_TARI; break; case TMR_PARAM_GEN2_BAP: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_BAP; break; case TMR_PARAM_GEN2_WRITEMODE: *(TMR_GEN2_WriteMode *)value = sr->writeMode; break; case TMR_PARAM_GEN2_PROTOCOLEXTENSION: protokey.u.gen2 = TMR_SR_GEN2_CONFIGURATION_PROTCOLEXTENSION; break; #ifdef TMR_ENABLE_ISO180006B case TMR_PARAM_ISO180006B_BLF: protokey.protocol = TMR_TAG_PROTOCOL_ISO180006B; protokey.u.iso180006b = TMR_SR_ISO180006B_CONFIGURATION_LINKFREQUENCY; break; case TMR_PARAM_ISO180006B_MODULATION_DEPTH: { protokey.protocol = TMR_TAG_PROTOCOL_ISO180006B; protokey.u.iso180006b = TMR_SR_ISO180006B_CONFIGURATION_MODULATION_DEPTH; break; } case TMR_PARAM_ISO180006B_DELIMITER: { protokey.protocol = TMR_TAG_PROTOCOL_ISO180006B; protokey.u.iso180006b = TMR_SR_ISO180006B_CONFIGURATION_DELIMITER; break; } #endif /* TMR_ENABLE_ISO180006B */ case TMR_PARAM_GEN2_ACCESSPASSWORD: *(TMR_GEN2_Password *)value = sr->gen2AccessPassword; break; case TMR_PARAM_REGION_SUPPORTEDREGIONS: ret = TMR_SR_cmdGetAvailableRegions(reader, value); break; case TMR_PARAM_VERSION_SUPPORTEDPROTOCOLS: ret = TMR_SR_cmdGetAvailableProtocols(reader, value); break; case TMR_PARAM_RADIO_TEMPERATURE: ret = TMR_SR_cmdGetTemperature(reader, value); break; case TMR_PARAM_VERSION_HARDWARE: ret = getHardwareInfo(reader, value); break; case TMR_PARAM_VERSION_SERIAL: ret = getSerialNumber(reader, value); break; case TMR_PARAM_VERSION_MODEL: { const char *model = NULL; switch (sr->versionInfo.hardware[0]) { case TMR_SR_MODEL_M5E: model = "M5e"; break; case TMR_SR_MODEL_M5E_COMPACT: model = "M5e Compact"; break; case TMR_SR_MODEL_M5E_I: { /** * I - International . It has following Variants. **/ switch (sr->versionInfo.hardware[3]) { case TMR_SR_MODEL_M5E_I_REV_EU: model = "M5e EU"; break; case TMR_SR_MODEL_M5E_I_REV_NA: model = "M5e NA"; break; case TMR_SR_MODEL_M5E_I_REV_JP: model = "M5E JP"; break; case TMR_SR_MODEL_M5E_I_REV_PRC: model = "M5e PRC"; break; default: model = "Unknown"; break; } break; } case TMR_SR_MODEL_M4E: model = "M4e"; break; case TMR_SR_MODEL_M6E: model = "M6e"; break; case TMR_SR_MODEL_M6E_I: { /** * M6e I has following variants **/ switch (sr->versionInfo.hardware[3]) { case TMR_SR_MODEL_M6E_I_PRC: model = "M6e PRC"; break; case TMR_SR_MODEL_M6E_I_JIC: model = "M6e JIC"; break; default: model = "Unknown"; } } break; case TMR_SR_MODEL_MICRO: { /** * Micro has following variants. **/ switch (sr->versionInfo.hardware[3]) { case TMR_SR_MODEL_M6E_MICRO: model = "M6e Micro"; break; case TMR_SR_MODEL_M6E_MICRO_USB: model = "M6e Micro USB"; break; case TMR_SR_MODEL_M6E_MICRO_USB_PRO: model = "M6e Micro USBPro"; break; } } break; case TMR_SR_MODEL_M6E_NANO: model = "M6e Nano"; break; default: model = "Unknown"; } TMR_stringCopy(value, model, (int)strlen(model)); break; } case TMR_PARAM_VERSION_SOFTWARE: { char tmp[38]; TMR_SR_VersionInfo *info; info = &sr->versionInfo; TMR_hexDottedQuad(info->fwVersion, tmp); tmp[11] = '-'; TMR_hexDottedQuad(info->fwDate, tmp + 12); tmp[23] = '-'; tmp[24] = 'B'; tmp[25] = 'L'; TMR_hexDottedQuad(info->bootloader, tmp+26); TMR_stringCopy(value, tmp, 37); break; } case TMR_PARAM_LICENSE_KEY: ret = TMR_ERROR_UNSUPPORTED; break; case TMR_PARAM_USER_CONFIG: ret = TMR_ERROR_UNSUPPORTED; break; case TMR_PARAM_READER_STATS: { if ((NULL != reader->pSupportsResetStats) && (false == *(reader->pSupportsResetStats))) { /* Command not supported, pop up the error */ return TMR_ERROR_UNSUPPORTED; } /** * We should ask for the fields which are requested by the user, * if no fields are requested by the user, then fetch all fields. */ if (TMR_READER_STATS_FLAG_NONE == reader->statsFlag) { reader->statsFlag = TMR_READER_STATS_FLAG_ALL; } ret = TMR_SR_cmdGetReaderStats(reader, reader->statsFlag, value); break; } case TMR_PARAM_READER_STATS_ENABLE: { if ((NULL != reader->pSupportsResetStats) && (false == *(reader->pSupportsResetStats))) { /* Command not supported, pop up the error */ return TMR_ERROR_UNSUPPORTED; } *(TMR_Reader_StatsFlag *)value = reader->statsFlag; break; } case TMR_PARAM_READER_STATISTICS: ret = TMR_SR_cmdGetReaderStatistics(reader, TMR_SR_READER_STATS_ALL, value); break; case TMR_PARAM_PRODUCT_GROUP: { const char *group; TMR_SR_ProductGroupID id = (TMR_SR_ProductGroupID)sr->productId; switch (id) { case TMR_SR_PRODUCT_MODULE: case TMR_SR_PRODUCT_INVALID: group = "Embedded Reader"; break; case TMR_SR_PRODUCT_RUGGEDIZED_READER: group = "Ruggedized Reader"; break; case TMR_SR_PRODUCT_USB_READER: group = "USB Reader"; break; default: group = "Unknown"; break; } if (NULL != value) { TMR_stringCopy(value, group, (int)strlen(group)); } else { ret = TMR_ERROR_ILLEGAL_VALUE; } break; } case TMR_PARAM_TAGREADATA_TAGOPSUCCESSCOUNT: { *(uint16_t *)value = sr->tagopSuccessCount; break; } case TMR_PARAM_TAGREADATA_TAGOPFAILURECOUNT: { *(uint16_t *)value = sr->tagopFailureCount; break; } case TMR_PARAM_READER_WRITE_REPLY_TIMEOUT: case TMR_PARAM_READER_WRITE_EARLY_EXIT: { TMR_SR_Gen2ReaderWriteTimeOut timeout; ret = TMR_SR_cmdGetReaderWriteTimeOut(reader, protokey.protocol, &timeout); if (TMR_SUCCESS != ret) { break; } switch (key) { case TMR_PARAM_READER_WRITE_REPLY_TIMEOUT: { *(uint16_t *)value = (uint16_t)timeout.writetimeout; break; } case TMR_PARAM_READER_WRITE_EARLY_EXIT: { *(bool *)value = !((bool)timeout.earlyexit); break; } default: ret = TMR_ERROR_NOT_FOUND; } } break; case TMR_PARAM_METADATAFLAG: { *(TMR_TRD_MetadataFlag *)value = reader->userMetadataFlag; break; } default: ret = TMR_ERROR_NOT_FOUND; } switch (key) { case TMR_PARAM_ANTENNA_CHECKPORT: case TMR_PARAM_RADIO_ENABLEPOWERSAVE: case TMR_PARAM_RADIO_ENABLESJC: case TMR_PARAM_TAGREADDATA_RECORDHIGHESTRSSI: case TMR_PARAM_TAGREADDATA_REPORTRSSIINDBM: case TMR_PARAM_TAGREADDATA_UNIQUEBYANTENNA: case TMR_PARAM_TAGREADDATA_UNIQUEBYDATA: case TMR_PARAM_PRODUCT_GROUP_ID: case TMR_PARAM_PRODUCT_ID: ret = TMR_SR_cmdGetReaderConfiguration(reader, readerkey, value); break; case TMR_PARAM_EXTENDEDEPC: { if ((TMR_SR_MODEL_M6E == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_I == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_M6E_NANO == sr->versionInfo.hardware[0]) || (TMR_SR_MODEL_MICRO == sr->versionInfo.hardware[0])) { ret = TMR_ERROR_UNSUPPORTED; } else { ret = TMR_SR_cmdGetReaderConfiguration(reader, readerkey, value); } } break; case TMR_PARAM_GEN2_Q: case TMR_PARAM_GEN2_TAGENCODING: case TMR_PARAM_GEN2_SESSION: case TMR_PARAM_GEN2_TARGET: case TMR_PARAM_GEN2_BLF: case TMR_PARAM_GEN2_TARI: case TMR_PARAM_GEN2_BAP: case TMR_PARAM_GEN2_PROTOCOLEXTENSION: #ifdef TMR_ENABLE_ISO180006B case TMR_PARAM_ISO180006B_BLF: case TMR_PARAM_ISO180006B_MODULATION_DEPTH: case TMR_PARAM_ISO180006B_DELIMITER: #endif /* TMR_ENABLE_ISO180006B */ ret = TMR_SR_cmdGetProtocolConfiguration(reader, protokey.protocol, protokey, value); break; default: ; } if (0 == BITGET(sr->paramConfirmed, key)) { if ((TMR_SUCCESS == ret) || ret == TMR_ERROR_AUTOREAD_ENABLED ) { BITSET(sr->paramPresent, key); } BITSET(sr->paramConfirmed, key); } return ret; } TMR_Status TMR_SR_SerialReader_init(TMR_Reader *reader) { reader->readerType = TMR_READER_TYPE_SERIAL; #ifndef TMR_ENABLE_SERIAL_READER_ONLY reader->connect = TMR_SR_connect; reader->destroy = TMR_SR_destroy; reader->read = TMR_SR_read; reader->hasMoreTags = TMR_SR_hasMoreTags; reader->getNextTag = TMR_SR_getNextTag; reader->executeTagOp = TMR_SR_executeTagOp; reader->readTagMemWords = TMR_SR_readTagMemWords; reader->readTagMemBytes = TMR_SR_readTagMemBytes; reader->writeTagMemBytes = TMR_SR_writeTagMemBytes; reader->writeTagMemWords = TMR_SR_writeTagMemWords; reader->writeTag = TMR_SR_writeTag; reader->killTag = TMR_SR_killTag; reader->lockTag = TMR_SR_lockTag; reader->gpiGet = TMR_SR_gpiGet; reader->gpoSet = TMR_SR_gpoSet; #ifdef TMR_ENABLE_STDIO reader->firmwareLoad = TMR_SR_firmwareLoad; #endif reader->modifyFlash = TMR_SR_modifyFlash; reader->reboot = TMR_SR_reboot; #endif reader->cmdStopReading = TMR_SR_cmdStopReading; #ifdef TMR_ENABLE_BACKGROUND_READS reader->cmdAutonomousReading = TMR_SR_receiveAutonomousReading; #endif reader->paramSet = TMR_SR_paramSet; reader->paramGet = TMR_SR_paramGet; memset(reader->u.serialReader.paramConfirmed,0, sizeof(reader->u.serialReader.paramConfirmed)); memset(reader->u.serialReader.paramPresent,0, sizeof(reader->u.serialReader.paramPresent)); reader->u.serialReader.baudRate = 115200; reader->u.serialReader.currentProtocol = TMR_TAG_PROTOCOL_NONE; reader->u.serialReader.versionInfo.hardware[0] = TMR_SR_MODEL_UNKNOWN; reader->u.serialReader.supportsPreamble = false; reader->u.serialReader.extendedEPC = false; reader->u.serialReader.powerMode = TMR_SR_POWER_MODE_INVALID; reader->u.serialReader.transportTimeout = 5000; reader->u.serialReader.commandTimeout = 1000; reader->u.serialReader.regionId = TMR_REGION_NONE; reader->u.serialReader.tagsRemaining = 0; reader->u.serialReader.tagsRemainingInBuffer = 0; reader->u.serialReader.gen2AccessPassword = 0; reader->u.serialReader.oldQ.type = TMR_SR_GEN2_Q_INVALID; reader->u.serialReader.writeMode = TMR_GEN2_WORD_ONLY; reader->u.serialReader.tagopSuccessCount = 0; reader->u.serialReader.tagopFailureCount = 0; reader->u.serialReader.enableReadFiltering = true; reader->u.serialReader.readFilterTimeout = 0; reader->u.serialReader.usrTimeoutEnable = false; reader->u.serialReader.crcEnabled = true; reader->u.serialReader.transportType = TMR_SR_MSG_SOURCE_UNKNOWN; reader->u.serialReader.gen2AllMemoryBankEnabled = false; reader->u.serialReader.isBapEnabled = false; reader->u.serialReader.probeBaudRates.list = reader->u.serialReader.baudRates; reader->u.serialReader.probeBaudRates.max = TMR_MAX_PROBE_BAUDRATE_LENGTH; reader->u.serialReader.probeBaudRates.len = 0; reader->u.serialReader.enableAutonomousRead = false; reader->u.serialReader.isBasetimeUpdated = false; { //initialize the probe baud rate list with the supported baud rate values TMR_uint32List value; uint32_t rates[TMR_MAX_PROBE_BAUDRATE_LENGTH] ={9600, 115200, 921600, 19200, 38400, 57600,230400, 460800}; value.list = rates; value.len = value.max = 8; TMR_paramSet(reader, TMR_PARAM_PROBEBAUDRATES, &value); } return TMR_reader_init_internal(reader); } uint16_t TMR_SR_getConfigWord(TMR_Reader *reader, TMR_TagOp_GEN2_NXP_Untraceable op) { uint16_t configWord = 0x0000; uint16_t Mask; int Pos; if(op.epc == 1) { configWord |= 0x0001 << 14; } Mask = 0x1F; Pos = 9; configWord |= (uint16_t)((op.epcLength & Mask) << Pos); Mask = 0x03; Pos = 7; configWord |= (uint16_t)((op.tid & Mask) << Pos); if (op.userMemory == 1) { configWord |= 0x0001 << 6; } Mask = 0x03; Pos = 4; configWord |= (uint16_t)((op.range & Mask) << Pos); return configWord; } TMR_Status TMR_SR_executeTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop, TMR_TagFilter *filter, TMR_uint8List *data) { TMR_Status ret; TMR_SR_SerialReader *sr; sr = &reader->u.serialReader; switch (tagop->type) { case (TMR_TAGOP_GEN2_WRITETAG): { TMR_TagOp_GEN2_WriteTag op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.writeTag; return TMR_SR_cmdWriteGen2TagEpc(reader, filter, sr->gen2AccessPassword, (uint16_t)(sr->commandTimeout), op.epcptr->epcByteCount, op.epcptr->epc, false); } case (TMR_TAGOP_GEN2_KILL): { TMR_TagOp_GEN2_Kill op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.kill; return TMR_SR_cmdKillTag(reader, (uint16_t)(sr->commandTimeout), op.password, filter); } case (TMR_TAGOP_GEN2_LOCK): { TMR_TagOp_GEN2_Lock op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.lock; return TMR_SR_cmdGEN2LockTag(reader, (uint16_t)sr->commandTimeout, op.mask, op.action, op.accessPassword, filter); } case (TMR_TAGOP_GEN2_WRITEDATA): { TMR_TagOp_GEN2_WriteData op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.writeData; return TMR_SR_writeTagMemWords(reader, filter, op.bank, op.wordAddress, op.data.len, op.data.list); } case (TMR_TAGOP_GEN2_READDATA): { TMR_TagOp_GEN2_ReadData op; TMR_TagReadData read; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if (NULL != data) { read.data.len = 0; read.data.list = data->list; read.data.max = data->max; } else { read.data.list = NULL; } read.metadataFlags = 0; op = tagop->u.gen2.u.readData; ret = TMR_SR_cmdGEN2ReadTagData(reader, (uint16_t)(sr->commandTimeout), op.bank, op.wordAddress, op.len, sr->gen2AccessPassword, filter, &read); if (NULL != data) { data->len = read.data.len; } return ret; } case (TMR_TAGOP_GEN2_BLOCKWRITE): { TMR_TagOp_GEN2_BlockWrite op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.blockWrite; return TMR_SR_cmdBlockWrite(reader,(uint16_t)sr->commandTimeout, op.bank, op.wordPtr, op.data.len, op.data.list, sr->gen2AccessPassword, filter); } case (TMR_TAGOP_GEN2_BLOCKPERMALOCK): { TMR_TagOp_GEN2_BlockPermaLock op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.blockPermaLock; return TMR_SR_cmdBlockPermaLock(reader, (uint16_t)sr->commandTimeout, op.readLock, op.bank, op.blockPtr, op.mask.len, op.mask.list, sr->gen2AccessPassword, filter, data); } case (TMR_TAGOP_GEN2_BLOCKERASE): { TMR_TagOp_GEN2_BlockErase op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.blockErase; return TMR_SR_cmdBlockErase(reader, (uint16_t)sr->commandTimeout, op.bank, op.wordPtr, op.wordCount, sr->gen2AccessPassword, filter); } #ifdef TMR_ENABLE_GEN2_CUSTOM_TAGOPS case (TMR_TAGOP_GEN2_ALIEN_HIGGS2_PARTIALLOADIMAGE): { TMR_TagOp_GEN2_Alien_Higgs2_PartialLoadImage op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.alien.u.higgs2.u.partialLoadImage; if (op.epcptr->epcByteCount > 12 || op.epcptr->epcByteCount <=0 ) { /* Only 96 bit epc */ return TMR_ERROR_PROTOCOL_INVALID_EPC; } return TMR_SR_cmdHiggs2PartialLoadImage(reader, (uint16_t)sr->commandTimeout, op.accessPassword, op.killPassword, op.epcptr->epcByteCount, op.epcptr->epc, filter); } case (TMR_TAGOP_GEN2_ALIEN_HIGGS2_FULLLOADIMAGE): { TMR_TagOp_GEN2_Alien_Higgs2_FullLoadImage op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.alien.u.higgs2.u.fullLoadImage; if (op.epcptr->epcByteCount > 12 || op.epcptr->epcByteCount <= 0 ) { /* Only 96 bit epc */ return TMR_ERROR_PROTOCOL_INVALID_EPC; } return TMR_SR_cmdHiggs2FullLoadImage(reader, (uint16_t)sr->commandTimeout, op.accessPassword, op.killPassword, op.lockBits, op.pcWord, op.epcptr->epcByteCount, op.epcptr->epc, filter); } case (TMR_TAGOP_GEN2_ALIEN_HIGGS3_FASTLOADIMAGE): { /* The FastLoadImage command automatically erases the content of all * User Memory. If this is undesirable then use the LoadImage or multiple Write * Tag Data commands. */ TMR_TagOp_GEN2_Alien_Higgs3_FastLoadImage op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.alien.u.higgs3.u.fastLoadImage; if (op.epcptr->epcByteCount > 12 || op.epcptr->epcByteCount <= 0 ) { /* Only 96 bit epc */ return TMR_ERROR_PROTOCOL_INVALID_EPC; } return TMR_SR_cmdHiggs3FastLoadImage(reader, (uint16_t)sr->commandTimeout, op.currentAccessPassword, op.accessPassword, op.killPassword, op.pcWord, op.epcptr->epcByteCount, op.epcptr->epc, filter); } case (TMR_TAGOP_GEN2_ALIEN_HIGGS3_LOADIMAGE): { TMR_TagOp_GEN2_Alien_Higgs3_LoadImage op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.alien.u.higgs3.u.loadImage; if (op.epcAndUserData->len > 76 || op.epcAndUserData->len <= 0 ) { /* Only 76 byte epcAndUserData */ return TMR_ERROR_MSG_INVALID_PARAMETER_VALUE; } return TMR_SR_cmdHiggs3LoadImage(reader, (uint16_t)sr->commandTimeout, op.currentAccessPassword, op.accessPassword, op.killPassword, op.pcWord, (uint8_t)op.epcAndUserData->len, op.epcAndUserData->list, filter); } case (TMR_TAGOP_GEN2_ALIEN_HIGGS3_BLOCKREADLOCK): { TMR_TagOp_GEN2_Alien_Higgs3_BlockReadLock op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.alien.u.higgs3.u.blockReadLock; return TMR_SR_cmdHiggs3BlockReadLock(reader, (uint16_t)sr->commandTimeout, op.accessPassword, op.lockBits, filter); } case (TMR_TAGOP_GEN2_NXP_SETREADPROTECT): { TMR_TagOp_GEN2_NXP_SetReadProtect op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.nxp.u.setReadProtect; return TMR_SR_cmdNxpSetReadProtect(reader, (uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, op.accessPassword, filter); } case (TMR_TAGOP_GEN2_NXP_RESETREADPROTECT): { TMR_TagOp_GEN2_NXP_ResetReadProtect op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.nxp.u.resetReadProtect; return TMR_SR_cmdNxpResetReadProtect(reader, (uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, op.accessPassword, filter); } case (TMR_TAGOP_GEN2_NXP_CHANGEEAS): { TMR_TagOp_GEN2_NXP_ChangeEAS op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.nxp.u.changeEAS; return TMR_SR_cmdNxpChangeEas(reader, (uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, op.accessPassword, op.reset, filter); } case (TMR_TAGOP_GEN2_NXP_EASALARM): { TMR_TagOp_GEN2_NXP_EASAlarm op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.nxp.u.EASAlarm; return TMR_SR_cmdNxpEasAlarm(reader, (uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, op.dr, op.m, op.trExt, data, filter); } case (TMR_TAGOP_GEN2_NXP_CALIBRATE): { TMR_TagOp_GEN2_NXP_Calibrate op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.nxp.u.calibrate; return TMR_SR_cmdNxpCalibrate(reader, (uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, op.accessPassword, data, filter); } case (TMR_TAGOP_GEN2_NXP_CHANGECONFIG): { TMR_TagOp_GEN2_NXP_ChangeConfig op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.nxp.u.changeConfig; return TMR_SR_cmdNxpChangeConfig(reader, (uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, op.accessPassword, op.configWord, data, filter); } case (TMR_TAGOP_GEN2_NXP_UNTRACEABLE): { TMR_TagOp_GEN2_NXP_Untraceable op; uint16_t configWord; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.nxp.u.untraceable; configWord = TMR_SR_getConfigWord(reader,op); return TMR_SR_cmdGen2v2NXPUntraceable(reader,(uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, sr->gen2AccessPassword, configWord , op, data, filter); } case (TMR_TAGOP_GEN2_NXP_AUTHENTICATE): { TMR_TagOp_GEN2_NXP_Authenticate op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.nxp.u.authenticate; return TMR_SR_cmdGen2v2NXPAuthenticate(reader,(uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, sr->gen2AccessPassword, op, data, filter); } case (TMR_TAGOP_GEN2_NXP_READBUFFER): { TMR_TagOp_GEN2_NXP_Readbuffer op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.gen2.u.custom.u.nxp.u.readBuffer; return TMR_SR_cmdGen2v2NXPReadBuffer(reader,(uint16_t)sr->commandTimeout, tagop->u.gen2.u.custom.chipType, sr->gen2AccessPassword, op, data, filter); } case (TMR_TAGOP_GEN2_IMPINJ_MONZA4_QTREADWRITE): { TMR_TagOp_GEN2_Impinj_Monza4_QTReadWrite op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.impinj.u.monza4.u.qtReadWrite; return TMR_SR_cmdMonza4QTReadWrite(reader, (uint16_t)sr->commandTimeout, op.accessPassword, op.controlByte, op.payload, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_GETSENSOR): { TMR_TagOp_GEN2_IDS_SL900A_GetSensorValue op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.sensor; return TMR_SR_cmdSL900aGetSensorValue(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password,op.sl900A.level, op.sl900A.sensortype, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_GETMEASUREMENTSETUP): { TMR_TagOp_GEN2_IDS_SL900A_GetMeasurementSetup op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.measurementSetup; return TMR_SR_cmdSL900aGetMeasurementSetup(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password,op.sl900A.level, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_GETCALIBRATIONDATA): { TMR_TagOp_GEN2_IDS_SL900A_GetCalibrationData op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.calibrationData; return TMR_SR_cmdSL900aGetCalibrationData(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_SETCALIBRATIONDATA): { TMR_TagOp_GEN2_IDS_SL900A_SetCalibrationData op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.setCalibration; return TMR_SR_cmdSL900aSetCalibrationData(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, op.cal.raw, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_SETSFEPARAMETERS): { TMR_TagOp_GEN2_IDS_SL900A_SetSfeParameters op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.setSfeParameters; return TMR_SR_cmdSL900aSetSfeParameters(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, op.sfe->raw, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_GETLOGSTATE): { TMR_TagOp_GEN2_IDS_SL900A_GetLogState op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.getLog; return TMR_SR_cmdSL900aGetLogState(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_SETLOGMODE): { TMR_TagOp_GEN2_IDS_SL900A_SetLogMode op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.setLogMode; return TMR_SR_cmdSL900aSetLogMode(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, op.sl900A.dataLog, op.sl900A.rule, op.Ext1Enable, op.Ext2Enable, op.TempEnable, op.BattEnable, op.LogInterval, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_INITIALIZE): { TMR_TagOp_GEN2_IDS_SL900A_Initialize op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.initialize; return TMR_SR_cmdSL900aInitialize(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, op.delayTime.raw, op.applicationData.raw, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_ENDLOG): { TMR_TagOp_GEN2_IDS_SL900A_EndLog op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.endLog; return TMR_SR_cmdSL900aEndLog(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password,op.sl900A.level, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_SETPASSWORD): { TMR_TagOp_GEN2_IDS_SL900A_SetPassword op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.setPassword; return TMR_SR_cmdSL900aSetPassword(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password,op.sl900A.level, op.NewPassword, op.NewPasswordLevel, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOSTATUS): { TMR_TagOp_GEN2_IDS_SL900A_AccessFifoStatus op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.accessFifoStatus; return TMR_SR_cmdSL900aAccessFifoStatus(reader, (uint16_t)sr->commandTimeout, op.status.AccessPassword, op.status.CommandCode, op.status.Password, op.status.sl900A.level, op.status.operation, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOREAD): { TMR_TagOp_GEN2_IDS_SL900A_AccessFifoRead op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.accessFifoRead; return TMR_SR_cmdSL900aAccessFifoRead(reader, (uint16_t)sr->commandTimeout, op.read.AccessPassword, op.read.CommandCode, op.read.Password, op.read.sl900A.level, op.read.operation,op.length, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOWRITE): { TMR_TagOp_GEN2_IDS_SL900A_AccessFifoWrite op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.accessFifoWrite; return TMR_SR_cmdSL900aAccessFifoWrite(reader, (uint16_t)sr->commandTimeout, op.write.AccessPassword, op.write.CommandCode, op.write.Password, op.write.sl900A.level, op.write.operation, op.payLoad, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_STARTLOG): { TMR_TagOp_GEN2_IDS_SL900A_StartLog op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.startLog; return TMR_SR_cmdSL900aStartLog(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, op.startTime, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_GETBATTERYLEVEL): { TMR_TagOp_GEN2_IDS_SL900A_GetBatteryLevel op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.batteryLevel; return TMR_SR_cmdSL900aGetBatteryLevel(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, op.batteryType, data, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_SETLOGLIMITS): { TMR_TagOp_GEN2_IDS_SL900A_SetLogLimits op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.setLogLimit; return TMR_SR_cmdSL900aSetLogLimit(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, op.limit.extremeLower, op.limit.lower, op.limit.upper, op.limit.extremeUpper, filter); } case (TMR_TAGOP_GEN2_IDS_SL900A_SETSHELFLIFE): { TMR_TagOp_GEN2_IDS_SL900A_SetShelfLife op; /* Set the protocol for tag operation */ ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } /* Do some error checking */ if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.ids.u.setShelfLife; return TMR_SR_cmdSL900aSetShelfLife(reader, (uint16_t)sr->commandTimeout, op.AccessPassword, op.CommandCode, op.Password, op.sl900A.level, op.shelfLifeBlock0->raw, op.shelfLifeBlock1->raw, filter); } case (TMR_TAGOP_GEN2_DENATRAN_IAV_ACTIVATESECUREMODE): { TMR_TagOp_GEN2_Denatran_IAV_Activate_Secure_Mode op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.secureMode; return TMR_SR_cmdIAVDenatranCustomOp(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter); } case (TMR_TAGOP_GEN2_DENATRAN_IAV_AUTHENTICATEOBU): { TMR_TagOp_GEN2_Denatran_IAV_Authenticate_OBU op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.authenticateOBU; return TMR_SR_cmdIAVDenatranCustomOp(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter); } case (TMR_TAGOP_GEN2_ACTIVATE_SINIAV_MODE): { TMR_TagOp_GEN2_Denatran_IAV_Activate_Siniav_Mode op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.activateSiniavMode; return TMR_SR_cmdIAVDenatranCustomActivateSiniavMode(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter, op.isTokenDesc, op.token); } case (TMR_TAGOP_GEN2_OBU_AUTH_ID): { TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_ID op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthId; return TMR_SR_cmdIAVDenatranCustomOp(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter); } case (TMR_TAGOP_GEN2_AUTHENTICATE_OBU_FULL_PASS1): { TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass1 op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass1; return TMR_SR_cmdIAVDenatranCustomOp(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter); } case (TMR_TAGOP_GEN2_AUTHENTICATE_OBU_FULL_PASS2): { TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass2 op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass2; return TMR_SR_cmdIAVDenatranCustomOp(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter); } case (TMR_TAGOP_GEN2_OBU_READ_FROM_MEM_MAP): { TMR_TagOp_GEN2_Denatran_IAV_OBU_ReadFromMemMap op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.obuReadFromMemMap; return TMR_SR_cmdIAVDenatranCustomReadFromMemMap(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter, op.readPtr); } case (TMR_TAGOP_GEN2_DENATRAN_IAV_READ_SEC): { TMR_TagOp_GEN2_Denatran_IAV_Read_Sec op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.readSec; return TMR_SR_cmdIAVDenatranCustomReadSec(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter, op.readPtr); } case (TMR_TAGOP_GEN2_OBU_WRITE_TO_MEM_MAP): { TMR_TagOp_GEN2_Denatran_IAV_OBU_WriteToMemMap op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.obuWriteToMemMap; return TMR_SR_cmdIAVDenatranCustomWriteToMemMap(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter, op.writePtr, op.wordData,op.tagIdentification, op.dataBuf); } case (TMR_TAGOP_GEN2_DENATRAN_IAV_WRITE_SEC): { TMR_TagOp_GEN2_Denatran_IAV_Write_Sec op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.writeSec; return TMR_SR_cmdIAVDenatranCustomWriteSec(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter, op.dataWords, op.dataBuf); } case (TMR_TAGOP_GEN2_DENATRAN_IAV_GET_TOKEN_ID): { TMR_TagOp_GEN2_Denatran_IAV_Get_Token_Id op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if ( TMR_SUCCESS != ret) { return ret; } if (NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.getTokenId; return TMR_SR_cmdIAVDenatranCustomGetTokenId(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, data, filter); } case (TMR_TAGOP_GEN2_DENATRAN_IAV_AUTHENTICATE_OBU_FULL_PASS): { TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass; return TMR_SR_cmdIAVDenatranCustomOp(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter); } case (TMR_TAGOP_GEN2_DENATRAN_IAV_G0_PA_OBU_AUTHENTICATE_ID): { TMR_TagOp_GEN2_Denatran_IAV_G0_PA_OBU_Auth_ID op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_GEN2); if (TMR_SUCCESS != ret) { return ret; } if(NULL != data) { data->len = 0; } op = tagop->u.gen2.u.custom.u.IavDenatran.u.g0paobuauthid; return TMR_SR_cmdIAVDenatranCustomOp(reader, (uint16_t)sr->commandTimeout, sr->gen2AccessPassword, op.mode, op.payload, data, filter); } #endif /* TMR_ENABLE_GEN2_CUSTOM_TAGOPS */ #ifdef TMR_ENABLE_ISO180006B case (TMR_TAGOP_ISO180006B_READDATA): { TMR_TagOp_ISO180006B_ReadData op; TMR_TagReadData read; ret = setProtocol(reader, TMR_TAG_PROTOCOL_ISO180006B); if (TMR_SUCCESS != ret) { return ret; } if (NULL != data) { read.data.max = data->max; read.data.len = 0; read.data.list = data->list; } else { read.data.list = NULL; } read.metadataFlags = 0; op = tagop->u.iso180006b.u.readData; ret = TMR_SR_cmdISO180006BReadTagData(reader, (uint16_t)sr->commandTimeout, op.byteAddress, op.len, filter, &read); if (NULL != data) { data->len = read.data.len; } return ret; } case (TMR_TAGOP_ISO180006B_WRITEDATA): { TMR_TagOp_ISO180006B_WriteData op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_ISO180006B); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.iso180006b.u.writeData; return TMR_SR_cmdISO180006BWriteTagData(reader, (uint16_t)(sr->commandTimeout), op.byteAddress, (uint8_t)op.data.len, op.data.list, filter); } case (TMR_TAGOP_ISO180006B_LOCK): { TMR_TagOp_ISO180006B_Lock op; ret = setProtocol(reader, TMR_TAG_PROTOCOL_ISO180006B); if (TMR_SUCCESS != ret) { return ret; } op = tagop->u.iso180006b.u.lock; return TMR_SR_cmdISO180006BLockTag(reader, (uint16_t)(sr->commandTimeout), op.address, filter); } #endif /* TMR_ENABLE_ISO180006B */ default: { return TMR_ERROR_UNIMPLEMENTED_FEATURE; } } } /** * Internal method used for adding the tagop **/ TMR_Status TMR_SR_addTagOp(struct TMR_Reader *reader, TMR_TagOp *tagop,TMR_ReadPlan *rp, uint8_t *msg, uint8_t *j, uint32_t readTimeMs, uint8_t *byte ) { TMR_Status ret = TMR_SUCCESS; TMR_SR_SerialReader *sr; uint8_t i, lenbyte; i = *j; lenbyte = *byte; sr = &reader->u.serialReader; switch (tagop->type) { case (TMR_TAGOP_GEN2_WRITETAG): { TMR_TagOp_GEN2_WriteTag *args; args = &rp->u.simple.tagop->u.gen2.u.writeTag; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddGEN2WriteTagEPC(msg,&i, 0, args->epcptr->epc, args->epcptr->epcByteCount); break; } case TMR_TAGOP_GEN2_READDATA: { TMR_TagOp_GEN2_ReadData *args; args = &rp->u.simple.tagop->u.gen2.u.readData; /** * If user wants to read all the memory bank data, * In that case args.bank value should be greater than 3 **/ if ((uint8_t)args->bank > 3) { /* enable the gen2AllMemoryBankEnabled option */ sr->gen2AllMemoryBankEnabled = true; } prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddGEN2DataRead(msg, &i, 2000, args->bank, args->wordAddress, args->len, 0x00, false); break; } case TMR_TAGOP_GEN2_SECURE_READDATA: { TMR_TagOp_GEN2_SecureReadData *args; uint8_t accessPassword[4]; int index = 0; /* Enable the Secure ReadData option */ isSecureAccessEnabled = true; args = &rp->u.simple.tagop->u.gen2.u.secureReadData; if (args->passwordType == TMR_SECURE_GEN2_LOOKUP_TABLE_PASSWORD) { /* Do this in case of look up table */ accessPassword[index++] = args->password.secureAddressLength; accessPassword[index++] = args->password.secureAddressOffset; accessPassword[index++] = (args->password.secureFlashOffset >> 8); accessPassword[index++] = (args->password.secureFlashOffset & 0xFF); sr->gen2AccessPassword = (uint32_t)accessPassword[0] << 24 | (uint32_t)accessPassword[1] << 16 | (uint32_t)accessPassword[2] << 8 | (uint32_t)accessPassword[3]; } else { /* Do this in case of Gen2 password */ sr->gen2AccessPassword = args->password.gen2PassWord.u.gen2Password; } prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND | TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddGEN2DataRead(msg, &i, 2000, args->readData.bank, args->readData.wordAddress, args->readData.len,args->type, false); isSecureAccessEnabled = false; break; } case TMR_TAGOP_GEN2_WRITEDATA: { TMR_TagOp_GEN2_WriteData *args; int idx ; args = &rp->u.simple.tagop->u.gen2.u.writeData; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddGEN2DataWrite(msg, &i, 0, args->bank, args->wordAddress); for(idx = 0 ; idx< args->data.len; idx++) { msg[i++]= (args->data.list[idx]>>8) & 0xFF; msg[i++]= (args->data.list[idx]>>0) & 0xFF; } break; } case TMR_TAGOP_GEN2_LOCK: { TMR_TagOp_GEN2_Lock *args; args = &rp->u.simple.tagop->u.gen2.u.lock; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->accessPassword, &lenbyte); TMR_SR_msgAddGEN2LockTag(msg, &i, 0, args->mask, args->action, 0); break; } case TMR_TAGOP_GEN2_KILL: { TMR_TagOp_GEN2_Kill *args; args = &rp->u.simple.tagop->u.gen2.u.kill; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddGEN2KillTag(msg, &i, 0, args->password); break; } case TMR_TAGOP_GEN2_BLOCKWRITE: { TMR_TagOp_GEN2_BlockWrite *args; args = &rp->u.simple.tagop->u.gen2.u.blockWrite; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddGEN2BlockWrite(msg, &i, 0, args->bank, args->wordPtr, args->data.len, args->data.list, 0, NULL); break; } case TMR_TAGOP_GEN2_BLOCKPERMALOCK: { TMR_TagOp_GEN2_BlockPermaLock *args; args = &rp->u.simple.tagop->u.gen2.u.blockPermaLock; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddGEN2BlockPermaLock(msg, &i, 0,args->readLock, args->bank, args->blockPtr, args->mask.len, args->mask.list, 0, NULL); break; } case TMR_TAGOP_GEN2_BLOCKERASE: { TMR_TagOp_GEN2_BlockErase *args; args = &rp->u.simple.tagop->u.gen2.u.blockErase; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddGEN2BlockErase(msg, &i, 0, args->wordPtr, args->bank, args->wordCount, 0, NULL); break; } #ifdef TMR_ENABLE_GEN2_CUSTOM_TAGOPS case TMR_TAGOP_GEN2_ALIEN_HIGGS2_PARTIALLOADIMAGE: { TMR_TagOp_GEN2_Alien_Higgs2_PartialLoadImage *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.alien.u.higgs2.u.partialLoadImage; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddHiggs2PartialLoadImage(msg, &i, 0, args->accessPassword, args->killPassword, args->epcptr->epcByteCount, args->epcptr->epc, NULL); break; } case TMR_TAGOP_GEN2_ALIEN_HIGGS2_FULLLOADIMAGE: { TMR_TagOp_GEN2_Alien_Higgs2_FullLoadImage *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.alien.u.higgs2.u.fullLoadImage; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddHiggs2FullLoadImage(msg, &i, 0, args->accessPassword, args->killPassword, args->lockBits, args->pcWord, args->epcptr->epcByteCount, args->epcptr->epc, NULL); break; } case TMR_TAGOP_GEN2_ALIEN_HIGGS3_FASTLOADIMAGE: { TMR_TagOp_GEN2_Alien_Higgs3_FastLoadImage *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.alien.u.higgs3.u.fastLoadImage; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->currentAccessPassword, &lenbyte); TMR_SR_msgAddHiggs3FastLoadImage(msg, &i, 0, args->currentAccessPassword, args->accessPassword, args->killPassword, args->pcWord, args->epcptr->epcByteCount, args->epcptr->epc, NULL); break; } case TMR_TAGOP_GEN2_ALIEN_HIGGS3_LOADIMAGE: { TMR_TagOp_GEN2_Alien_Higgs3_LoadImage *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.alien.u.higgs3.u.loadImage; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->currentAccessPassword, &lenbyte); TMR_SR_msgAddHiggs3LoadImage(msg, &i, 0, args->currentAccessPassword, args->accessPassword, args->killPassword, args->pcWord, (uint8_t)args->epcAndUserData->len, args->epcAndUserData->list, NULL); break; } case TMR_TAGOP_GEN2_ALIEN_HIGGS3_BLOCKREADLOCK: { TMR_TagOp_GEN2_Alien_Higgs3_BlockReadLock *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.alien.u.higgs3.u.blockReadLock; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->accessPassword, &lenbyte); TMR_SR_msgAddHiggs3BlockReadLock(msg, &i, 0, args->accessPassword, args->lockBits, NULL); break; } case TMR_TAGOP_GEN2_NXP_SETREADPROTECT: { TMR_TagOp_GEN2_NXP_SetReadProtect *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.nxp.u.setReadProtect; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->accessPassword, &lenbyte); TMR_SR_msgAddNXPSetReadProtect(msg, &i, 0, rp->u.simple.tagop->u.gen2.u.custom.chipType, args->accessPassword, NULL); break; } case TMR_TAGOP_GEN2_NXP_RESETREADPROTECT: { TMR_TagOp_GEN2_NXP_ResetReadProtect *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.nxp.u.resetReadProtect; if (rp->u.simple.tagop->u.gen2.u.custom.chipType == TMR_SR_GEN2_NXP_G2X_SILICON) { /* NXP_G2XL_ResetReadProtect can not be embedded. * Throw un supported exception to the user */ return TMR_ERROR_UNSUPPORTED; } prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->accessPassword, &lenbyte); TMR_SR_msgAddNXPResetReadProtect(msg, &i, 0, rp->u.simple.tagop->u.gen2.u.custom.chipType, args->accessPassword, NULL); break; } case TMR_TAGOP_GEN2_NXP_CHANGEEAS: { TMR_TagOp_GEN2_NXP_ChangeEAS *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.nxp.u.changeEAS; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->accessPassword, &lenbyte); TMR_SR_msgAddNXPChangeEAS(msg, &i, 0, rp->u.simple.tagop->u.gen2.u.custom.chipType, args->accessPassword, args->reset, NULL); break; } case TMR_TAGOP_GEN2_NXP_EASALARM: { return TMR_ERROR_UNSUPPORTED; } case TMR_TAGOP_GEN2_NXP_CALIBRATE: { TMR_TagOp_GEN2_NXP_Calibrate *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.nxp.u.calibrate; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->accessPassword, &lenbyte); TMR_SR_msgAddNXPCalibrate(msg, &i, 0, rp->u.simple.tagop->u.gen2.u.custom.chipType, args->accessPassword, NULL); break; } case TMR_TAGOP_GEN2_NXP_CHANGECONFIG: { TMR_TagOp_GEN2_NXP_ChangeConfig *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.nxp.u.changeConfig; if (rp->u.simple.tagop->u.gen2.u.custom.chipType == TMR_SR_GEN2_NXP_G2X_SILICON) { /* Change Config is not supported for G2xL silicon*/ return TMR_ERROR_UNSUPPORTED; } prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->accessPassword, &lenbyte); TMR_SR_msgAddNXPChangeConfig(msg, &i, 0, rp->u.simple.tagop->u.gen2.u.custom.chipType, 0, args->configWord, NULL); break; } case TMR_TAGOP_GEN2_IMPINJ_MONZA4_QTREADWRITE: { TMR_TagOp_GEN2_Impinj_Monza4_QTReadWrite *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.impinj.u.monza4.u.qtReadWrite; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->accessPassword, &lenbyte); TMR_SR_msgAddMonza4QTReadWrite(msg, &i, 0, 0, args->controlByte, args->payload, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_GETSENSOR: { TMR_TagOp_GEN2_IDS_SL900A_GetSensorValue *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.sensor; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aGetSensorValue(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->sl900A.sensortype, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_GETMEASUREMENTSETUP: { TMR_TagOp_GEN2_IDS_SL900A_GetMeasurementSetup *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.measurementSetup; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aGetMeasurementSetup(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, NULL); } case TMR_TAGOP_GEN2_IDS_SL900A_GETLOGSTATE: { TMR_TagOp_GEN2_IDS_SL900A_GetLogState *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.getLog; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aGetLogState(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level,NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_SETLOGMODE: { TMR_TagOp_GEN2_IDS_SL900A_SetLogMode *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.setLogMode; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aSetLogMode(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->sl900A.dataLog, args->sl900A.rule, args->Ext1Enable, args->Ext2Enable, args->TempEnable, args->BattEnable, args->LogInterval, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_INITIALIZE: { TMR_TagOp_GEN2_IDS_SL900A_Initialize *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.initialize; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aInitialize(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->delayTime.raw, args->applicationData.raw, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_ENDLOG: { TMR_TagOp_GEN2_IDS_SL900A_EndLog *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.endLog; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aEndLog(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_SETPASSWORD: { TMR_TagOp_GEN2_IDS_SL900A_SetPassword *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.setPassword; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aSetPassword(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->NewPassword, args->NewPasswordLevel, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_STARTLOG: { TMR_TagOp_GEN2_IDS_SL900A_StartLog *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.startLog; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aStartLog(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->startTime, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOSTATUS: { TMR_TagOp_GEN2_IDS_SL900A_AccessFifoStatus *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.accessFifoStatus; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->status.AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aAccessFifoStatus(msg, &i, 0, 0, args->status.CommandCode, args->status.Password, args->status.sl900A.level, args->status.operation, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOREAD: { TMR_TagOp_GEN2_IDS_SL900A_AccessFifoRead *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.accessFifoRead; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->read.AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aAccessFifoRead(msg, &i, 0, 0, args->read.CommandCode, args->read.Password, args->read.sl900A.level, args->read.operation, args->length, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_ACCESSFIFOWRITE: { TMR_TagOp_GEN2_IDS_SL900A_AccessFifoWrite *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.accessFifoWrite; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->write.AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aAccessFifoWrite(msg, &i, 0, 0, args->write.CommandCode, args->write.Password, args->write.sl900A.level, args->write.operation, args->payLoad, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_GETCALIBRATIONDATA: { TMR_TagOp_GEN2_IDS_SL900A_GetCalibrationData *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.calibrationData; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aGetCalibrationData(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_SETCALIBRATIONDATA: { TMR_TagOp_GEN2_IDS_SL900A_SetCalibrationData *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.setCalibration; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aSetCalibrationData(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->cal.raw, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_SETSFEPARAMETERS: { TMR_TagOp_GEN2_IDS_SL900A_SetSfeParameters *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.setSfeParameters; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aSetSfeParameters(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->sfe->raw, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_GETBATTERYLEVEL: { TMR_TagOp_GEN2_IDS_SL900A_GetBatteryLevel *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.batteryLevel; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aGetBatteryLevel(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->batteryType, NULL); break; } case TMR_TAGOP_GEN2_IDS_SL900A_SETLOGLIMITS: { TMR_TagOp_GEN2_IDS_SL900A_SetLogLimits *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.ids.u.setLogLimit; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, args->AccessPassword, &lenbyte); TMR_SR_msgAddIdsSL900aSetLogLimit(msg, &i, 0, 0, args->CommandCode, args->Password, args->sl900A.level, args->limit.extremeLower, args->limit.lower, args->limit.upper, args->limit.extremeUpper, NULL); break; } case TMR_TAGOP_GEN2_DENATRAN_IAV_ACTIVATESECUREMODE: { TMR_TagOp_GEN2_Denatran_IAV_Activate_Secure_Mode *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.secureMode; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, 0, 0, args->mode, args->payload, NULL); break; } case TMR_TAGOP_GEN2_DENATRAN_IAV_AUTHENTICATEOBU: { TMR_TagOp_GEN2_Denatran_IAV_Authenticate_OBU *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.authenticateOBU; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, 0, 0, args->mode, args->payload, NULL); break; } case TMR_TAGOP_GEN2_ACTIVATE_SINIAV_MODE: { TMR_TagOp_GEN2_Denatran_IAV_Activate_Siniav_Mode *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.activateSiniavMode; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomActivateSiniavMode(msg, &i, 0, 0, args->mode, args->payload, NULL, args->isTokenDesc, args->token); break; } case TMR_TAGOP_GEN2_OBU_AUTH_ID: { TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_ID *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthId; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, 0, 0, args->mode, args->payload, NULL); break; } case TMR_TAGOP_GEN2_AUTHENTICATE_OBU_FULL_PASS1: { TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass1 *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass1; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, 0, 0, args->mode, args->payload, NULL); break; } case TMR_TAGOP_GEN2_AUTHENTICATE_OBU_FULL_PASS2: { TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass2 *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass2; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, 0, 0, args->mode, args->payload, NULL); break; } case TMR_TAGOP_GEN2_OBU_READ_FROM_MEM_MAP: { TMR_TagOp_GEN2_Denatran_IAV_OBU_ReadFromMemMap *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.obuReadFromMemMap; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomReadFromMemMap(msg, &i, 0, 0, args->mode, args->payload, NULL, args->readPtr); break; } case TMR_TAGOP_GEN2_DENATRAN_IAV_READ_SEC: { TMR_TagOp_GEN2_Denatran_IAV_Read_Sec *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.readSec; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomReadSec(msg, &i, 0, 0, args->mode, args->payload, NULL, args->readPtr); break; } case TMR_TAGOP_GEN2_OBU_WRITE_TO_MEM_MAP: { TMR_TagOp_GEN2_Denatran_IAV_OBU_WriteToMemMap *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.obuWriteToMemMap; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomWriteToMemMap(msg, &i, 0, 0, args->mode, args->payload, NULL, args->writePtr, args->wordData, args->tagIdentification, args->dataBuf); break; } case TMR_TAGOP_GEN2_DENATRAN_IAV_WRITE_SEC: { TMR_TagOp_GEN2_Denatran_IAV_Write_Sec *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.writeSec; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomWriteSec(msg, &i, 0, 0, args->mode, args->payload, NULL, args->dataWords, args->dataBuf); break; } case TMR_TAGOP_GEN2_DENATRAN_IAV_GET_TOKEN_ID: { TMR_TagOp_GEN2_Denatran_IAV_Get_Token_Id *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.getTokenId; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomGetTokenId(msg, &i, 0, 0, args->mode, NULL); break; } case TMR_TAGOP_GEN2_DENATRAN_IAV_AUTHENTICATE_OBU_FULL_PASS: { TMR_TagOp_GEN2_Denatran_IAV_OBU_Auth_Full_Pass *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.obuAuthFullPass; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, 0, 0, args->mode, args->payload, NULL); break; } case TMR_TAGOP_GEN2_DENATRAN_IAV_G0_PA_OBU_AUTHENTICATE_ID: { TMR_TagOp_GEN2_Denatran_IAV_G0_PA_OBU_Auth_ID *args; args = &rp->u.simple.tagop->u.gen2.u.custom.u.IavDenatran.u.g0paobuauthid; prepEmbReadTagMultiple(reader, msg, &i, (uint16_t)readTimeMs, (TMR_SR_SearchFlag)(TMR_SR_SEARCH_FLAG_CONFIGURED_LIST | TMR_SR_SEARCH_FLAG_EMBEDDED_COMMAND|TMR_SR_SEARCH_FLAG_LARGE_TAG_POPULATION_SUPPORT), rp->u.simple.filter, rp->u.simple.protocol, sr->gen2AccessPassword, &lenbyte); TMR_SR_msgAddIAVDenatranCustomOp(msg, &i, 0, 0, args->mode, args->payload, NULL); break; } #endif /* TMR_ENABLE_GEN2_CUSTOM_TAGOPS */ case TMR_TAGOP_LIST: return TMR_ERROR_UNIMPLEMENTED; /* Module doesn't implement these */ default: return TMR_ERROR_INVALID; /* Unknown tagop - internal error */ } *j = i; *byte = lenbyte; return ret; } /* Internal method used to update the base times stamp */ void TMR_SR_updateBaseTimeStamp(TMR_Reader *reader) { /* update the base time stamp to current host time */ uint32_t starttimeLow, starttimeHigh; starttimeHigh = 0; starttimeLow = 0; tm_gettime_consistent(&starttimeHigh, &starttimeLow); reader->u.serialReader.readTimeHigh = starttimeHigh; reader->u.serialReader.readTimeLow = starttimeLow; reader->u.serialReader.lastSentTagTimestampHigh = starttimeHigh; reader->u.serialReader.lastSentTagTimestampLow = starttimeLow; } #endif /* TMR_ENABLE_SERIAL_READER */